{"id":21428684,"url":"https://github.com/spikef/smart-koa-router","last_synced_at":"2025-07-19T14:32:43.455Z","repository":{"id":65478853,"uuid":"129221649","full_name":"Spikef/smart-koa-router","owner":"Spikef","description":"smart-koa-router是一个复合型的Koa路由处理模块，支持Restful API、静态文件、文件上传、模板渲染，自动解析body参数，支持允许跨域请求，支持API参数校验和自动生成文档，支持应用启动时拦截等功能。","archived":false,"fork":false,"pushed_at":"2018-05-30T09:14:23.000Z","size":1042,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-24T15:10:00.602Z","etag":null,"topics":["body-parser","koa","nodejs","router","static","swagger","upload"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Spikef.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-12T08:50:37.000Z","updated_at":"2020-07-07T16:16:11.000Z","dependencies_parsed_at":"2023-01-25T15:16:16.677Z","dependency_job_id":null,"html_url":"https://github.com/Spikef/smart-koa-router","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spikef%2Fsmart-koa-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spikef%2Fsmart-koa-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spikef%2Fsmart-koa-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spikef%2Fsmart-koa-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Spikef","download_url":"https://codeload.github.com/Spikef/smart-koa-router/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225970900,"owners_count":17553410,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["body-parser","koa","nodejs","router","static","swagger","upload"],"created_at":"2024-11-22T22:14:22.669Z","updated_at":"2024-11-22T22:14:23.257Z","avatar_url":"https://github.com/Spikef.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# smart-koa-router\n\n## 概述\n\n`smart-koa-router`是一个复合型的`Koa`路由处理模块，支持Restful API、静态文件、文件上传、模板渲染，自动解析body参数，支持允许跨域请求，支持API参数校验和自动生成文档，支持应用启动时拦截等功能。\n\n这是一个与`koa-router`在使用方式上接近，但是设计理念完全不同的`Koa`路由处理模块：不仅覆盖了web应用需要的所有场景，而且更加灵活方便，在性能上也比`koa-router`表现更为优异。\n\n## 如何使用\n\n`Router`是一个`class`，且使用了`async`和`await`，因此需要在`node v7.6+`环境中才能使用。\n\n### 实例化\n\n你可以根据需要多次实例化`Router`对象，每个实例化`router`对象使用不同的配置。\n\n```javascript\nvar Router = require('smart-koa-router');\nvar router = new Router();\n\nrouter.get('/index', function(ctx) {\n    ctx.body = 'Hello world!';\n});\n```\n\n所有的配置参数都是可选的，这时会使用默认值或者具体某个路由的设置。\n\n\u003e + **options.prefix:** 路由前缀，可通过[`router.prefix()`](#路由前缀)方法覆盖，默认为`/`\n\u003e + **options.methods:** 支持的methods，默认为['HEAD', 'OPTIONS', 'GET', 'PUT', 'PATCH', 'POST', 'DELETE']\n\u003e + **options.parseBody:** 默认情况下，对于`POST`、`PUT`和`PATCH`请求，会自动解析body，也可以自定义[解析body配置](#解析body配置)\n\u003e + **options.allowCross:** 是否允许跨域，默认为false，可以简单地设置为true来使用默认配置，也可以自定义[跨域配置](#跨域配置)\n\u003e + **options.staticFile:** 默认的[静态文件资源配置](#静态文件资源配置)\n\u003e + **options.uploadFile:** 默认的[文件上传配置](#文件上传配置)\n\u003e + **options.renderFile:** 默认的[模板渲染配置](#模板渲染配置)\n\u003e + **options.swagger:** 默认的[Swagger文档配置](#swagger文档配置)\n\u003e + **options.validator:** [参数校验配置](#参数校验配置)，默认为true，可以简单地设置为false来禁用参数校验\n\u003e + **options.document:** swagger文档基础配置，具体可以参考[OpenAPI Specification](#https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md)\n\n### 使用路由\n\n路由的实例化虽然是多次的，但是路由的使用却只需要一次。\n\n```javascript\nvar koa = require('koa');\nvar Router = require('smart-koa-router');\n\napp.use(router.routes());\n\napp.listen(8444, '0.0.0.0', function() {\n    console.log('http://localhost:8444');\n});\n```\n\n## API\n\n### router.use(methods, path, opts, ...middleware)\n\n定义一个路由拦截行为，统一拦截请求进入时的操作。\n\n```javascript\nrouter.use(['POST', 'PUT', 'PATCH', 'DELETE'], async function authorizeMiddleware(ctx, next) {\n    // 所有的增删改操作都要进入权限认证\n    await next();\n});\n```\n\n**参数**\n\n+ methods: String|String[]，接收的request method，如果省略则接收所有的默认允许的methods\n+ path: String|RegExp，接收的request path，如果省略则等同于'*'，如果为字符串则表示支持参数\n\n  为了支持swagger的path参数格式，在解析参数时使用了[open-path](http://npmjs.com/open-path)模块来代替`path-to-regexp`\n+ opts: 路由配置，与[实例化](#实例化)时的参数配置相同，该参数可以省略，也可以写在middleware的后面\n+ middleware: 一个或多个路由处理中间件\n\n### router.param([path], param, middleware)\n\n对指定路径参数作统一拦截，属于router.use()方法的语法糖。\n\n```javascript\nrouter\n    .param('user', (id, ctx, next) =\u003e {\n        ctx.user = users[id];\n        if (!ctx.user) return ctx.status = 404;\n        return next();\n    })\n    .get('/users/:user', ctx =\u003e {\n        ctx.body = ctx.user;\n    })\n    .get('/users/:user/friends', async (ctx) =\u003e {\n        var friends = await ctx.user.getFriends();\n        ctx.body = friends;\n    });\n    // /users/3 =\u003e {\"id\": 3, \"name\": \"Alex\"}\n    // /users/3/friends =\u003e [{\"id\": 4, \"name\": \"TJ\"}]\n```\n\n### router.prefix(prefix)\n\n定义路由前缀，在此之后定义的路由，只要`path`是以`./`开头的，都会自动加上此前缀。\n\n### router.any(methods, path, opts, ...middleware)\n\n不同于路由拦截，路由定义最多只会命中一个定义的路由，且后定义的路由将覆盖先定义的路由。\n\n**参数**\n\n相比于通用配置，多了一个`opts.annotations`配置，用于描述该路由和校验请求参数，声明方式请参考[operation-object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#operation-object)。\n\n另外还有一个`opts.routeOptions`配置，供中间件调用。\n\n### router.get(path, opts, ...middleware)\n\n定义一个`get`请求，同时会定义一个`head`请求，如果需要自定义`head`请求，只需要手动定义一个`head`请求覆盖掉即可。\n\n### router.post(path, opts, ...middleware)\n\n定义一个`post`请求。\n\n### router.put(path, opts, ...middleware)\n\n定义一个`put`请求。\n\n### router.patch(path, opts, ...middleware)\n\n定义一个`patch`请求。\n\n### router.delete(path, opts, ...middleware)\n\n定义一个`delete`请求。\n\n### router.head(path, opts, ...middleware)\n\n定义一个`head`请求。\n\n### router.options(path, opts, ...middleware)\n\n定义一个`options`请求。\n\n### router.static(methods, path, opts, ...middleware)\n\n通过定制的[koa-send](https://github.com/koajs/send)模块，满足提供静态文件服务的需求。\n\n```javascript\n// 单个文件\nrouter.static('/index.html', {\n    staticFile: {\n        filename: 'index.html',\n        root: __dirname\n    }\n});\n\n// 整个目录\nrouter.static('/assets', {\n    staticFile: {\n        root: __dirname,\n        include: /(css|js|html)$/i\n    }\n});\n```\n\n**参数**\n\n除了methods的默认值为GET外，其余参数无区别。\n\n### router.render(methods, path, opts, ...middleware)\n\n用于提供根据模板渲染页面的能力。\n\n```javascript\nrouter.render(docUrl, {\n   renderFile: {\n       template: path.resolve(__dirname, 'swagger-ui/index.ejs'),\n       data: Object.assign({\n           home: '/',\n           title: 'Swagger UI',\n           pageTitle: 'Swagger',\n           url: '/api-docs',\n           auth: null\n       }, options.swaggerUi)\n   }\n});\n```\n\n**参数**\n\n除了methods的默认值为GET外，其余参数无区别。\n\n**自定义Engine**\n\n请参考[/src/render/engine/ejs-engine.js](/src/render/engine/ejs-engine.js)。\n\n### router.upload(methods, path, opts, ...middleware)\n\n通过定制的[busboy](https://github.com/mscdex/busboy)模块，满足文件上传的需求。并实现了`FileStorage`和`MemoryStorage`来接收处理文件，还支持自定义`Storage`。\n\n```javascript\nrouter.upload('./upload', {\n    uploadFile: {\n        root: path.resolve(__dirname, 'uploads'),\n        allowedFileExts: 'js,png'\n    }\n}, async (ctx, next) =\u003e {\n    console.log(ctx.req.body);      // 除type=file外的其它fields\n    console.log(ctx.req.files);     // 由Storage返回的文件对象\n    console.log(ctx.request.body);  // 等价于 ctx.req.body\n    console.log(ctx.request.files); // 等价于 ctx.req.files\n    ctx.body = '上传成功!';\n});\n```\n\n**参数**\n\n除了methods的默认值为POST外，其余参数无区别。\n\n**自定义Storage**\n\n请参考[/src/upload/storage/file.js](/src/upload/storage/file.js)。\n\n### router.redirect(source, target, code)\n\n路由跳转。\n\n**参数**\n\n+ source: 访问路径\n+ target: 目标位置\n+ code: 状态码，默认为301\n\n### router.beforeStart(callback)\n\n在服务启动之前的通用拦截操作，此时会执行传入的callback。\n\n**参数**\n\n+ callback: Function，待执行的回调函数，入参为已定义的所有routes对象数组。\n\n## ctx\n\n路由在处理过程中会往`koa`的`ctx`对象上塞入一些变量。\n\n#### ctx.route\n\n当前命中路由的实例对象。\n\n### ctx.router\n\n当前的实例化router对象。\n\n### ctx.routeOptions\n\n从路由定义时传入的额外配置参数(opts.routeOptions)，主要是为了在拦截阶段可以根据路由定义的不同routeOptions来分别处理。\n\n### ctx.params\n\n定义在path上的参数解析之后的对象。\n\n### ctx.req.body和ctx.request.body\n\n解析之后得到的body参数。\n\n### ctx.req.files和ctx.request.files\n\n解析之后得到的文件上传对象。\n\n### ctx.req.formData和ctx.request.formData\n\n解析`multipart/form-data`时得到的内容，即`body` + `files`。\n\n## 路由配置\n\n### 解析body配置\n\n\u003e + **parseBody.encoding:** String，字符编码，默认为'utf8'\n\u003e + **parseBody.jsonLimit：** Array，`Content-Type`为`application/json`时的body大小，默认不超过2MB\n\u003e + **parseBody.formLimit：** Array，`Content-Type`为`application/x-www-form-urlencoded`时的body大小，默认不超过56KB\n\u003e + **parseBody.jsonFormats：** Array，`Content-Type`的值，默认为['application/json']\n\u003e + **parseBody.formFormats：** Array，`Content-Type`的值，默认为['application/x-www-form-urlencoded']\n\u003e + **parseBody.onerror：** Function，解析错误处理回调函数，传入参数为一个错误对象，`this`将指向`Koa`的`context`。如果不指定，则将返回400状态。\n\n### 跨域配置\n\n\u003e + **allowCross.origin:** 设置`Access-Control-Allow-Origin`头，值可以是以下类型：\n\u003e   **Boolean** - 为`true`时设置为请求头的`Origin`字段，为`false`时将禁用跨域。\n\u003e   **String** - 设置为指定值。例如指定为`http://example.com`时，只有从`http://example.com`发起的请求才能跨域。\n\u003e   **RegExp** - 当请求头的`Origin`字段匹配时才能跨域。例如指定为`/example\\.com$/`时，所有以`example.com`结尾的网站发过来的跨域请求都将被允许。\n\u003e   **Array** - 允许列表中的多个网站跨域。\n\u003e   **Function** - 自定义是否允许跨域。第一个参数为请求头的`Origin`字段，第二个参数为一个回调处理函数(回调的第一个参数为err [object]，第二个参数为allow [bool])。\n\u003e + **allowCross.methods:** 设置`Access-Control-Allow-Methods`头，值可以是个数组(如: ['GET', 'PUT', 'POST'])或者以英文逗号分隔的字符串(如: 'GET,PUT,POST')。\n\u003e + **allowCross.allowedHeaders:** 设置`Access-Control-Allow-Headers`头，值可以是个数组(如: ['Content-Type', 'Authorization'])或者以英文逗号分隔的字符串(如: 'Content-Type,Authorization')。如果未指定该设置，那么将自动使用请求头的`Access-Control-Request-Headers`字段。\n\u003e + **allowCross.exposedHeaders:** 设置`Access-Control-Expose-Headers`头，值可以是个数组(如: ['Content-Range', 'X-Content-Range'])或者以英文逗号分隔的字符串(如: 'Content-Range,X-Content-Range')。\n\u003e + **allowCross.credentials:** 设置`Access-Control-Allow-Credentials`头，值为true或false(默认为false)。当需要允许跨域传cookie时，需要设置为true。\n\u003e + **allowCross.maxAge:** String，设置`Access-Control-Max-Age`头。\n\u003e + **allowCross.optionsSuccessStatus:** String，设置`OPTIONS`请求时返回的状态码，默认为204(No Content)。\n\n### 静态文件资源配置\n\n\u003e + **staticFile.maxAge:** 设置浏览器最大缓存时间(毫秒)，默认为0。\n\u003e + **staticFile.immutable:** 设置资源是否不会变更，可以永久缓存，默认为false。\n\u003e + **staticFile.hidden:** 设置是否允许输出隐藏文件，默认为false。\n\u003e + **staticFile.root:** 设置资源文件所在的根目录，必需指定。\n\u003e + **staticFile.index:** 设置目录下的默认页，如果设置该值，则当用户直接访问该目录时，会自动跳转到默认页。\n\u003e + **staticFile.gzip:** 设置是否自动使用gzip压缩文件(.gz)，默认为true。\n\u003e + **staticFile.brotli:** 设置是否自动使用brotli压缩文件(.br)，默认为true。\n\u003e + **staticFile.setHeaders:** 设置自定义响应头`Cache-Control`或`Last-Modified`，该方法接受`res, path, stats`三个参数。\n\u003e + **staticFile.extensions:** Array，设置自动补全的文件扩展名，默认为false。\n\u003e + **staticFile.filename:** 设置静态文件对应的文件名，当为目录时不需要指定该配置。\n\u003e + **staticFile.filter:** Function，接收请求的filename，返回true时才能访问该静态资源文件，默认无限制。\n\u003e + **staticFile.include:** RegExp，限制允许访问的静态资源文件，当设置了`filter`时该选项将被忽略。\n\u003e + **staticFile.exclude:** RegExp，限制不允许访问的静态资源文件，当设置了`filter`时该选项将被忽略。\n\u003e + **staticFile.converter:** Function，接收请求的filename，返回对应的本地文件的filename。\n\u003e + **staticFile.mapList:** key/value，设置请求的filename到本地文件的映射关系，当设置了`converter`时该选项将被忽略。\n\u003e + **staticFile.onerror:** Function，错误处理回调函数，传入参数为一个错误对象，`this`将指向`Koa`的`context`。如果不指定，则将直接抛出该错误。\n\n\n### 文件上传配置\n\n\u003e + **uploadFile.storage:** Class，上传文件处理类。当指定了`uploadFile.root`时，将使用`FileStorage`保存为本地文件，否则使用`MemoryStorage`保存到内存\n\u003e + **uploadFile.allowedFileExts:** String|Array，允许的上传文件名后缀，默认为*\n\u003e + **uploadFile.allowedFileNames:** String|Array，允许的上传文件名(即input的name属性)，默认为*\n\u003e + **uploadFile.root:** String，文件保存的根目录(绝对路径)\n\u003e + **uploadFile.mode:** Number，文件保存目录的权限，默认为0777\n\u003e + **uploadFile.multiple:** Boolean，是否允许多文件上传(即input的multiple属性)，默认为false\n\u003e + **uploadFile.fieldNameSize:** Number，允许的字段名总大小，默认为100B\n\u003e + **uploadFile.fieldValueSize:** Number，允许的字段值总大小，默认为1M\n\u003e + **uploadFile.fieldsCount:** Number，允许的字段总个数，默认不限制\n\u003e + **uploadFile.fileSize:** Number，允许的字段总个数，默认不限制\n\u003e + **uploadFile.fieldsCount:** Number，允许的字段总个数，默认不限制\n\u003e + **uploadFile.fieldsCount:** Number，允许的字段总个数，默认不限制\n\u003e + **uploadFile.fileSize:** Number，允许的单个文件大小(单位为Byte)，默认10240(即10MB)\n\u003e + **uploadFile.filesCount** Number，允许上传的文件个数，默认不限制\n\u003e + **uploadFile.partsCount** Number，允许的字段+文件总个数，默认不限制\n\u003e + **uploadFile.onerror** Function，上传出错时的处理方式，如果不指定则将直接返回500状态\n\n### 模板渲染配置\n\n\u003e + **renderFile.engine:** Class，模板渲染类。默认为ejs\n\u003e + **renderFile.data** Object，传入用于模板渲染的额外数据\n\u003e + **renderFile.template** String，模板文件的绝对路径\n\u003e + **renderFile.onerror** Function，渲染出错时的处理方式，如果不指定则将直接返回500状态\n\n### Swagger文档配置\n\n\u003e + **swagger.docApi:** String，api文档接口地址，默认为\"/api-docs\"\n\u003e + **swagger.docUrl:** String，swagger页面地址，默认为\"/swagger-ui.html\"\n\u003e + **swagger.swaggerUi:** Object，swagger-ui的相关配置\n\u003e + **swagger.swaggerUi.home:** String，首页地址，默认为\"/\"\n\u003e + **swagger.swaggerUi.title:** String，title标签内容\n\u003e + **swagger.swaggerUi.pageTitle:** String，页面上显示的标题内容\n\u003e + **swagger.swaggerUi.url:** String，api文档接口地址，默认为\"/api-docs\"\n\u003e + **swagger.swaggerUi.auth:** Object，auth配置\n\n### 参数校验配置\n\n\u003e + **validator.onerror** Function，校验不匹配时的处理方式，如果不指定则将直接返回400状态\n\n## 示例\n\n更多使用示例请查看[examples](/examples)目录。\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspikef%2Fsmart-koa-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspikef%2Fsmart-koa-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspikef%2Fsmart-koa-router/lists"}