Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do changes to request.url in Express middleware persist on to the next middleware?

I have a middleware that rewrites the request.url. However in the next() middleware, the request.url is still the original unmodified url.

Example:

var express = require('express');
var router = express.Router();

router.use(function(req, res, next) {
  console.log('Before Rewrite',req.url);
  if(/^\/v[1-9]/.test(req.originalUrl) ) {
    console.log('Rewritten');
    req.url = '/api' + req.originalUrl;
  }
  console.log('After Rewrite',req.url);
  next();
});
router.use('/api', function(req, res, next) {
  console.log('Next', req.url);
  next();
});

With an example url of '/v3/foo' the following is output to console:

Before Rewrite /v3/foo
Rewritten
After Rewrite /api/v3/foo
Next /v3/foo

Any thoughts on why the request changes do not persist on to the next middleware?

like image 703
Geoff Ford Avatar asked Nov 20 '22 18:11

Geoff Ford


1 Answers

Thanks to the link from @kelz to the Express next() code, I have a better understanding of how Express handles urls. It seems that req.url is writeable because Express removes the root of the url when matching. For example with an original url of '/foo/bar', if you have this:

router.use('/foo', someMiddleWare);

Then req.url within someMiddleWare will now be '/bar' i.e. with the matched root removed. This is why we have req.originalUrl (which is not writeable) to persist the unaltered url.

As my original approach to rewriting the url can't work, I opted for a simpler solution:

  router.all(/^\/v[1-9]/, function(req, res) { res.redirect('/api' + req.originalUrl); });

This way, after the redirect, the req.originalUrl is as it should be for my later middleware.

like image 153
Geoff Ford Avatar answered Nov 23 '22 17:11

Geoff Ford