koa-router 是
koa
框架的一个路由处理级别的中间件
koa-router可以说是koa必须用上的一个库了, 其具体配置和用法我们直接查看源码或者官方文档,基于部分同学对router.allowedMethods()
用法不理解,所以我们重点查看一下其中allowedMethods
到底搞了什么猫腻,弄明白allowedMethods
的应用场景
首先我们查阅koa-router
的源码看到allowedMethods
方法的申明
koa-router/lib/router.js (line-401)
Router.prototype.allowedMethods = function (options) {
options = options || {};
var implemented = this.methods;
return function allowedMethods(ctx, next) {
return next().then(function() {
var allowed = {};
//重点代码
//当后续所有中间件执行完成之后,判断ctx的status,如果next中间件已经正确处理了response响应,则直接略过
if (!ctx.status || ctx.status === 404) {
ctx.matched.forEach(function (route) {
route.methods.forEach(function (method) {
allowed[method] = method;
});
});
var allowedArr = Object.keys(allowed);
if (!~implemented.indexOf(ctx.method)) {
if (options.throw) {
var notImplementedThrowable;
if (typeof options.notImplemented === 'function') {
notImplementedThrowable = options.notImplemented(); // set whatever the user returns from their function
} else {
notImplementedThrowable = new HttpError.NotImplemented();
}
throw notImplementedThrowable;
} else {
ctx.status = 501;
ctx.set('Allow', allowedArr);
}
} else if (allowedArr.length) {
if (ctx.method === 'OPTIONS') {
ctx.status = 200;
ctx.body = '';
ctx.set('Allow', allowedArr);
} else if (!allowed[ctx.method]) {
if (options.throw) {
var notAllowedThrowable;
if (typeof options.methodNotAllowed === 'function') {
notAllowedThrowable = options.methodNotAllowed(); // set whatever the user returns from their function
} else {
notAllowedThrowable = new HttpError.MethodNotAllowed();
}
throw notAllowedThrowable;
} else {
ctx.status = 405;
ctx.set('Allow', allowedArr);
}
}
}
}
});
};
};
从源码中我们可以看到.allowedMethods
处理的业务是当所有路由中间件执行完成之后,若ctx.status
为空或者404的时候,丰富response
对象的header
头.
allowedMethods 应用场景
- 全局应用
var Koa = require('koa');
var Router = require('koa-router');
var app = new Koa();
var router = new Router();
app.use(router.routes());
app.use(router.allowedMethods());
这是官方文档的推荐用法,我们可以看到router.allowedMethods()
用在了路由匹配router.routes()
之后,所以在当所有路由中间件最后调用.此时根据ctx.status
设置response响应头
- 局部应用
有的同学将他用在了路由级的中间件
var Koa = require('koa');
var Router = require('koa-router');
var app = new Koa();
var router = new Router();
router.use('/test',router.allowedMethods())
app.use(router.routes());
这时候只有当请求路径匹配到了/test
才会执行allowedMethods
,然后根据ctx.status
设置response响应头
当然,如果我们不设置router.allowedMethods()
在表现上除了ctx.status
不会自动设置,以及response header
中不会加上Allow
之外,不会造成其他影响.
如果要设置,建议按照官方的写法,搞成全局的,路由级别的配置感觉很鸡肋