/**
* Returns separate middleware for responding to `OPTIONS` requests with
* an `Allow` header containing the allowed methods, as well as responding
* with `405 Method Not Allowed` and `501 Not Implemented` as appropriate.
*
* @example
*
* ```javascript
* 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());
* ```
*
* **Example with [Boom](https://github.com/hapijs/boom)**
*
* ```javascript
* var Koa = require('koa');
* var Router = require('koa-router');
* var Boom = require('boom');
*
* var app = new Koa();
* var router = new Router();
*
* app.use(router.routes());
* app.use(router.allowedMethods({
* throw: true,
* notImplemented: () => new Boom.notImplemented(),
* methodNotAllowed: () => new Boom.methodNotAllowed()
* }));
* ```
*
* @param {Object=} options
* @param {Boolean=} options.throw throw error instead of setting status and header
* @param {Function=} options.notImplemented throw the returned value in place of the default NotImplemented error
* @param {Function=} options.methodNotAllowed throw the returned value in place of the default MethodNotAllowed error
* @returns {Function}
*/
Router.prototype.allowedMethods = function (options) {
options = options || {};
var implemented = this.methods; return function allowedMethods(ctx, next) {
// 所有中间件执行完之后执行allowedMethod方法
return next().then(function() {
var allowed = {};
// 没有响应状态码或者响应了404
if (!ctx.status || ctx.status === 404) {
// 在match方法中,匹配的路由的layer实例对象组成的数组
ctx.matched.forEach(function (route) {
route.methods.forEach(function (method) {
// 把匹配的路由的http方法保存起来,认为是允许的http请求方法
allowed[method] = method;
});
});
var allowedArr = Object.keys(allowed);
// 如果该方法在router实例的methods中不存在
if (!~implemented.indexOf(ctx.method)) {
// 如果在初始化router时配置了throw属性为true
if (options.throw) {
var notImplementedThrowable;
if (typeof options.notImplemented === 'function') {
// 指定了报错函数
notImplementedThrowable = options.notImplemented(); // set whatever the user returns from their function
} else {
// 没有指定则抛出http异常
notImplementedThrowable = new HttpError.NotImplemented();
}
throw notImplementedThrowable;
} else {
// 没有配置throw则响应501









