diff --git a/lib/directory.js b/lib/directory.js index 9dc49ae..487f974 100755 --- a/lib/directory.js +++ b/lib/directory.js @@ -113,7 +113,7 @@ exports.handler = function (route, options) { error = err; } - // Not found + // Handle Not found if (internals.isNotFound(error)) { if (settings.defaultExtension) { @@ -138,55 +138,40 @@ exports.handler = function (route, options) { return; } - // Propagate non-directory errors + // Handle Directory - if (!internals.isDirectory(error)) { + if (internals.isDirectory(error)) { + if (settings.redirectToSlash !== false && // Defaults to true + !request.server.settings.router.stripTrailingSlash && + !hasTrailingSlash) { - throw error; - } - - // Directory - - if (!indexNames.length && - !settings.listing) { - - throw error; - } - - if (settings.redirectToSlash !== false && // Defaults to true - !request.server.settings.router.stripTrailingSlash && - !hasTrailingSlash) { - - return reply.redirect(resource + '/'); - } - - for (let i = 0; i < indexNames.length; ++i) { - const indexName = indexNames[i]; - - const indexFile = Path.join(path, indexName); - try { - // File loaded successfully - - return await File.load(indexFile, request, fileOptions); + return reply.redirect(resource + '/'); } - catch (err) { - Bounce.ignore(err, 'boom'); - // Directory + for (const indexName of indexNames) { + const indexFile = Path.join(path, indexName); + try { + return await File.load(indexFile, request, fileOptions); + } + catch (err) { + Bounce.ignore(err, 'boom'); + + if (!internals.isNotFound(err)) { + throw Boom.internal(indexName + ' is a directory', err); + } - if (!internals.isNotFound(err)) { - throw Boom.badImplementation(indexName + ' is a directory'); + // Not found - try next } } - } - // None of the index files were found + // None of the index files were found - if (!settings.listing) { - throw Boom.forbidden(); + if (settings.listing) { + return internals.generateListing(Path.join(baseDir, path), resource, selection, hasTrailingSlash, settings, request); + } } - return await internals.generateListing(Path.join(baseDir, path), resource, selection, hasTrailingSlash, settings, request); + throw error; }; for (let i = 0; i < paths.length; ++i) { diff --git a/test/directory.js b/test/directory.js index b002987..93e7f66 100755 --- a/test/directory.js +++ b/test/directory.js @@ -117,6 +117,20 @@ describe('directory', () => { expect(res.payload).to.contain('name": "inert"'); }); + it('returns 404 when the a fn directory handler returns an empty array', async () => { + + const directoryFn = (request) => { + + return []; + }; + + const server = await provisionServer(); + server.route({ method: 'GET', path: '/directoryfn/{path?}', handler: { directory: { path: directoryFn } } }); + + const res = await server.inject('/directoryfn/index.js'); + expect(res.statusCode).to.equal(404); + }); + it('returns the correct file when requesting a file from a child directory', async () => { const server = await provisionServer(); @@ -525,6 +539,15 @@ describe('directory', () => { expect(res.statusCode).to.equal(404); }); + it('appends default extension and errors on file', async () => { + + const server = await provisionServer(); + server.route({ method: 'GET', path: '/directory/{path*}', handler: { directory: { path: __dirname, defaultExtension: 'dir' } } }); + + const res = await server.inject('/directory/directory/index'); + expect(res.statusCode).to.equal(403); + }); + it('does not append default extension when directory exists', async () => { const server = await provisionServer(); diff --git a/test/directory/index.dir/.gitempty b/test/directory/index.dir/.gitempty new file mode 100644 index 0000000..e69de29