Skip to content

Commit

Permalink
Merge pull request hapijs#10 from yortus/moreFlexibleIndexOption
Browse files Browse the repository at this point in the history
more flexible 'index' option for directory handler
  • Loading branch information
kanongil committed Dec 30, 2014
2 parents cad7bd9 + 2b8ce4e commit cbdbf78
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 17 deletions.
54 changes: 38 additions & 16 deletions lib/directory.js
Expand Up @@ -16,7 +16,7 @@ var internals = {};

internals.schema = Joi.object({
path: Joi.alternatives(Joi.array().includes(Joi.string()).single(), Joi.func()).required(),
index: Joi.boolean(),
index: Joi.alternatives(Joi.boolean(), Joi.string(), Joi.array().includes(Joi.string()).min(1)),
listing: Joi.boolean(),
showHidden: Joi.boolean(),
redirectToSlash: Joi.boolean(),
Expand Down Expand Up @@ -132,8 +132,21 @@ exports.handler = function (route, options) {

// Directory

var index = (settings.index !== false); // Defaults to true
if (!index &&
var indexNames;
if (settings.index === false) {
indexNames = null;
}
else if (Array.isArray(settings.index)) {
indexNames = settings.index;
}
else if (typeof settings.index === "string") {
indexNames = [settings.index];
}
else {
indexNames = ['index.html']; // settings.index defaults to ['index.html']
}

if (!indexNames &&
!settings.listing) {

return reply(Boom.forbidden());
Expand All @@ -146,27 +159,36 @@ exports.handler = function (route, options) {
return reply.redirect(resource + '/');
}

if (!index) {
if (!indexNames) {
return internals.generateListing(path, resource, selection, hasTrailingSlash, settings, request, reply);
}

var indexFile = Path.join(path, 'index.html');
File.load(indexFile, request, { lookupCompressed: settings.lookupCompressed }, function (indexResponse) {
Items.serial(indexNames, function (indexName, next) {

// File loaded successfully
var indexFile = Path.join(path, indexName);
File.load(indexFile, request, { lookupCompressed: settings.lookupCompressed }, function (indexResponse) {

if (!indexResponse.isBoom) {
return reply(indexResponse);
}
// File loaded successfully

// Directory
if (!indexResponse.isBoom) {
return reply(indexResponse);
}

var err = indexResponse;
if (err.output.statusCode !== 404) {
return reply(Boom.badImplementation('index.html is a directory'));
}
// Directory

var err = indexResponse;
if (err.output.statusCode !== 404) {
return reply(Boom.badImplementation(indexName + ' is a directory'));
}

// Not found, try the next one

return next();
});
},
function (/* err */) {

// Not found
// None of the index files were found

if (!settings.listing) {
return reply(Boom.forbidden());
Expand Down
64 changes: 63 additions & 1 deletion test/directory.js
Expand Up @@ -265,7 +265,7 @@ describe('directory', function () {
});
});

it('returns the index when found', function (done) {
it('returns the "index.html" index file when found and default index enabled', function (done) {

var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/' } } });
Expand All @@ -278,6 +278,56 @@ describe('directory', function () {
});
});

it('returns the index file when found and single custom index file specified', function (done) {

var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: 'index.js' } } });

server.inject('/directoryIndex/', function (res) {

expect(res.statusCode).to.equal(200);
expect(res.payload).to.contain('var isTest = true;');
done();
});
});

it('returns the first index file found when an array of index files is specified', function (done) {

var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: ['default.html', 'index.js', 'non.existing'] } } });

server.inject('/directoryIndex/', function (res) {

expect(res.statusCode).to.equal(200);
expect(res.payload).to.contain('var isTest = true;');
done();
});
});

it('returns a 403 when listing is disabled and a custom index file is specified but not found', function (done) {

var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: 'default.html' } } });

server.inject('/directoryIndex/', function (res) {

expect(res.statusCode).to.equal(403);
done();
});
});

it('returns a 403 when listing is disabled and an array of index files is specified but none were found', function (done) {

var server = provisionServer();
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: ['default.html', 'non.existing'] } } });

server.inject('/directoryIndex/', function (res) {

expect(res.statusCode).to.equal(403);
done();
});
});

it('returns the index when served from a hidden folder', function (done) {

var server = provisionServer();
Expand Down Expand Up @@ -322,6 +372,18 @@ describe('directory', function () {
});
});

it('returns a 500 when the custom index is a directory', function (done) {

var server = provisionServer(null, false);
server.route({ method: 'GET', path: '/directoryIndex/{path*}', handler: { directory: { path: './directory/', index: 'misc' } } });

server.inject('/directoryIndex/invalid/', function (res) {

expect(res.statusCode).to.equal(500);
done();
});
});

it('returns the correct file when using a fn directory handler', function (done) {

var directoryFn = function (request) {
Expand Down
1 change: 1 addition & 0 deletions test/directory/index.js
@@ -0,0 +1 @@
var isTest = true;
Empty file.

0 comments on commit cbdbf78

Please sign in to comment.