diff --git a/README.md b/README.md index 156c380c..83d64cb2 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,10 @@ consider it one for handling `OPTIONS` requests. * Note: If a `path` is specified, that `path` is stripped from the start of `req.url`. +* Note: The stripped `path` is added back to `req.url` when the middleware calls + `next()`. A `req.url` rewritten by the middleware is treated as relative to the + mount `path`, so rewriting `req.url` to `/index.html` inside a router mounted + on `/app` continues with `/app/index.html`. diff --git a/index.js b/index.js index 4358aebd..f9bce07f 100644 --- a/index.js +++ b/index.js @@ -158,7 +158,7 @@ Router.prototype.handle = function handle (req, res, callback) { const protohost = getProtohost(req.url) || '' let removed = '' const self = this - let slashAdded = false + let slashAddedUrl = null let sync = 0 const paramcalled = {} @@ -190,10 +190,10 @@ Router.prototype.handle = function handle (req, res, callback) { ? null : err - // remove added slash - if (slashAdded) { - req.url = req.url.slice(1) - slashAdded = false + // remove added slash unless the layer rewrote req.url + if (slashAddedUrl !== null) { + if (req.url === slashAddedUrl) req.url = req.url.slice(1) + slashAddedUrl = null } // restore altered req.url @@ -325,7 +325,7 @@ Router.prototype.handle = function handle (req, res, callback) { // Ensure leading slash if (!protohost && req.url[0] !== '/') { req.url = '/' + req.url - slashAdded = true + slashAddedUrl = req.url } // Setup base URL (no trailing slash) diff --git a/test/router.js b/test/router.js index b440e404..b2915ae5 100644 --- a/test/router.js +++ b/test/router.js @@ -1393,6 +1393,36 @@ describe('Router', function () { .expect('x-saw-1', 'GET /') .expect(200, 'saw GET /foo/', done) }) + + it('should restore a req.url rewritten inside the layer', function (done) { + const router = new Router() + const server = createServer(router) + + router.use('/foo', function (req, res, next) { + req.url = '/bar' + next() + }) + router.use(saw) + + request(server) + .get('/foo') + .expect(200, 'saw GET /foo/bar', done) + }) + + it('should restore a req.url rewritten inside the layer when a query string was present', function (done) { + const router = new Router() + const server = createServer(router) + + router.use('/foo', function (req, res, next) { + req.url = '/bar' + next() + }) + router.use(saw) + + request(server) + .get('/foo?fizz=buzz') + .expect(200, 'saw GET /foo/bar', done) + }) }) })