Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Continuation control flow from middleware #19

Closed
h2non opened this issue Jul 4, 2015 · 8 comments
Closed

Continuation control flow from middleware #19

h2non opened this issue Jul 4, 2015 · 8 comments
Assignees
Labels

Comments

@h2non
Copy link

h2non commented Jul 4, 2015

Currently the router only discern between path based pattern matching.

In some cases it could be useful to ignore a matched route in the case that during in the middleware dispatch process, providing an extra layer of control flow.

To give you a simple example:

router.use('/users', function (req, res, next) {
  if (req.headers.version === '1.0') {
    // Ignore the route and continue with the request matching process with other routes
    return next.continue()
  }
  // Perform mad science here with the route as usual
  next()
})
@h2non h2non changed the title Support to ignore route from middleware Continuation control flow from middleware Jul 4, 2015
@dougwilson
Copy link
Contributor

Hi! Can you expand on your example a little bit :)? It's not clear to me where next.continue() would go and how it's different from next() or next('route').

@h2non
Copy link
Author

h2non commented Jul 4, 2015

The idea is as simple as trying to continue with the route matching process, instead of running the current matched route (e.g: /users in the above example).

As far as I can understand, calling next('error') will terminate the middleware cycle stoping calling the pending ones and reaching the final handler to do whatever it should do in case of error, like for instance write the response with an error, but this doesn't allow you to re-start the route matching process trying to match the next route after /users, for instance I could configure another one with the same method and path, but for a different purpose.

Probably my proposal is a sort of workaround to achieve a missing feature like providing a more powerful matching based on multiple request params, such as HTTP headers. E.g:

route.use('/users', /* run only if matches the header */ { 'Version': '1.0' }, middleware)
route.use('/users', /* run only if matches the header */ { 'Version': '2.0' }, middleware)

@dougwilson
Copy link
Contributor

Gotcha. To me, you are simply describing next('route') (where you pass a special string, 'route' as the argument to next):

// this will not run "middleware" if req.headers.version is not 1.0
route.use('/users', onlyIfVersion1, middleware)
route.use('/users', ..) // this is where next('route') jumps you to

function onlyIfVersion1(req, res, next) {
  if (req.headers.version !== '1.0') return next('route')
  next()
}

@dougwilson
Copy link
Contributor

You can find more information about next('route') in the Express 4.x docs: http://expressjs.com/guide/routing.html#route-handlers

@h2non
Copy link
Author

h2non commented Jul 5, 2015

Got it! That would be enough. Thanks

@h2non h2non closed this as completed Jul 5, 2015
@dougwilson
Copy link
Contributor

Here is an example of using what is currently in this module that seems like it fits your use-case exactly:

route.use('/users', /* run only if matches the header */ requireHeadersMatch({ 'Version': '1.0' }), middleware)
route.use('/users', /* run only if matches the header */ requireHeadersMatch({ 'Version': '2.0' }), middleware)

function requireHeadersMatch(headers) {
  return function (req, res, next) {
    for (var k in headers) {
      if (req.headers[k.toLowerCase()] !== headers[k]) return next('route')
    }
    next()
  }
}

@dougwilson dougwilson self-assigned this Jul 5, 2015
@dougwilson
Copy link
Contributor

Got it! That would be enough. Thanks

Cool :) Let me know if you need anything! I was actually just playing around with your rocky earlier this week :)

@h2non
Copy link
Author

h2non commented Jul 5, 2015

Thanks for the snippet. My example above was just representative to explain the thing, but the obvios way to do that is via middleware, indeed I created a tiny middleware module which does the same.

Regarding to rocky, I'm happy to read that :D. It's still young, but I'm working in a new version with interesting features. Feel free to give me any kind of feedback, I'll appreciate it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants