diff --git a/docs/Reference.md b/docs/Reference.md index 17f675d60..003ec3f91 100755 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -349,10 +349,11 @@ The following options are available when adding a route: - `'attachment'` - `'inline'`

- - `directory` - generates a directory endpoint for serving static content from a directory. Routes using the directory handler must include a - single path parameter at the end of the path string (e.g. '/path/to/somewhere/{param}' where the parameter name does not matter). The path - parameter can use any of the parameter options (e.g. '{param}' for one level files only, '{param?}' for one level files or the directory root, - '{param*}' for any level, or '{param*3}' for a specific level). The directory handler is an object with the following options: + - `directory` - generates a directory endpoint for serving static content from a directory. Routes using the + directory handler must include a path parameter at the end of the path string (e.g. '/path/to/somewhere/{param}' where the parameter name does + not matter). The path parameter can use any of the parameter options (e.g. '{param}' for one level files only, '{param?}' for one level files or + the directory root, '{param*}' for any level, or '{param*3}' for a specific level). If additional path parameters are present, they are ignored for + the purpose of selecting the file system resource. The directory handler is an object with the following options: - `path` - (required) the directory root path (relative paths are resolved based on the server [`files`](#server.config.files) configuration). Value can be: - a single path string used as the prefix for any resources requested by appending the request path parameter to the provided string. diff --git a/lib/files.js b/lib/files.js index f112a6bbb..5d68d9b3d 100755 --- a/lib/files.js +++ b/lib/files.js @@ -59,7 +59,7 @@ exports.directoryHandler = function (route, options) { Utils.assert(typeof options === 'object' && options.path, 'Options must be an object with a path'); Utils.assert(typeof options.path === 'function' || typeof options.path === 'string' || Array.isArray(options.path), 'options.path must be a function, a string, or an array of strings'); Utils.assert(route.path[route.path.length - 1] === '}', 'The route path must end with a parameter'); - Utils.assert(route.params.length === 1, 'The route path must include one and only one parameter'); + Utils.assert(route.params.length >= 1, 'The route path must include at least one parameter'); var settings = Utils.clone(options); // options can be reused var absolutePath = internals.absolutePath(route); @@ -102,12 +102,13 @@ exports.directoryHandler = function (route, options) { // Append parameter var selection = null; - if (request._paramsArray[0]) { - if (request._paramsArray[0].indexOf('..') !== -1) { + var lastParam = request._paramsArray[request._paramsArray.length - 1]; + if (lastParam) { + if (lastParam.indexOf('..') !== -1) { return request.reply(Boom.forbidden()); } - selection = request._paramsArray[0]; + selection = lastParam; } // Generate response diff --git a/lib/route.js b/lib/route.js index 3df3e5cd9..bbfc8c638 100755 --- a/lib/route.js +++ b/lib/route.js @@ -497,8 +497,8 @@ exports.sort = function (a, b) { var bSegment = bFingers[i]; if ((aSegment.isWildcard && bSegment.isWildcard) || - (aSegment.name && bSegment.name) || - (aSegment.literal == bSegment.literal)) { + (aSegment.name && bSegment.name && !aSegment.isWildcard && !bSegment.isWildcard) || + (aSegment.literal !== undefined && aSegment.literal === bSegment.literal)) { continue; } diff --git a/test/integration/response.js b/test/integration/response.js index df5a8b0d9..647543950 100755 --- a/test/integration/response.js +++ b/test/integration/response.js @@ -738,6 +738,7 @@ describe('Response', function () { server.route({ method: 'GET', path: '/showindex/{path*}', handler: { directory: { path: './', index: true, listing: true } } }); server.route({ method: 'GET', path: '/multiple/{path*}', handler: { directory: { path: ['./', '../'], listing: true } } }); server.route({ method: 'GET', path: '/redirect/{path*}', handler: { directory: { path: './', index: true, listing: true, redirectToSlash: true } } }); + server.route({ method: 'GET', path: '/{ignore}/4/{path*}', handler: { directory: { path: '.' } } }); it('returns a 403 when no index exists and listing is disabled', function (done) { @@ -955,6 +956,16 @@ describe('Response', function () { done(); }); }); + + it('ignores unused path params', function (done) { + + server.inject('/crap/4/response.js', function (res) { + + expect(res.statusCode).to.equal(200); + expect(res.payload).to.contain('hapi'); + done(); + }); + }); }); describe('Stream', function () { diff --git a/test/integration/route.js b/test/integration/route.js index 1e1ff8bdb..53cf8fa47 100755 --- a/test/integration/route.js +++ b/test/integration/route.js @@ -41,6 +41,7 @@ describe('Route', function () { '/a/{p}/b/{x}', '/{p*5}', '/a/b/{p*}', + '/{a}/b/{p*}', '/{p*}' ]; @@ -111,7 +112,7 @@ describe('Route', function () { }); }; - for (var i = 0; i < 50; i++) { + for (var i = 0; i < 50; ++i) { randomLoad(); } @@ -156,7 +157,8 @@ describe('Route', function () { ['/a/c/b/d', '/a/{p}/b/{x}'], ['/a/b/c/d/e', '/{p*5}'], ['/a/b/c/d/e/f', '/a/b/{p*}'], - ['/x/b/c/d/e/f/g', '/{p*}'] + ['/x/b/c/d/e/f/g', '/{a}/b/{p*}'], + ['/x/y/c/d/e/f/g', '/{p*}'] ]; Async.forEachSeries(requests, function (request, next) { diff --git a/test/unit/route.js b/test/unit/route.js index cd406eecf..5e8ff2aec 100755 --- a/test/unit/route.js +++ b/test/unit/route.js @@ -252,6 +252,12 @@ describe('Route', function () { '/path/': { p: 'path/' } + }, + '/{a}/b/{p*}': { + '/a/b/path/': { + a: 'a', + p: 'path/' + } } };