smart-koa-router
是一个复合型的Koa
路由处理模块,支持Restful API、静态文件、文件上传、模板渲染,自动解析body参数,支持允许跨域请求,支持API参数校验和自动生成文档,支持应用启动时拦截等功能。
这是一个与koa-router
在使用方式上接近,但是设计理念完全不同的Koa
路由处理模块:不仅覆盖了web应用需要的所有场景,而且更加灵活方便,在性能上也比koa-router
表现更为优异。
Router
是一个class
,且使用了async
和await
,因此需要在node v7.6+
环境中才能使用。
你可以根据需要多次实例化Router
对象,每个实例化router
对象使用不同的配置。
var Router = require('smart-koa-router');
var router = new Router();
router.get('/index', function(ctx) {
ctx.body = 'Hello world!';
});
所有的配置参数都是可选的,这时会使用默认值或者具体某个路由的设置。
- options.prefix: 路由前缀,可通过
router.prefix()
方法覆盖,默认为/
- options.methods: 支持的methods,默认为['HEAD', 'OPTIONS', 'GET', 'PUT', 'PATCH', 'POST', 'DELETE']
- options.parseBody: 默认情况下,对于
POST
、PUT
和PATCH
请求,会自动解析body,也可以自定义解析body配置- options.allowCross: 是否允许跨域,默认为false,可以简单地设置为true来使用默认配置,也可以自定义跨域配置
- options.staticFile: 默认的静态文件资源配置
- options.uploadFile: 默认的文件上传配置
- options.renderFile: 默认的模板渲染配置
- options.swagger: 默认的Swagger文档配置
- options.validator: 参数校验配置,默认为true,可以简单地设置为false来禁用参数校验
- options.document: swagger文档基础配置,具体可以参考OpenAPI Specification
路由的实例化虽然是多次的,但是路由的使用却只需要一次。
var koa = require('koa');
var Router = require('smart-koa-router');
app.use(router.routes());
app.listen(8444, '0.0.0.0', function() {
console.log('http://localhost:8444');
});
定义一个路由拦截行为,统一拦截请求进入时的操作。
router.use(['POST', 'PUT', 'PATCH', 'DELETE'], async function authorizeMiddleware(ctx, next) {
// 所有的增删改操作都要进入权限认证
await next();
});
参数
-
methods: String|String[],接收的request method,如果省略则接收所有的默认允许的methods
-
path: String|RegExp,接收的request path,如果省略则等同于'*',如果为字符串则表示支持参数
为了支持swagger的path参数格式,在解析参数时使用了open-path模块来代替
path-to-regexp
-
opts: 路由配置,与实例化时的参数配置相同,该参数可以省略,也可以写在middleware的后面
-
middleware: 一个或多个路由处理中间件
对指定路径参数作统一拦截,属于router.use()方法的语法糖。
router
.param('user', (id, ctx, next) => {
ctx.user = users[id];
if (!ctx.user) return ctx.status = 404;
return next();
})
.get('/users/:user', ctx => {
ctx.body = ctx.user;
})
.get('/users/:user/friends', async (ctx) => {
var friends = await ctx.user.getFriends();
ctx.body = friends;
});
// /users/3 => {"id": 3, "name": "Alex"}
// /users/3/friends => [{"id": 4, "name": "TJ"}]
定义路由前缀,在此之后定义的路由,只要path
是以./
开头的,都会自动加上此前缀。
不同于路由拦截,路由定义最多只会命中一个定义的路由,且后定义的路由将覆盖先定义的路由。
参数
相比于通用配置,多了一个opts.annotations
配置,用于描述该路由和校验请求参数,声明方式请参考operation-object。
另外还有一个opts.routeOptions
配置,供中间件调用。
定义一个get
请求,同时会定义一个head
请求,如果需要自定义head
请求,只需要手动定义一个head
请求覆盖掉即可。
定义一个post
请求。
定义一个put
请求。
定义一个patch
请求。
定义一个delete
请求。
定义一个head
请求。
定义一个options
请求。
通过定制的koa-send模块,满足提供静态文件服务的需求。
// 单个文件
router.static('/index.html', {
staticFile: {
filename: 'index.html',
root: __dirname
}
});
// 整个目录
router.static('/assets', {
staticFile: {
root: __dirname,
include: /(css|js|html)$/i
}
});
参数
除了methods的默认值为GET外,其余参数无区别。
用于提供根据模板渲染页面的能力。
router.render(docUrl, {
renderFile: {
template: path.resolve(__dirname, 'swagger-ui/index.ejs'),
data: Object.assign({
home: '/',
title: 'Swagger UI',
pageTitle: 'Swagger',
url: '/api-docs',
auth: null
}, options.swaggerUi)
}
});
参数
除了methods的默认值为GET外,其余参数无区别。
自定义Engine
请参考/src/render/engine/ejs-engine.js。
通过定制的busboy模块,满足文件上传的需求。并实现了FileStorage
和MemoryStorage
来接收处理文件,还支持自定义Storage
。
router.upload('./upload', {
uploadFile: {
root: path.resolve(__dirname, 'uploads'),
allowedFileExts: 'js,png'
}
}, async (ctx, next) => {
console.log(ctx.req.body); // 除type=file外的其它fields
console.log(ctx.req.files); // 由Storage返回的文件对象
console.log(ctx.request.body); // 等价于 ctx.req.body
console.log(ctx.request.files); // 等价于 ctx.req.files
ctx.body = '上传成功!';
});
参数
除了methods的默认值为POST外,其余参数无区别。
自定义Storage
请参考/src/upload/storage/file.js。
路由跳转。
参数
- source: 访问路径
- target: 目标位置
- code: 状态码,默认为301
在服务启动之前的通用拦截操作,此时会执行传入的callback。
参数
- callback: Function,待执行的回调函数,入参为已定义的所有routes对象数组。
路由在处理过程中会往koa
的ctx
对象上塞入一些变量。
当前命中路由的实例对象。
当前的实例化router对象。
从路由定义时传入的额外配置参数(opts.routeOptions),主要是为了在拦截阶段可以根据路由定义的不同routeOptions来分别处理。
定义在path上的参数解析之后的对象。
解析之后得到的body参数。
解析之后得到的文件上传对象。
解析multipart/form-data
时得到的内容,即body
+ files
。
- parseBody.encoding: String,字符编码,默认为'utf8'
- parseBody.jsonLimit: Array,
Content-Type
为application/json
时的body大小,默认不超过2MB- parseBody.formLimit: Array,
Content-Type
为application/x-www-form-urlencoded
时的body大小,默认不超过56KB- parseBody.jsonFormats: Array,
Content-Type
的值,默认为['application/json']- parseBody.formFormats: Array,
Content-Type
的值,默认为['application/x-www-form-urlencoded']- parseBody.onerror: Function,解析错误处理回调函数,传入参数为一个错误对象,
this
将指向Koa
的context
。如果不指定,则将返回400状态。
- allowCross.origin: 设置
Access-Control-Allow-Origin
头,值可以是以下类型: Boolean - 为true
时设置为请求头的Origin
字段,为false
时将禁用跨域。 String - 设置为指定值。例如指定为http://example.com
时,只有从http://example.com
发起的请求才能跨域。 RegExp - 当请求头的Origin
字段匹配时才能跨域。例如指定为/example\.com$/
时,所有以example.com
结尾的网站发过来的跨域请求都将被允许。 Array - 允许列表中的多个网站跨域。 Function - 自定义是否允许跨域。第一个参数为请求头的Origin
字段,第二个参数为一个回调处理函数(回调的第一个参数为err [object],第二个参数为allow [bool])。- allowCross.methods: 设置
Access-Control-Allow-Methods
头,值可以是个数组(如: ['GET', 'PUT', 'POST'])或者以英文逗号分隔的字符串(如: 'GET,PUT,POST')。- allowCross.allowedHeaders: 设置
Access-Control-Allow-Headers
头,值可以是个数组(如: ['Content-Type', 'Authorization'])或者以英文逗号分隔的字符串(如: 'Content-Type,Authorization')。如果未指定该设置,那么将自动使用请求头的Access-Control-Request-Headers
字段。- allowCross.exposedHeaders: 设置
Access-Control-Expose-Headers
头,值可以是个数组(如: ['Content-Range', 'X-Content-Range'])或者以英文逗号分隔的字符串(如: 'Content-Range,X-Content-Range')。- allowCross.credentials: 设置
Access-Control-Allow-Credentials
头,值为true或false(默认为false)。当需要允许跨域传cookie时,需要设置为true。- allowCross.maxAge: String,设置
Access-Control-Max-Age
头。- allowCross.optionsSuccessStatus: String,设置
OPTIONS
请求时返回的状态码,默认为204(No Content)。
- staticFile.maxAge: 设置浏览器最大缓存时间(毫秒),默认为0。
- staticFile.immutable: 设置资源是否不会变更,可以永久缓存,默认为false。
- staticFile.hidden: 设置是否允许输出隐藏文件,默认为false。
- staticFile.root: 设置资源文件所在的根目录,必需指定。
- staticFile.index: 设置目录下的默认页,如果设置该值,则当用户直接访问该目录时,会自动跳转到默认页。
- staticFile.gzip: 设置是否自动使用gzip压缩文件(.gz),默认为true。
- staticFile.brotli: 设置是否自动使用brotli压缩文件(.br),默认为true。
- staticFile.setHeaders: 设置自定义响应头
Cache-Control
或Last-Modified
,该方法接受res, path, stats
三个参数。- staticFile.extensions: Array,设置自动补全的文件扩展名,默认为false。
- staticFile.filename: 设置静态文件对应的文件名,当为目录时不需要指定该配置。
- staticFile.filter: Function,接收请求的filename,返回true时才能访问该静态资源文件,默认无限制。
- staticFile.include: RegExp,限制允许访问的静态资源文件,当设置了
filter
时该选项将被忽略。- staticFile.exclude: RegExp,限制不允许访问的静态资源文件,当设置了
filter
时该选项将被忽略。- staticFile.converter: Function,接收请求的filename,返回对应的本地文件的filename。
- staticFile.mapList: key/value,设置请求的filename到本地文件的映射关系,当设置了
converter
时该选项将被忽略。- staticFile.onerror: Function,错误处理回调函数,传入参数为一个错误对象,
this
将指向Koa
的context
。如果不指定,则将直接抛出该错误。
- uploadFile.storage: Class,上传文件处理类。当指定了
uploadFile.root
时,将使用FileStorage
保存为本地文件,否则使用MemoryStorage
保存到内存- uploadFile.allowedFileExts: String|Array,允许的上传文件名后缀,默认为*
- uploadFile.allowedFileNames: String|Array,允许的上传文件名(即input的name属性),默认为*
- uploadFile.root: String,文件保存的根目录(绝对路径)
- uploadFile.mode: Number,文件保存目录的权限,默认为0777
- uploadFile.multiple: Boolean,是否允许多文件上传(即input的multiple属性),默认为false
- uploadFile.fieldNameSize: Number,允许的字段名总大小,默认为100B
- uploadFile.fieldValueSize: Number,允许的字段值总大小,默认为1M
- uploadFile.fieldsCount: Number,允许的字段总个数,默认不限制
- uploadFile.fileSize: Number,允许的字段总个数,默认不限制
- uploadFile.fieldsCount: Number,允许的字段总个数,默认不限制
- uploadFile.fieldsCount: Number,允许的字段总个数,默认不限制
- uploadFile.fileSize: Number,允许的单个文件大小(单位为Byte),默认10240(即10MB)
- uploadFile.filesCount Number,允许上传的文件个数,默认不限制
- uploadFile.partsCount Number,允许的字段+文件总个数,默认不限制
- uploadFile.onerror Function,上传出错时的处理方式,如果不指定则将直接返回500状态
- renderFile.engine: Class,模板渲染类。默认为ejs
- renderFile.data Object,传入用于模板渲染的额外数据
- renderFile.template String,模板文件的绝对路径
- renderFile.onerror Function,渲染出错时的处理方式,如果不指定则将直接返回500状态
- swagger.docApi: String,api文档接口地址,默认为"/api-docs"
- swagger.docUrl: String,swagger页面地址,默认为"/swagger-ui.html"
- swagger.swaggerUi: Object,swagger-ui的相关配置
- swagger.swaggerUi.home: String,首页地址,默认为"/"
- swagger.swaggerUi.title: String,title标签内容
- swagger.swaggerUi.pageTitle: String,页面上显示的标题内容
- swagger.swaggerUi.url: String,api文档接口地址,默认为"/api-docs"
- swagger.swaggerUi.auth: Object,auth配置
- validator.onerror Function,校验不匹配时的处理方式,如果不指定则将直接返回400状态
更多使用示例请查看examples目录。