Open IlyaSemenov opened 6 years ago
as a workaround i used this small middleware instead of .use(router.allowedMethods())
:
app.use(async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', '*')
ctx.set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
if (ctx.method === 'OPTIONS') {
const route = router.match(ctx.path)
const methods = route.path.reduce((acc, path) => acc + path.methods.join(','), '')
ctx.set('Access-Control-Allow-Methods', methods)
ctx.status = 204
} else {
try {
await next()
} catch (e) {
ctx.status = e.status
ctx.body = e.message
}
}
})
If there is a middleware added after
router.allowedMethods()
that invokesctx.throw
, it preventsallowedMethods
from responding toOPTIONS
requests for legitimate URLs.Experiment 1
Run server:
The
OPTIONS
handler for a legitimate route works as expected:Experiment 2
Replace
ctx.status = 404
withctx.throw(404)
:The
OPTIONS
handler for a legitimate route will give 404:Expected result
Both experiment should produce identical results (
OPTIONS
handler replies with properAllow:
headers).Frankly, I believe this issue is a sign of a more serious problem.
allowedMethods()
should check for matches immediately and should not run any subsequent middleware at all in case of successful match. This is the same as normal route handlers work: they do not run next middleware in chain when they can handle request themselves fully.