Skip to content

Commit

Permalink
Allow middlewares to be used for options requests (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexghr authored and nervgh committed May 29, 2019
1 parent a17e353 commit 145a1a9
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 11 deletions.
39 changes: 30 additions & 9 deletions lib/Router.js
Expand Up @@ -155,13 +155,6 @@ class Router {
[__MIDDLEWARE](ctx, next) {
let {method} = ctx

// OPTIONS support
if (method === 'OPTIONS') {
ctx.response.status = 204
ctx.response.set('Allow', this.methods.toString())
return
}

let match
try {
match = this.trie.match(ctx.request.path)
Expand All @@ -179,21 +172,49 @@ class Router {
let middle = getMiddleware(this.methods, method) // router[method](fn)
let bottom = getMiddleware(node.methods, method) // router[method](path, fn)

let stack = [...top, ...middle, preBottom.bind(this), ...bottom]
let stack = [
...top,
preMiddle.bind(this),
...middle,
preBottom.bind(this),
...bottom
]

let fn = compose(stack)
return fn(ctx, noop)

// ----------------

/**
* OPTIONS support
* we want to provide a default OPTIONS handler for any path
* so we set all the required headers and HTTP status here
* and we give middleware functions a chance to overwrite them
* then, in the `preBottom` function, we'll return this status
* (or the value it was overwritten with) if no middleware
* handles this path
*/
function preMiddle(ctx, goToMiddleMiddleware) {
if (method === 'OPTIONS') {
ctx.response.status = 204
ctx.response.set('Allow', this.methods.toString())
}

return goToMiddleMiddleware()
}

function preBottom(ctx, goToBottomMiddleware) {
// If no route match or no methods are defined, go to next middleware
if (node.isGag || !node.methods.size) {
return next()
}
// If there is no one middleware
// it's a 405 error
if (!bottom.length) {
//
// normally we'd return a 405 here since no route handles this path
// but we provide a default OPTIONS handler
// we've set all of the necessary headers and HTTP statuses in the `preMiddle` function
if (!bottom.length && method !== 'OPTIONS') {
ctx.response.set('Allow', this.methods.toString())
ctx.response.status = 405
return
Expand Down
29 changes: 27 additions & 2 deletions test/routes.js
Expand Up @@ -173,6 +173,20 @@ describe('router[method]()', function () {
.get('/one')
.status(204)
})

it('calls OPTIONS middleware', function () {
let expectedOrigin = 'https://example.com'

router.options(function (ctx) {
ctx.status = 200
ctx.set('Access-Control-Allow-Origin', expectedOrigin)
})

return request.options('/')
.status(200)
.header('Access-Control-Allow-Origin', expectedOrigin)
})

})


Expand Down Expand Up @@ -283,6 +297,19 @@ describe('router[method](path, [fn...])', function () {
.status(204)
})
})

it('calls OPTIONS middleware', function () {
let expectedOrigin = 'https://example.com'

router.options('/', function (ctx) {
ctx.status = 200
ctx.set('Access-Control-Allow-Origin', expectedOrigin)
})

return request.options('/')
.status(200)
.header('Access-Control-Allow-Origin', expectedOrigin)
})
})


Expand Down Expand Up @@ -401,5 +428,3 @@ describe('regressions', function () {
})
})
})


0 comments on commit 145a1a9

Please sign in to comment.