From 24e860ca0717c7079edcfb1b8af6f6691d009a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Tue, 8 Dec 2015 15:09:53 +0100 Subject: [PATCH 01/16] Added responseStatus() function --- index.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 81ec0b3..5d7e391 100644 --- a/index.js +++ b/index.js @@ -79,6 +79,22 @@ module.exports.mime = mime var listenerCount = EventEmitter.listenerCount || function (emitter, type) { return emitter.listeners(type).length } + +function responseStatus(res, code, msg) +{ + if(msg == null) + { + msg = statuses[code] + + res.setHeader('Content-Type', 'text/plain; charset=UTF-8') + } + + res.statusCode = code + res.setHeader('Content-Length', Buffer.byteLength(msg)) + res.setHeader('X-Content-Type-Options', 'nosniff') + res.end(msg) +} + /** * Return a `SendStream` for `req` and `path`. * @@ -278,7 +294,6 @@ SendStream.prototype.error = function error (status, error) { } var res = this.res - var msg = statuses[status] // clear existing headers clearHeaders(res) @@ -289,11 +304,7 @@ SendStream.prototype.error = function error (status, error) { } // send basic response - res.statusCode = status - res.setHeader('Content-Type', 'text/plain; charset=UTF-8') - res.setHeader('Content-Length', Buffer.byteLength(msg)) - res.setHeader('X-Content-Type-Options', 'nosniff') - res.end(msg) + responseStatus(res, status) } /** From 3857607e8f7d48d33335f64e375b9a015e291ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Tue, 8 Dec 2015 15:12:42 +0100 Subject: [PATCH 02/16] Added redirect() function --- index.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 5d7e391..fac6f1a 100644 --- a/index.js +++ b/index.js @@ -95,6 +95,19 @@ function responseStatus(res, code, msg) res.end(msg) } +function redirect(res, loc) +{ + // redirect + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Location', loc) + + loc = escapeHtml(loc) + var msg = 'Redirecting to ' + loc + '\n' + + responseStatus(res, 301, msg) +} + + /** * Return a `SendStream` for `req` and `path`. * @@ -456,17 +469,7 @@ SendStream.prototype.redirect = function redirect (path) { return } - var loc = encodeUrl(collapseLeadingSlashes(path + '/')) - var msg = 'Redirecting to ' + escapeHtml(loc) + '\n' - var res = this.res - - // redirect - res.statusCode = 301 - res.setHeader('Content-Type', 'text/html; charset=UTF-8') - res.setHeader('Content-Length', Buffer.byteLength(msg)) - res.setHeader('X-Content-Type-Options', 'nosniff') - res.setHeader('Location', loc) - res.end(msg) + redirect(this.res, path + '/') } /** From 0363e3ecfb9c22b5ecde93b488c3fb8bea178d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Tue, 8 Dec 2015 15:14:06 +0100 Subject: [PATCH 03/16] Redirection for symlinks --- index.js | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index fac6f1a..c814876 100644 --- a/index.js +++ b/index.js @@ -458,7 +458,7 @@ SendStream.prototype.isRangeFresh = function isRangeFresh () { * @private */ -SendStream.prototype.redirect = function redirect (path) { +SendStream.prototype.redirectDirectory = function redirectDirectory(path) { if (listenerCount(this, 'directory') !== 0) { this.emit('directory') return @@ -472,6 +472,24 @@ SendStream.prototype.redirect = function redirect (path) { redirect(this.res, path + '/') } +/** + * Redirect a symbolic link. + * + * @param {string} path + * @private + */ + +SendStream.prototype.redirectSymbolicLink = function redirectSymbolicLink(path) { + var self = this + + fs.readlink(path, function(err, linkString) + { + if (err) return self.onStatError(err) + + redirect(self.res, linkString) + }) +} + /** * Pipe to `res. * @@ -679,14 +697,20 @@ SendStream.prototype.sendFile = function sendFile (path) { var i = 0 var self = this - debug('stat "%s"', path) - fs.stat(path, function onstat (err, stat) { - if (err && err.code === 'ENOENT' && !extname(path) && path[path.length - 1] !== sep) { + debug('stat "%s"', path); + fs.lstat(path, function onstat(err, stat) { + if (err && err.code === 'ENOENT' + && !extname(path) + && path[path.length - 1] !== sep) { // not found, check extensions return next(err) } + if (err) return self.onStatError(err) - if (stat.isDirectory()) return self.redirect(self.path) + + if (stat.isDirectory()) return self.redirectDirectory(self.path) + if (stat.isSymbolicLink()) return self.redirectSymbolicLink(self.path) + self.emit('file', path, stat) self.send(path, stat) }) From a8d73fa91df2e248ac21cc9ec9e9a4ab0d47c329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Tue, 8 Dec 2015 15:15:10 +0100 Subject: [PATCH 04/16] Clean-up and make code more homogeneous --- index.js | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/index.js b/index.js index c814876..b0c2636 100644 --- a/index.js +++ b/index.js @@ -460,13 +460,11 @@ SendStream.prototype.isRangeFresh = function isRangeFresh () { SendStream.prototype.redirectDirectory = function redirectDirectory(path) { if (listenerCount(this, 'directory') !== 0) { - this.emit('directory') - return + return this.emit('directory') } if (this.hasTrailingSlash()) { - this.error(403) - return + return this.error(403) } redirect(this.res, path + '/') @@ -717,9 +715,8 @@ SendStream.prototype.sendFile = function sendFile (path) { function next (err) { if (self._extensions.length <= i) { - return err - ? self.onStatError(err) - : self.error(404) + if (err) return self.onStatError(err); + return self.error(404); } var p = path + '.' + self._extensions[i++] @@ -727,7 +724,9 @@ 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() + self.emit('file', p, stat) self.send(p, stat) }) @@ -740,25 +739,27 @@ SendStream.prototype.sendFile = function sendFile (path) { * @param {String} path * @api private */ -SendStream.prototype.sendIndex = function sendIndex (path) { - var i = -1 - var self = this +SendStream.prototype.sendIndex = function sendIndex(path){ + var i = 0; + var self = this; - function next (err) { - if (++i >= self._index.length) { - if (err) return self.onStatError(err) - return self.error(404) + function next(err){ + if (self._index.length <= i) { + if (err) return self.onStatError(err); + return self.error(404); } - var p = join(path, self._index[i]) + var p = join(path, self._index[i++]); - debug('stat "%s"', p) - fs.stat(p, function (err, stat) { - if (err) return next(err) - if (stat.isDirectory()) return next() - self.emit('file', p, stat) - self.send(p, stat) - }) + debug('stat "%s"', p); + fs.stat(p, function(err, stat){ + if (err) return next(err); + + if (stat.isDirectory()) return next(); + + self.emit('file', p, stat); + self.send(p, stat); + }); } next() From 4fbd0c85fc9870c1b969481db26afa2fe9fb1926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Tue, 8 Dec 2015 22:27:29 +0100 Subject: [PATCH 05/16] Ensure the returned redirect for symlinks are always relative --- index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index b0c2636..1f26f3e 100644 --- a/index.js +++ b/index.js @@ -484,6 +484,14 @@ SendStream.prototype.redirectSymbolicLink = function redirectSymbolicLink(path) { if (err) return self.onStatError(err) + // Get relative paths for all symlinks, also for absolute ones + path = dirname(path) + linkString = relative(path, resolve(path, linkString)) + + // Resolve the URL, and make it relative (is this necessary?) + linkString = url.resolve(self.path, linkString) + linkString = relative(dirname(self.path), linkString) + redirect(self.res, linkString) }) } @@ -707,7 +715,7 @@ SendStream.prototype.sendFile = function sendFile (path) { if (err) return self.onStatError(err) if (stat.isDirectory()) return self.redirectDirectory(self.path) - if (stat.isSymbolicLink()) return self.redirectSymbolicLink(self.path) + if (stat.isSymbolicLink()) return self.redirectSymbolicLink(path) self.emit('file', path, stat) self.send(path, stat) From 53fd98bef894495f11ae187393b8ddef5110889f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Tue, 8 Dec 2015 22:27:41 +0100 Subject: [PATCH 06/16] Test for symlinks --- test/send.js | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/test/send.js b/test/send.js index da101aa..5de7897 100644 --- a/test/send.js +++ b/test/send.js @@ -132,8 +132,36 @@ describe('send(file).pipe(res)', function () { .expect(200, '404 ENOENT', done) }) - it('should not override content-type', function (done) { - var app = http.createServer(function (req, res) { + it('should 301 if the directory exists', function(done){ + request(app) + .get('/pets') + .expect('Location', '/pets/') + .expect(301, 'Redirecting to /pets/', done) + }) + + it("should 301 if it's a symbolic link", function(done){ + var destination = 'name.txt' + var path2 = path.join(fixtures, 'symlink') + + fs.symlink(destination, path2, function(error) + { + if(error && error.code !== 'EEXIST') return done(error) + + request(app) + .get('/symlink') + .expect('Location', destination) + .expect(301, 'Redirecting to '+destination+'\n', function(error) + { + fs.unlink(path2, function(error2) + { + done(error || error2) + }) + }) + }) + }) + + it('should not override content-type', function(done){ + var app = http.createServer(function(req, res){ res.setHeader('Content-Type', 'application/x-custom') send(req, req.url, {root: fixtures}).pipe(res) }) From b0648bb71a6eb5cc970f7c50d94c80aedb6e3ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Wed, 9 Dec 2015 15:01:10 +0100 Subject: [PATCH 07/16] Match existing brackets style --- index.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 1f26f3e..08e88e5 100644 --- a/index.js +++ b/index.js @@ -80,10 +80,8 @@ var listenerCount = EventEmitter.listenerCount || function (emitter, type) { return emitter.listeners(type).length } -function responseStatus(res, code, msg) -{ - if(msg == null) - { +function responseStatus(res, code, msg) { + if(msg == null) { msg = statuses[code] res.setHeader('Content-Type', 'text/plain; charset=UTF-8') @@ -95,8 +93,7 @@ function responseStatus(res, code, msg) res.end(msg) } -function redirect(res, loc) -{ +function redirect(res, loc) { // redirect res.setHeader('Content-Type', 'text/html; charset=UTF-8') res.setHeader('Location', loc) From 6a242f3ae6145b97650e304c580a201845eea458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Wed, 9 Dec 2015 15:05:52 +0100 Subject: [PATCH 08/16] Maintain old method name for backwards compatibility --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 08e88e5..94a834b 100644 --- a/index.js +++ b/index.js @@ -455,7 +455,7 @@ SendStream.prototype.isRangeFresh = function isRangeFresh () { * @private */ -SendStream.prototype.redirectDirectory = function redirectDirectory(path) { +SendStream.prototype.redirect = function redirectDirectory(path) { if (listenerCount(this, 'directory') !== 0) { return this.emit('directory') } @@ -711,7 +711,7 @@ SendStream.prototype.sendFile = function sendFile (path) { if (err) return self.onStatError(err) - if (stat.isDirectory()) return self.redirectDirectory(self.path) + if (stat.isDirectory()) return self.redirect(self.path) if (stat.isSymbolicLink()) return self.redirectSymbolicLink(path) self.emit('file', path, stat) From 277eba90c22fa4167377355cd37128e4d34650c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Wed, 9 Dec 2015 15:07:21 +0100 Subject: [PATCH 09/16] Return undefined instead of the event emitter instance --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 94a834b..60e1440 100644 --- a/index.js +++ b/index.js @@ -457,7 +457,8 @@ SendStream.prototype.isRangeFresh = function isRangeFresh () { SendStream.prototype.redirect = function redirectDirectory(path) { if (listenerCount(this, 'directory') !== 0) { - return this.emit('directory') + this.emit('directory') + return } if (this.hasTrailingSlash()) { From 64c15ca3493a829e658ee65a432405faaac814c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Wed, 9 Dec 2015 15:08:11 +0100 Subject: [PATCH 10/16] redirectSymlinks option --- README.md | 7 ++++++- index.js | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4167926..f4e5be0 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,11 @@ Provide a max-age in milliseconds for http caching, defaults to 0. This can also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme) module. +##### redirectSymlinks + +When `true`, return symlinks as `301 Redirect` instead of the file they are +pointing. Default is `false`. + ##### root Serve files relative to `path`. @@ -229,7 +234,7 @@ var app = http.createServer(function onRequest (req, res) { }).listen(3000) ``` -## License +## License [MIT](LICENSE) diff --git a/index.js b/index.js index 60e1440..b4fde2e 100644 --- a/index.js +++ b/index.js @@ -192,6 +192,8 @@ function SendStream (req, path, options) { ? resolve(opts.root) : null + this._redirectSymlinks = opts.redirectSymlinks + if (!this._root && opts.from) { this.from(opts.from) } @@ -713,7 +715,9 @@ SendStream.prototype.sendFile = function sendFile (path) { if (err) return self.onStatError(err) if (stat.isDirectory()) return self.redirect(self.path) - if (stat.isSymbolicLink()) return self.redirectSymbolicLink(path) + + if (stat.isSymbolicLink() && self._redirectSymlinks) + return self.redirectSymbolicLink(path) self.emit('file', path, stat) self.send(path, stat) From 08c3d08662ee74d26b3baacfd0274a7660a2a553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Wed, 9 Dec 2015 15:08:22 +0100 Subject: [PATCH 11/16] Fixed tests --- index.js | 4 ++++ test/send.js | 28 +++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index b4fde2e..41c8c0b 100644 --- a/index.js +++ b/index.js @@ -31,6 +31,10 @@ var statuses = require('statuses') var Stream = require('stream') var util = require('util') +var dirname = path.dirname +var relative = path.relative +var url = require('url') + /** * Path function references. * @private diff --git a/test/send.js b/test/send.js index 5de7897..e3a311b 100644 --- a/test/send.js +++ b/test/send.js @@ -139,7 +139,33 @@ describe('send(file).pipe(res)', function () { .expect(301, 'Redirecting to /pets/', done) }) - it("should 301 if it's a symbolic link", function(done){ + it("should not redirect on symbolic links", function(done){ + var destination = 'name.txt' + var path2 = path.join(fixtures, 'symlink') + + fs.symlink(destination, path2, function(error) + { + if(error && error.code !== 'EEXIST') return done(error) + + request(app) + .get('/symlink') + .expect(200, 'tobi', function(error) + { + fs.unlink(path2, function(error2) + { + done(error || error2) + }) + }) + }) + }) + + it("should 301 if it's a symbolic link and we want to redirect", function(done){ + var app = http.createServer(function (req, res) { + send(req, req.url, {root: fixtures, redirectSymlinks: true}) + .on('error', function (err) { res.end(err.statusCode + ' ' + err.code) }) + .pipe(res) + }) + var destination = 'name.txt' var path2 = path.join(fixtures, 'symlink') From bc95ab0c9be26cfd68f8b586929bfa2dba9b0dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Thu, 10 Dec 2015 11:46:46 +0100 Subject: [PATCH 12/16] Removed deops --- index.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 41c8c0b..93a925a 100644 --- a/index.js +++ b/index.js @@ -85,8 +85,9 @@ var listenerCount = EventEmitter.listenerCount || function responseStatus(res, code, msg) { - if(msg == null) { - msg = statuses[code] + var errMsg = msg + if(errMsg == null) { + errMsg = statuses[code] res.setHeader('Content-Type', 'text/plain; charset=UTF-8') } @@ -94,7 +95,7 @@ function responseStatus(res, code, msg) { res.statusCode = code res.setHeader('Content-Length', Buffer.byteLength(msg)) res.setHeader('X-Content-Type-Options', 'nosniff') - res.end(msg) + res.end(errMsg) } function redirect(res, loc) { @@ -102,8 +103,8 @@ function redirect(res, loc) { res.setHeader('Content-Type', 'text/html; charset=UTF-8') res.setHeader('Location', loc) - loc = escapeHtml(loc) - var msg = 'Redirecting to ' + loc + '\n' + var escLoc = escapeHtml(loc) + var msg = 'Redirecting to ' + escLoc + '\n' responseStatus(res, 301, msg) } @@ -468,7 +469,8 @@ SendStream.prototype.redirect = function redirectDirectory(path) { } if (this.hasTrailingSlash()) { - return this.error(403) + this.error(403) + return } redirect(this.res, path + '/') From 2d1e7eb69f5713a1add8db515c79c2e18bd283d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Thu, 21 Jan 2016 01:16:46 +0100 Subject: [PATCH 13/16] return 403 error if symlink destination is outside files root --- index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 93a925a..b26baf5 100644 --- a/index.js +++ b/index.js @@ -490,9 +490,15 @@ SendStream.prototype.redirectSymbolicLink = function redirectSymbolicLink(path) { if (err) return self.onStatError(err) + // Get absolute path on the real filesystem of the destination + path = dirname(path) + var to = resolve(path, linkString) + + // Check destination is not out of files root + if(to.indexOf(self._root) !== 0) return this.error(403) + // Get relative paths for all symlinks, also for absolute ones - path = dirname(path) - linkString = relative(path, resolve(path, linkString)) + linkString = relative(path, to) // Resolve the URL, and make it relative (is this necessary?) linkString = url.resolve(self.path, linkString) From bb6b9ed2bdf7a51f69fca723453c540bff2d1a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Sat, 13 Aug 2016 13:50:48 +0200 Subject: [PATCH 14/16] Fixed test for redirection --- test/send.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/send.js b/test/send.js index e3a311b..1b075b9 100644 --- a/test/send.js +++ b/test/send.js @@ -136,7 +136,7 @@ describe('send(file).pipe(res)', function () { request(app) .get('/pets') .expect('Location', '/pets/') - .expect(301, 'Redirecting to /pets/', done) + .expect(301, 'Redirecting to /pets/\n', done) }) it("should not redirect on symbolic links", function(done){ From 6945537943bdfc9f089743d3ab6b577770a55409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Sat, 13 Aug 2016 15:50:47 +0200 Subject: [PATCH 15/16] Removed trash code --- index.js | 19 ------------------- package.json | 1 - 2 files changed, 20 deletions(-) diff --git a/index.js b/index.js index b26baf5..00f4014 100644 --- a/index.js +++ b/index.js @@ -16,7 +16,6 @@ var createError = require('http-errors') var debug = require('debug')('send') var deprecate = require('depd')('send') var destroy = require('destroy') -var encodeUrl = require('encodeurl') var escapeHtml = require('escape-html') var etag = require('etag') var EventEmitter = require('events').EventEmitter @@ -907,24 +906,6 @@ function clearHeaders (res) { res._headerNames = {} } -/** - * Collapse all leading slashes into a single slash - * - * @param {string} str - * @private - */ -function collapseLeadingSlashes (str) { - for (var i = 0; i < str.length; i++) { - if (str[i] !== '/') { - break - } - } - - return i > 1 - ? '/' + str.substr(i) - : str -} - /** * Determine if path parts contain a dotfile. * diff --git a/package.json b/package.json index 3a93e89..9d932f7 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "debug": "~2.2.0", "depd": "~1.1.0", "destroy": "~1.0.4", - "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.7.0", "fresh": "0.3.0", From 41a9611c23cf53758de0450fdbc70c982ebef9d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Legan=C3=A9s=20Combarro=20=22piranna?= Date: Sat, 13 Aug 2016 15:50:55 +0200 Subject: [PATCH 16/16] Fixed linting --- index.js | 64 +++++++++++++++++++++++++--------------------------- test/send.js | 32 +++++++++++--------------- 2 files changed, 44 insertions(+), 52 deletions(-) diff --git a/index.js b/index.js index 00f4014..c7a007e 100644 --- a/index.js +++ b/index.js @@ -30,7 +30,7 @@ var statuses = require('statuses') var Stream = require('stream') var util = require('util') -var dirname = path.dirname +var dirname = path.dirname var relative = path.relative var url = require('url') @@ -82,10 +82,9 @@ module.exports.mime = mime var listenerCount = EventEmitter.listenerCount || function (emitter, type) { return emitter.listeners(type).length } - -function responseStatus(res, code, msg) { +function responseStatus (res, code, msg) { var errMsg = msg - if(errMsg == null) { + if (errMsg == null) { errMsg = statuses[code] res.setHeader('Content-Type', 'text/plain; charset=UTF-8') @@ -97,7 +96,7 @@ function responseStatus(res, code, msg) { res.end(errMsg) } -function redirect(res, loc) { +function redirect (res, loc) { // redirect res.setHeader('Content-Type', 'text/html; charset=UTF-8') res.setHeader('Location', loc) @@ -108,7 +107,6 @@ function redirect(res, loc) { responseStatus(res, 301, msg) } - /** * Return a `SendStream` for `req` and `path`. * @@ -461,7 +459,7 @@ SendStream.prototype.isRangeFresh = function isRangeFresh () { * @private */ -SendStream.prototype.redirect = function redirectDirectory(path) { +SendStream.prototype.redirect = function redirectDirectory (path) { if (listenerCount(this, 'directory') !== 0) { this.emit('directory') return @@ -482,11 +480,10 @@ SendStream.prototype.redirect = function redirectDirectory(path) { * @private */ -SendStream.prototype.redirectSymbolicLink = function redirectSymbolicLink(path) { +SendStream.prototype.redirectSymbolicLink = function redirectSymbolicLink (path) { var self = this - fs.readlink(path, function(err, linkString) - { + fs.readlink(path, function (err, linkString) { if (err) return self.onStatError(err) // Get absolute path on the real filesystem of the destination @@ -494,7 +491,7 @@ SendStream.prototype.redirectSymbolicLink = function redirectSymbolicLink(path) var to = resolve(path, linkString) // Check destination is not out of files root - if(to.indexOf(self._root) !== 0) return this.error(403) + if (to.indexOf(self._root) !== 0) return this.error(403) // Get relative paths for all symlinks, also for absolute ones linkString = relative(path, to) @@ -714,11 +711,11 @@ SendStream.prototype.sendFile = function sendFile (path) { var i = 0 var self = this - debug('stat "%s"', path); - fs.lstat(path, function onstat(err, stat) { - if (err && err.code === 'ENOENT' - && !extname(path) - && path[path.length - 1] !== sep) { + debug('stat "%s"', path) + fs.lstat(path, function onstat (err, stat) { + if (err && err.code === 'ENOENT' && + !extname(path) && + path[path.length - 1] !== sep) { // not found, check extensions return next(err) } @@ -727,8 +724,9 @@ SendStream.prototype.sendFile = function sendFile (path) { if (stat.isDirectory()) return self.redirect(self.path) - if (stat.isSymbolicLink() && self._redirectSymlinks) + if (stat.isSymbolicLink() && self._redirectSymlinks) { return self.redirectSymbolicLink(path) + } self.emit('file', path, stat) self.send(path, stat) @@ -736,8 +734,8 @@ SendStream.prototype.sendFile = function sendFile (path) { function next (err) { if (self._extensions.length <= i) { - if (err) return self.onStatError(err); - return self.error(404); + if (err) return self.onStatError(err) + return self.error(404) } var p = path + '.' + self._extensions[i++] @@ -760,27 +758,27 @@ SendStream.prototype.sendFile = function sendFile (path) { * @param {String} path * @api private */ -SendStream.prototype.sendIndex = function sendIndex(path){ - var i = 0; - var self = this; +SendStream.prototype.sendIndex = function sendIndex (path) { + var i = 0 + var self = this - function next(err){ + function next (err) { if (self._index.length <= i) { - if (err) return self.onStatError(err); - return self.error(404); + if (err) return self.onStatError(err) + return self.error(404) } - var p = join(path, self._index[i++]); + var p = join(path, self._index[i++]) - debug('stat "%s"', p); - fs.stat(p, function(err, stat){ - if (err) return next(err); + debug('stat "%s"', p) + fs.stat(p, function (err, stat) { + if (err) return next(err) - if (stat.isDirectory()) return next(); + if (stat.isDirectory()) return next() - self.emit('file', p, stat); - self.send(p, stat); - }); + self.emit('file', p, stat) + self.send(p, stat) + }) } next() diff --git a/test/send.js b/test/send.js index 1b075b9..bf34024 100644 --- a/test/send.js +++ b/test/send.js @@ -132,34 +132,31 @@ describe('send(file).pipe(res)', function () { .expect(200, '404 ENOENT', done) }) - it('should 301 if the directory exists', function(done){ + it('should 301 if the directory exists', function (done) { request(app) .get('/pets') .expect('Location', '/pets/') .expect(301, 'Redirecting to /pets/\n', done) }) - it("should not redirect on symbolic links", function(done){ + it('should not redirect on symbolic links', function (done) { var destination = 'name.txt' var path2 = path.join(fixtures, 'symlink') - fs.symlink(destination, path2, function(error) - { - if(error && error.code !== 'EEXIST') return done(error) + fs.symlink(destination, path2, function (error) { + if (error && error.code !== 'EEXIST') return done(error) request(app) .get('/symlink') - .expect(200, 'tobi', function(error) - { - fs.unlink(path2, function(error2) - { + .expect(200, 'tobi', function (error) { + fs.unlink(path2, function (error2) { done(error || error2) }) }) }) }) - it("should 301 if it's a symbolic link and we want to redirect", function(done){ + it("should 301 if it's a symbolic link and we want to redirect", function (done) { var app = http.createServer(function (req, res) { send(req, req.url, {root: fixtures, redirectSymlinks: true}) .on('error', function (err) { res.end(err.statusCode + ' ' + err.code) }) @@ -169,25 +166,22 @@ describe('send(file).pipe(res)', function () { var destination = 'name.txt' var path2 = path.join(fixtures, 'symlink') - fs.symlink(destination, path2, function(error) - { - if(error && error.code !== 'EEXIST') return done(error) + fs.symlink(destination, path2, function (error) { + if (error && error.code !== 'EEXIST') return done(error) request(app) .get('/symlink') .expect('Location', destination) - .expect(301, 'Redirecting to '+destination+'\n', function(error) - { - fs.unlink(path2, function(error2) - { + .expect(301, 'Redirecting to ' + destination + '\n', function (error) { + fs.unlink(path2, function (error2) { done(error || error2) }) }) }) }) - it('should not override content-type', function(done){ - var app = http.createServer(function(req, res){ + it('should not override content-type', function (done) { + var app = http.createServer(function (req, res) { res.setHeader('Content-Type', 'application/x-custom') send(req, req.url, {root: fixtures}).pipe(res) })