diff --git a/index.js b/index.js index 1655053d..9d484426 100644 --- a/index.js +++ b/index.js @@ -606,17 +606,27 @@ SendStream.prototype.sendFile = function sendFile (path) { var pathEndsWithSep = path[path.length - 1] === sep if (err && err.code === 'ENOENT' && !extname(path) && !pathEndsWithSep) { // not found, check extensions - return next(err) + return next(err, false) } if (err) return self.onStatError(err) - if (stat.isDirectory()) return self.redirect(path) + if (stat.isDirectory()) { + // if extensions are configured and path has no extension, try extensions first + if (self._extensions.length > 0 && !extname(path) && !pathEndsWithSep) { + return next(null, true) + } + return self.redirect(path) + } if (pathEndsWithSep) return self.error(404) self.emit('file', path, stat) self.send(path, stat) }) - function next (err) { + function next (err, isDir) { if (self._extensions.length <= i) { + // if original path was a directory, redirect to it + if (isDir) { + return self.redirect(path) + } return err ? self.onStatError(err) : self.error(404) @@ -626,8 +636,8 @@ SendStream.prototype.sendFile = function sendFile (path) { debug('stat "%s"', p) fs.stat(p, function (err, stat) { - if (err) return next(err) - if (stat.isDirectory()) return next() + if (err) return next(err, isDir) + if (stat.isDirectory()) return next(null, isDir) self.emit('file', p, stat) self.send(p, stat) }) diff --git a/test/fixtures/about.html b/test/fixtures/about.html new file mode 100644 index 00000000..a5d3a7fc --- /dev/null +++ b/test/fixtures/about.html @@ -0,0 +1 @@ +About Page \ No newline at end of file diff --git a/test/fixtures/about/team.html b/test/fixtures/about/team.html new file mode 100644 index 00000000..00812726 --- /dev/null +++ b/test/fixtures/about/team.html @@ -0,0 +1 @@ +Team Page \ No newline at end of file diff --git a/test/send.js b/test/send.js index b8242821..02ac1f3e 100644 --- a/test/send.js +++ b/test/send.js @@ -917,6 +917,36 @@ describe('send(file, options)', function () { .get('/thing.html') .expect(404, done) }) + + it('should serve file with extension when no directory exists', function (done) { + // /contact (no directory exists) → serves contact.html + request(createServer({ extensions: ['html'], root: fixtures })) + .get('/tobi') + .expect(200, '
tobi
', done) + }) + + it('should serve file with extension when directory also exists', function (done) { + // /about (directory exists) → serves about.html (not redirect to /about/) + request(createServer({ extensions: ['html'], root: fixtures })) + .get('/about') + .expect(200, 'About Page', done) + }) + + it('should redirect when directory exists and extensions not configured', function (done) { + // When extensions are not configured, should still redirect when directory exists + request(createServer({ root: fixtures })) + .get('/about') + .expect('Location', '/about/') + .expect(301, done) + }) + + it('should redirect to directory when file with extension does not exist', function (done) { + // /about with only about/ directory → redirects to /about/ + request(createServer({ extensions: ['html'], root: fixtures })) + .get('/pets') + .expect('Location', '/pets/') + .expect(301, done) + }) }) describe('lastModified', function () {