From 9ae08f932e11dcf53f938c8e6ef184cc2c5adf68 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 Jun 2015 01:17:42 -0400 Subject: [PATCH 01/39] build: should@6.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6dfbe7e3628..57f85757014 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "istanbul": "0.3.9", "marked": "0.3.3", "mocha": "2.2.5", - "should": "6.0.1", + "should": "6.0.3", "supertest": "1.0.1" }, "engines": { From a20a9a1a2e4dee052ca6832af6ae16a74c1ed9e0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 Jun 2015 01:21:20 -0400 Subject: [PATCH 02/39] deps: mkdirp@0.5.1 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index fbbed9e1357..8aa0e86df18 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +3.x +=== + + * deps: mkdirp@0.5.1 + - Work in global strict mode + 3.20.3 / 2015-05-17 =================== diff --git a/package.json b/package.json index 57f85757014..f4642558481 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "fresh": "0.2.4", "merge-descriptors": "1.0.0", "methods": "~1.1.1", - "mkdirp": "0.5.0", + "mkdirp": "0.5.1", "parseurl": "~1.3.0", "proxy-addr": "~1.0.8", "range-parser": "~1.0.2", From 29f51c67a612ecdf08494bc440f22918ce72a32e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 Jun 2015 01:24:21 -0400 Subject: [PATCH 03/39] docs: fix typos in history closes #2676 closes #2677 closes #2678 --- History.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 8aa0e86df18..e6af31f0b63 100644 --- a/History.md +++ b/History.md @@ -852,7 +852,7 @@ * update commander * jsonp: check if callback is a function * router: wrap encodeURIComponent in a try/catch #1735 (@lxe) - * res.format: now includes chraset @1747 (@sorribas) + * res.format: now includes charset @1747 (@sorribas) * res.links: allow multiple calls @1746 (@sorribas) 3.4.0 / 2013-09-07 @@ -1131,7 +1131,7 @@ * Added another example to content-negotiation * Added `fresh` dep * Changed: `res.send()` always checks freshness - * Fixed: expose connects mime module. Cloases #1165 + * Fixed: expose connects mime module. Closes #1165 3.0.0beta2 / 2012-06-06 ================== @@ -1213,7 +1213,7 @@ * Added `req.ips` * Added `req.fresh` * Added `req.stale` - * Added comma-delmited / array support for `req.accepts()` + * Added comma-delimited / array support for `req.accepts()` * Added debug instrumentation * Added `res.set(obj)` * Added `res.set(field, value)` From 62dfa792b26e32c99c27b07d490fa156d61a7782 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 20:08:32 -0400 Subject: [PATCH 04/39] deps: connect@2.30.0 --- History.md | 16 ++++++++++++++++ package.json | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e6af31f0b63..4fc52c4b75e 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,22 @@ 3.x === + * deps: connect@2.30.0 + - deps: body-parser@~1.13.1 + - deps: bytes@2.1.0 + - deps: compression@~1.5.0 + - deps: cookie@0.1.3 + - deps: cookie-parser@~1.3.5 + - deps: csurf@~1.8.3 + - deps: errorhandler@~1.4.0 + - deps: express-session@~1.11.3 + - deps: finalhandler@0.4.0 + - deps: fresh@0.3.0 + - deps: morgan@~1.6.0 + - deps: serve-favicon@~2.3.0 + - deps: serve-index@~1.7.0 + - deps: serve-static@~1.10.0 + - deps: type-is@~1.6.3 * deps: mkdirp@0.5.1 - Work in global strict mode diff --git a/package.json b/package.json index f4642558481..e060ace59a4 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ ], "dependencies": { "basic-auth": "1.0.0", - "connect": "2.29.2", + "connect": "2.30.0", "content-disposition": "0.5.0", "content-type": "~1.0.1", "commander": "2.6.0", From 92b5fa8c53fd451623523a41c3cedfd2efb8f4aa Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 20:10:16 -0400 Subject: [PATCH 05/39] build: should@7.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e060ace59a4..123a2c5ee64 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "istanbul": "0.3.9", "marked": "0.3.3", "mocha": "2.2.5", - "should": "6.0.3", + "should": "7.0.1", "supertest": "1.0.1" }, "engines": { From 5207b99e0874df268cb8f54eabedb314485890cd Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 20:34:04 -0400 Subject: [PATCH 06/39] deps: basic-auth@1.0.2 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 4fc52c4b75e..e681d5d75b1 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,11 @@ 3.x === + * deps: basic-auth@1.0.2 + - perf: enable strict mode + - perf: hoist regular expression + - perf: parse with regular expressions + - perf: remove argument reassignment * deps: connect@2.30.0 - deps: body-parser@~1.13.1 - deps: bytes@2.1.0 diff --git a/package.json b/package.json index 123a2c5ee64..7ce2bfc0c3e 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "api" ], "dependencies": { - "basic-auth": "1.0.0", + "basic-auth": "1.0.2", "connect": "2.30.0", "content-disposition": "0.5.0", "content-type": "~1.0.1", From 77402110b9402a6d327e232cc1518bc5110e651c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 20:35:56 -0400 Subject: [PATCH 07/39] deps: cookie@0.1.3 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e681d5d75b1..3d09788d390 100644 --- a/History.md +++ b/History.md @@ -22,6 +22,9 @@ - deps: serve-index@~1.7.0 - deps: serve-static@~1.10.0 - deps: type-is@~1.6.3 + * deps: cookie@0.1.3 + - perf: deduce the scope of try-catch deopt + - perf: remove argument reassignments * deps: mkdirp@0.5.1 - Work in global strict mode diff --git a/package.json b/package.json index 7ce2bfc0c3e..80e444a6749 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "content-disposition": "0.5.0", "content-type": "~1.0.1", "commander": "2.6.0", - "cookie": "0.1.2", + "cookie": "0.1.3", "cookie-signature": "1.0.6", "debug": "~2.2.0", "depd": "~1.0.1", From 0fbf2078e16cd315fd1b1769c430488f70e7faba Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 20:36:48 -0400 Subject: [PATCH 08/39] deps: escape-html@1.0.2 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 3d09788d390..a533c2415db 100644 --- a/History.md +++ b/History.md @@ -25,6 +25,7 @@ * deps: cookie@0.1.3 - perf: deduce the scope of try-catch deopt - perf: remove argument reassignments + * deps: escape-html@1.0.2 * deps: mkdirp@0.5.1 - Work in global strict mode diff --git a/package.json b/package.json index 80e444a6749..a771f9f42f4 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "cookie-signature": "1.0.6", "debug": "~2.2.0", "depd": "~1.0.1", - "escape-html": "1.0.1", + "escape-html": "1.0.2", "etag": "~1.5.1", "fresh": "0.2.4", "merge-descriptors": "1.0.0", From c8d61b62693948568083d5ad3c4491e5cc6f5338 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 20:54:26 -0400 Subject: [PATCH 09/39] deps: etag@~1.7.0 fixes #2667 --- History.md | 8 ++++++++ package.json | 2 +- test/res.send.js | 18 +++++++++--------- test/utils.js | 16 ++++++++-------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/History.md b/History.md index a533c2415db..6ed7c762c23 100644 --- a/History.md +++ b/History.md @@ -26,6 +26,14 @@ - perf: deduce the scope of try-catch deopt - perf: remove argument reassignments * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Always include entity length in ETags for hash length extensions + - Generate non-Stats ETags using MD5 only (no longer CRC32) + - Improve stat performance by removing hashing + - Improve support for JXcore + - Remove base64 padding in ETags to shorten + - Support "fake" stats objects in environments without fs + - Use MD5 instead of MD4 in weak ETags over 1KB * deps: mkdirp@0.5.1 - Work in global strict mode diff --git a/package.json b/package.json index a771f9f42f4..f3d51791a9d 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "debug": "~2.2.0", "depd": "~1.0.1", "escape-html": "1.0.2", - "etag": "~1.5.1", + "etag": "~1.7.0", "fresh": "0.2.4", "merge-descriptors": "1.0.0", "methods": "~1.1.1", diff --git a/test/res.send.js b/test/res.send.js index 9ad8fd88fee..67f872285c5 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -121,7 +121,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"fz/jGo0ONwzb+aKy/rWipg=="') + .expect('ETag', 'W/"7ff-fFD7Se+Vsq6deAl063thow"') .expect(200, done); }) @@ -193,7 +193,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"fz/jGo0ONwzb+aKy/rWipg=="') + .expect('ETag', 'W/"7ff-fFD7Se+Vsq6deAl063thow"') .expect(200, done); }) @@ -309,7 +309,7 @@ describe('res', function(){ request(app) .get('/') - .set('If-None-Match', 'W/"fz/jGo0ONwzb+aKy/rWipg=="') + .set('If-None-Match', 'W/"7ff-fFD7Se+Vsq6deAl063thow"') .expect(304, done); }) @@ -355,7 +355,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"c-5aee35d8"') + .expect('ETag', 'W/"c-ZUfd0NJ26qwjlKF4r8qb2g"') .expect(200, done); }); @@ -371,7 +371,7 @@ describe('res', function(){ request(app) [method]('/') - .expect('ETag', 'W/"c-5aee35d8"') + .expect('ETag', 'W/"c-ZUfd0NJ26qwjlKF4r8qb2g"') .expect(200, done); }) }); @@ -387,7 +387,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"0-0"') + .expect('ETag', 'W/"0-1B2M2Y8AsgTpgAmY7PhCfg"') .expect(200, done); }) @@ -403,7 +403,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"fz/jGo0ONwzb+aKy/rWipg=="') + .expect('ETag', 'W/"7ff-fFD7Se+Vsq6deAl063thow"') .expect(200, done); }); @@ -485,7 +485,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', '"Otu60XkfuuPskIiUxJY4cA=="') + .expect('ETag', '"d-Otu60XkfuuPskIiUxJY4cA"') .expect(200, done); }) }) @@ -502,7 +502,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"d-58988d13"') + .expect('ETag', 'W/"d-Otu60XkfuuPskIiUxJY4cA"') .expect(200, done) }) }) diff --git a/test/utils.js b/test/utils.js index b811762c591..750c84605f3 100644 --- a/test/utils.js +++ b/test/utils.js @@ -5,46 +5,46 @@ var utils = require('../lib/utils') describe('utils.etag(body, encoding)', function(){ it('should support strings', function(){ utils.etag('express!') - .should.eql('"zZdv4imtWD49AHEviejT6A=="') + .should.eql('"8-zZdv4imtWD49AHEviejT6A"') }) it('should support utf8 strings', function(){ utils.etag('express❤', 'utf8') - .should.eql('"fsFba4IxwQS6h6Umb+FNxw=="') + .should.eql('"a-fsFba4IxwQS6h6Umb+FNxw"') }) it('should support buffer', function(){ var buf = new Buffer('express!') utils.etag(buf) - .should.eql('"zZdv4imtWD49AHEviejT6A=="'); + .should.eql('"8-zZdv4imtWD49AHEviejT6A"'); }) it('should support empty string', function(){ utils.etag('') - .should.eql('"1B2M2Y8AsgTpgAmY7PhCfg=="'); + .should.eql('"0-1B2M2Y8AsgTpgAmY7PhCfg"'); }) }) describe('utils.wetag(body, encoding)', function(){ it('should support strings', function(){ utils.wetag('express!') - .should.eql('W/"8-b8aabac7"') + .should.eql('W/"8-zZdv4imtWD49AHEviejT6A"') }) it('should support utf8 strings', function(){ utils.wetag('express❤', 'utf8') - .should.eql('W/"a-686b0af1"') + .should.eql('W/"a-fsFba4IxwQS6h6Umb+FNxw"') }) it('should support buffer', function(){ var buf = new Buffer('express!') utils.wetag(buf) - .should.eql('W/"8-b8aabac7"'); + .should.eql('W/"8-zZdv4imtWD49AHEviejT6A"'); }) it('should support empty string', function(){ utils.wetag('') - .should.eql('W/"0-0"'); + .should.eql('W/"0-1B2M2Y8AsgTpgAmY7PhCfg"'); }) }) From 14b849246e9b72eb61dd9118b0409ca49d50f55e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 20:56:03 -0400 Subject: [PATCH 10/39] deps: send@0.13.0 --- History.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 6ed7c762c23..6c3684d8942 100644 --- a/History.md +++ b/History.md @@ -36,6 +36,19 @@ - Use MD5 instead of MD4 in weak ETags over 1KB * deps: mkdirp@0.5.1 - Work in global strict mode + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations 3.20.3 / 2015-05-17 =================== diff --git a/package.json b/package.json index f3d51791a9d..a36a43c3824 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "parseurl": "~1.3.0", "proxy-addr": "~1.0.8", "range-parser": "~1.0.2", - "send": "0.12.3", + "send": "0.13.0", "utils-merge": "1.0.0", "vary": "~1.0.0" }, From 4729685912b8d69c53739b04a2f3477b67dcc602 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 20:56:48 -0400 Subject: [PATCH 11/39] deps: fresh@0.3.0 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 6c3684d8942..dbe149cddd5 100644 --- a/History.md +++ b/History.md @@ -34,6 +34,8 @@ - Remove base64 padding in ETags to shorten - Support "fake" stats objects in environments without fs - Use MD5 instead of MD4 in weak ETags over 1KB + * deps: fresh@0.3.0 + - Add weak `ETag` matching support * deps: mkdirp@0.5.1 - Work in global strict mode * deps: send@0.13.0 diff --git a/package.json b/package.json index a36a43c3824..7b077c9b9ad 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "depd": "~1.0.1", "escape-html": "1.0.2", "etag": "~1.7.0", - "fresh": "0.2.4", + "fresh": "0.3.0", "merge-descriptors": "1.0.0", "methods": "~1.1.1", "mkdirp": "0.5.1", From 115dbe1a4d817d925d2dc87731a7ceb1663152ed Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 21:14:56 -0400 Subject: [PATCH 12/39] 3.21.0 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index dbe149cddd5..bb06bdb6f42 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -3.x -=== +3.21.0 / 2015-06-18 +=================== * deps: basic-auth@1.0.2 - perf: enable strict mode diff --git a/package.json b/package.json index 7b077c9b9ad..e8d2f00395f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Sinatra inspired web development framework", - "version": "3.20.3", + "version": "3.21.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 8da51e3acc0520f67daa92309e294a72a6256726 Mon Sep 17 00:00:00 2001 From: Radu Dan Date: Tue, 19 May 2015 22:37:06 +0300 Subject: [PATCH 13/39] Fix issue where next('route') in app.param would incorrectly skip values fixes #2655 --- History.md | 1 + lib/router/index.js | 3 ++- test/app.param.js | 60 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0f57672d34e..06c2c2be323 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Fix issue where `next('route')` in `app.param` would incorrectly skip values * deps: cookie@0.1.3 - perf: deduce the scope of try-catch deopt - perf: remove argument reassignments diff --git a/lib/router/index.js b/lib/router/index.js index 209f881b1eb..a20c592f075 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -357,7 +357,8 @@ proto.process_params = function(layer, called, req, res, done) { } // param previously called with same value or error occurred - if (paramCalled && (paramCalled.error || paramCalled.match === paramVal)) { + if (paramCalled && (paramCalled.match === paramVal + || (paramCalled.error && paramCalled.error !== 'route'))) { // restore value req.params[name] = paramCalled.value; diff --git a/test/app.param.js b/test/app.param.js index 858ea2d5f6a..30885bcdc89 100644 --- a/test/app.param.js +++ b/test/app.param.js @@ -303,5 +303,65 @@ describe('app', function(){ .get('/user/new') .expect('get.new', done); }) + + it('should not call when values differ on error', function(done) { + var app = express(); + var called = 0; + var count = 0; + + app.param('user', function(req, res, next, user) { + called++; + if (user === 'foo') throw new Error('err!'); + req.user = user; + next(); + }); + + app.get('/:user/bob', function(req, res, next) { + count++; + next(); + }); + app.get('/foo/:user', function(req, res, next) { + count++; + next(); + }); + + app.use(function(err, req, res, next) { + res.status(500); + res.send([count, called, err.message].join(' ')); + }); + + request(app) + .get('/foo/bob') + .expect(500, '0 1 err!', done) + }); + + it('should call when values differ when using "next"', function(done) { + var app = express(); + var called = 0; + var count = 0; + + app.param('user', function(req, res, next, user) { + called++; + if (user === 'foo') return next('route'); + req.user = user; + next(); + }); + + app.get('/:user/bob', function(req, res, next) { + count++; + next(); + }); + app.get('/foo/:user', function(req, res, next) { + count++; + next(); + }); + app.use(function(req, res) { + res.end([count, called, req.user].join(' ')); + }); + + request(app) + .get('/foo/bob') + .expect('1 2 bob', done); + }) }) }) From f7e94a30bce66ba4de1b6388910bfdd8b1e6edd1 Mon Sep 17 00:00:00 2001 From: Deepak Kapoor Date: Wed, 22 Apr 2015 17:36:55 +1000 Subject: [PATCH 14/39] Use array-flatten module for flattening arrays closes #2624 --- History.md | 1 + lib/application.js | 2 +- lib/router/index.js | 4 ++-- lib/router/route.js | 6 +++--- lib/utils.js | 15 +++------------ package.json | 1 + 6 files changed, 11 insertions(+), 18 deletions(-) diff --git a/History.md b/History.md index 06c2c2be323..de6a68f0ca8 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ unreleased ========== * Fix issue where `next('route')` in `app.param` would incorrectly skip values + * Use `array-flatten` module for flattening arrays * deps: cookie@0.1.3 - perf: deduce the scope of try-catch deopt - perf: remove argument reassignments diff --git a/lib/application.js b/lib/application.js index 5ec44248cad..fe386d7b368 100644 --- a/lib/application.js +++ b/lib/application.js @@ -12,7 +12,6 @@ */ var finalhandler = require('finalhandler'); -var flatten = require('./utils').flatten; var Router = require('./router'); var methods = require('methods'); var middleware = require('./middleware/init'); @@ -24,6 +23,7 @@ var compileETag = require('./utils').compileETag; var compileQueryParser = require('./utils').compileQueryParser; var compileTrust = require('./utils').compileTrust; var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); var merge = require('utils-merge'); var resolve = require('path').resolve; var slice = Array.prototype.slice; diff --git a/lib/router/index.js b/lib/router/index.js index a20c592f075..d0989da2090 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -9,8 +9,8 @@ var methods = require('methods'); var mixin = require('utils-merge'); var debug = require('debug')('express:router'); var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); var parseUrl = require('parseurl'); -var utils = require('../utils'); /** * Module variables. @@ -436,7 +436,7 @@ proto.use = function use(fn) { } } - var callbacks = utils.flatten(slice.call(arguments, offset)); + var callbacks = flatten(slice.call(arguments, offset)); if (callbacks.length === 0) { throw new TypeError('Router.use() requires middleware functions'); diff --git a/lib/router/route.js b/lib/router/route.js index 6213b821704..d3ef53bc176 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -3,9 +3,9 @@ */ var debug = require('debug')('express:router:route'); +var flatten = require('array-flatten'); var Layer = require('./layer'); var methods = require('methods'); -var utils = require('../utils'); /** * Expose `Route`. @@ -141,7 +141,7 @@ Route.prototype.dispatch = function(req, res, done){ */ Route.prototype.all = function(){ - var callbacks = utils.flatten([].slice.call(arguments)); + var callbacks = flatten([].slice.call(arguments)); callbacks.forEach(function(fn) { if (typeof fn !== 'function') { var type = {}.toString.call(fn); @@ -161,7 +161,7 @@ Route.prototype.all = function(){ methods.forEach(function(method){ Route.prototype[method] = function(){ - var callbacks = utils.flatten([].slice.call(arguments)); + var callbacks = flatten([].slice.call(arguments)); callbacks.forEach(function(fn) { if (typeof fn !== 'function') { diff --git a/lib/utils.js b/lib/utils.js index ce53ad8b99b..42ea76acde6 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -13,6 +13,7 @@ var contentDisposition = require('content-disposition'); var contentType = require('content-type'); var deprecate = require('depd')('express'); +var flatten = require('array-flatten'); var mime = require('send').mime; var basename = require('path').basename; var etag = require('etag'); @@ -76,18 +77,8 @@ exports.isAbsolute = function(path){ * @api private */ -exports.flatten = function(arr, ret){ - ret = ret || []; - var len = arr.length; - for (var i = 0; i < len; ++i) { - if (Array.isArray(arr[i])) { - exports.flatten(arr[i], ret); - } else { - ret.push(arr[i]); - } - } - return ret; -}; +exports.flatten = deprecate.function(flatten, + 'utils.flatten: use array-flatten npm module instead'); /** * Normalize the given `type`, for example "html" becomes "text/html". diff --git a/package.json b/package.json index 74efb91cc06..e14953f13b9 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ ], "dependencies": { "accepts": "~1.2.7", + "array-flatten": "1.1.0", "content-disposition": "0.5.0", "content-type": "~1.0.1", "cookie": "0.1.3", From b5f98ab3b3861161a92fee7f64a22cbb04f85ba9 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 22:26:48 -0400 Subject: [PATCH 15/39] deps: serve-static@~1.10.0 --- History.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index de6a68f0ca8..1acab96b1ef 100644 --- a/History.md +++ b/History.md @@ -30,6 +30,15 @@ unreleased - deps: on-finished@~2.3.0 - perf: enable strict mode - perf: remove unnecessary array allocations + * deps: serve-static@~1.10.0 + - Add `fallthrough` option + - Fix reading options from options prototype + - Improve the default redirect response headers + - Malformed URLs now `next()` instead of 400 + - deps: escape-html@1.0.2 + - deps: send@0.13.0 + - perf: enable strict mode + - perf: remove argument reassignment 4.12.4 / 2015-05-17 =================== diff --git a/package.json b/package.json index e14953f13b9..2e3fa5be1ed 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "qs": "2.4.2", "range-parser": "~1.0.2", "send": "0.13.0", - "serve-static": "~1.9.3", + "serve-static": "~1.10.0", "type-is": "~1.6.2", "vary": "~1.0.0", "utils-merge": "1.0.0" From 7b7aaf0bf3c8a245c7e9a0ac91af314adba4ea1d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 22:39:57 -0400 Subject: [PATCH 16/39] deps: finalhandler@0.4.0 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 1acab96b1ef..2f41a60a81b 100644 --- a/History.md +++ b/History.md @@ -15,6 +15,14 @@ unreleased - Remove base64 padding in ETags to shorten - Support "fake" stats objects in environments without fs - Use MD5 instead of MD4 in weak ETags over 1KB + * deps: finalhandler@0.4.0 + - Fix a false-positive when unpiping in Node.js 0.8 + - Support `statusCode` property on `Error` objects + - Use `unpipe` module for unpiping requests + - deps: escape-html@1.0.2 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove argument reassignment * deps: fresh@0.3.0 - Add weak `ETag` matching support * deps: send@0.13.0 diff --git a/package.json b/package.json index 2e3fa5be1ed..a2e66089bcf 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "depd": "~1.0.1", "escape-html": "1.0.2", "etag": "~1.7.0", - "finalhandler": "0.3.6", + "finalhandler": "0.4.0", "fresh": "0.3.0", "merge-descriptors": "1.0.0", "methods": "~1.1.1", From 8ad7e8f5e143768ef62adbde899e5b9099185f52 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 22:41:28 -0400 Subject: [PATCH 17/39] deps: on-finished@~2.3.0 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2f41a60a81b..65de61f8729 100644 --- a/History.md +++ b/History.md @@ -25,6 +25,10 @@ unreleased - perf: remove argument reassignment * deps: fresh@0.3.0 - Add weak `ETag` matching support + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 * deps: send@0.13.0 - Allow Node.js HTTP server to set `Date` response header - Fix incorrectly removing `Content-Location` on 304 response diff --git a/package.json b/package.json index a2e66089bcf..19cf6ad615a 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "fresh": "0.3.0", "merge-descriptors": "1.0.0", "methods": "~1.1.1", - "on-finished": "~2.2.1", + "on-finished": "~2.3.0", "parseurl": "~1.3.0", "path-to-regexp": "0.1.3", "proxy-addr": "~1.0.8", From 7b86a0ec98690784f196efa6ca5ba1ccf4c9e10f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 22:42:19 -0400 Subject: [PATCH 18/39] deps: type-is@~1.6.3 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 65de61f8729..9a0f49ac0fd 100644 --- a/History.md +++ b/History.md @@ -51,6 +51,10 @@ unreleased - deps: send@0.13.0 - perf: enable strict mode - perf: remove argument reassignment + * deps: type-is@~1.6.3 + - deps: mime-types@~2.1.1 + - perf: reduce try block size + - perf: remove bitwise operations 4.12.4 / 2015-05-17 =================== diff --git a/package.json b/package.json index 19cf6ad615a..43376f4a817 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "range-parser": "~1.0.2", "send": "0.13.0", "serve-static": "~1.10.0", - "type-is": "~1.6.2", + "type-is": "~1.6.3", "vary": "~1.0.0", "utils-merge": "1.0.0" }, From 4212efad74aa002d0e722b80c66f058b6b2b3969 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 22:43:51 -0400 Subject: [PATCH 19/39] deps: accepts@~1.2.9 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 9a0f49ac0fd..0db529dcfd5 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,12 @@ unreleased * Fix issue where `next('route')` in `app.param` would incorrectly skip values * Use `array-flatten` module for flattening arrays + * deps: accepts@~1.2.9 + - deps: mime-types@~2.1.1 + - perf: avoid argument reassignment & argument slice + - perf: avoid negotiator recursive construction + - perf: enable strict mode + - perf: remove unnecessary bitwise operator * deps: cookie@0.1.3 - perf: deduce the scope of try-catch deopt - perf: remove argument reassignments diff --git a/package.json b/package.json index 43376f4a817..e5a66451b4c 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "api" ], "dependencies": { - "accepts": "~1.2.7", + "accepts": "~1.2.9", "array-flatten": "1.1.0", "content-disposition": "0.5.0", "content-type": "~1.0.1", From 9073bb4fbc7e5b4b53d00696a3cda0678502379a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 22:45:33 -0400 Subject: [PATCH 20/39] deps: update example dependencies --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e5a66451b4c..0d1858911e5 100644 --- a/package.json +++ b/package.json @@ -61,14 +61,14 @@ "mocha": "2.2.5", "should": "7.0.1", "supertest": "1.0.1", - "body-parser": "~1.12.4", + "body-parser": "~1.13.1", "connect-redis": "~2.3.0", - "cookie-parser": "~1.3.4", + "cookie-parser": "~1.3.5", "cookie-session": "~1.1.0", - "express-session": "~1.11.2", - "jade": "~1.9.2", + "express-session": "~1.11.3", + "jade": "~1.11.0", "method-override": "~2.3.3", - "morgan": "~1.5.3", + "morgan": "~1.6.0", "multiparty": "~4.1.2", "vhost": "~3.0.0" }, From 91731b4b9ce23fe4bb702f341d0a46d78c8ccdbf Mon Sep 17 00:00:00 2001 From: Thomas Cort Date: Mon, 23 Mar 2015 07:31:21 -0400 Subject: [PATCH 21/39] perf: use saved reference to http.STATUS_CODES closes #2602 --- History.md | 1 + lib/response.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 0db529dcfd5..d33981cdf8f 100644 --- a/History.md +++ b/History.md @@ -61,6 +61,7 @@ unreleased - deps: mime-types@~2.1.1 - perf: reduce try block size - perf: remove bitwise operations + * perf: use saved reference to `http.STATUS_CODES` 4.12.4 / 2015-05-17 =================== diff --git a/lib/response.js b/lib/response.js index 1874300c514..8a976217a24 100644 --- a/lib/response.js +++ b/lib/response.js @@ -119,7 +119,7 @@ res.send = function send(body) { deprecate('res.send(status): Use res.sendStatus(status) instead'); this.statusCode = chunk; - chunk = http.STATUS_CODES[chunk]; + chunk = statusCodes[chunk]; } switch (typeof chunk) { @@ -324,7 +324,7 @@ res.jsonp = function jsonp(obj) { */ res.sendStatus = function sendStatus(statusCode) { - var body = http.STATUS_CODES[statusCode] || String(statusCode); + var body = statusCodes[statusCode] || String(statusCode); this.statusCode = statusCode; this.type('txt'); From 95ad276cad3369bf5f7253d0110a6e04425bd32a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 23:00:20 -0400 Subject: [PATCH 22/39] docs: add license comments --- index.js | 7 +++++++ lib/express.js | 8 ++++++++ lib/middleware/init.js | 8 ++++++++ lib/middleware/query.js | 8 ++++++++ lib/request.js | 8 ++++++++ lib/router/index.js | 7 +++++++ lib/router/layer.js | 8 ++++++++ lib/router/route.js | 8 ++++++++ lib/view.js | 8 ++++++++ 9 files changed, 70 insertions(+) diff --git a/index.js b/index.js index 3da33783794..e6cf8225c2e 100644 --- a/index.js +++ b/index.js @@ -1,2 +1,9 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ module.exports = require('./lib/express'); diff --git a/lib/express.js b/lib/express.js index bb8d8082a49..0d06c8205d7 100644 --- a/lib/express.js +++ b/lib/express.js @@ -1,3 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + /** * Module dependencies. */ diff --git a/lib/middleware/init.js b/lib/middleware/init.js index 1e3e903f04f..0c3644da1b9 100644 --- a/lib/middleware/init.js +++ b/lib/middleware/init.js @@ -1,3 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + /** * Initialization middleware, exposing the * request and response to each other, as well diff --git a/lib/middleware/query.js b/lib/middleware/query.js index 092bbd9985d..80d65859e98 100644 --- a/lib/middleware/query.js +++ b/lib/middleware/query.js @@ -1,3 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + /** * Module dependencies. */ diff --git a/lib/request.js b/lib/request.js index 99964925572..4d756deb900 100644 --- a/lib/request.js +++ b/lib/request.js @@ -1,3 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + /** * Module dependencies. */ diff --git a/lib/router/index.js b/lib/router/index.js index d0989da2090..d79a1eb4ce3 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -1,3 +1,10 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ /** * Module dependencies. diff --git a/lib/router/layer.js b/lib/router/layer.js index 88ebd3964c2..cc8a1f2c7b4 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -1,3 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + /** * Module dependencies. */ diff --git a/lib/router/route.js b/lib/router/route.js index d3ef53bc176..adb833cef96 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -1,3 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + /** * Module dependencies. */ diff --git a/lib/view.js b/lib/view.js index e0989b4ddac..acde752ebbd 100644 --- a/lib/view.js +++ b/lib/view.js @@ -1,3 +1,11 @@ +/*! + * express + * Copyright(c) 2009-2013 TJ Holowaychuk + * Copyright(c) 2013 Roman Shtylman + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + /** * Module dependencies. */ From e71014f522fb8db9ba1ef634f2e9f2c8069e4b6c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 23:01:18 -0400 Subject: [PATCH 23/39] perf: enable strict mode --- History.md | 1 + index.js | 2 ++ lib/application.js | 2 ++ lib/express.js | 2 ++ lib/middleware/init.js | 2 ++ lib/middleware/query.js | 2 ++ lib/request.js | 2 ++ lib/response.js | 2 ++ lib/router/index.js | 2 ++ lib/router/layer.js | 2 ++ lib/router/route.js | 2 ++ lib/utils.js | 2 ++ lib/view.js | 2 ++ 13 files changed, 25 insertions(+) diff --git a/History.md b/History.md index d33981cdf8f..f36c515619f 100644 --- a/History.md +++ b/History.md @@ -61,6 +61,7 @@ unreleased - deps: mime-types@~2.1.1 - perf: reduce try block size - perf: remove bitwise operations + * perf: enable strict mode * perf: use saved reference to `http.STATUS_CODES` 4.12.4 / 2015-05-17 diff --git a/index.js b/index.js index e6cf8225c2e..d219b0c878d 100644 --- a/index.js +++ b/index.js @@ -6,4 +6,6 @@ * MIT Licensed */ +'use strict'; + module.exports = require('./lib/express'); diff --git a/lib/application.js b/lib/application.js index fe386d7b368..b31c88b7b05 100644 --- a/lib/application.js +++ b/lib/application.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. * @api private diff --git a/lib/express.js b/lib/express.js index 0d06c8205d7..540c8be6f41 100644 --- a/lib/express.js +++ b/lib/express.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. */ diff --git a/lib/middleware/init.js b/lib/middleware/init.js index 0c3644da1b9..f3119ed3a15 100644 --- a/lib/middleware/init.js +++ b/lib/middleware/init.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Initialization middleware, exposing the * request and response to each other, as well diff --git a/lib/middleware/query.js b/lib/middleware/query.js index 80d65859e98..d86474a05a5 100644 --- a/lib/middleware/query.js +++ b/lib/middleware/query.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. */ diff --git a/lib/request.js b/lib/request.js index 4d756deb900..962f48d094d 100644 --- a/lib/request.js +++ b/lib/request.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. */ diff --git a/lib/response.js b/lib/response.js index 8a976217a24..50b0579b57e 100644 --- a/lib/response.js +++ b/lib/response.js @@ -5,6 +5,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. * @api private diff --git a/lib/router/index.js b/lib/router/index.js index d79a1eb4ce3..8786dc15d3e 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. */ diff --git a/lib/router/layer.js b/lib/router/layer.js index cc8a1f2c7b4..4747f70bea4 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. */ diff --git a/lib/router/route.js b/lib/router/route.js index adb833cef96..dadd2c7b6d4 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. */ diff --git a/lib/utils.js b/lib/utils.js index 42ea76acde6..d10391c43d9 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -5,6 +5,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. * @api private diff --git a/lib/view.js b/lib/view.js index acde752ebbd..072422180c6 100644 --- a/lib/view.js +++ b/lib/view.js @@ -6,6 +6,8 @@ * MIT Licensed */ +'use strict'; + /** * Module dependencies. */ From 24d1c98c0ae4cc5dfd79bfff5d536a95034f7569 Mon Sep 17 00:00:00 2001 From: Behcet Uyar Date: Fri, 29 May 2015 17:13:15 -0400 Subject: [PATCH 24/39] Fix res.format error when only default provided fixes #2665 --- History.md | 1 + lib/response.js | 4 +++- test/res.format.js | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index f36c515619f..7c33d28450f 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Fix `res.format` error when only `default` provided * Fix issue where `next('route')` in `app.param` would incorrectly skip values * Use `array-flatten` module for flattening arrays * deps: accepts@~1.2.9 diff --git a/lib/response.js b/lib/response.js index 50b0579b57e..5334515eeb4 100644 --- a/lib/response.js +++ b/lib/response.js @@ -606,7 +606,9 @@ res.format = function(obj){ if (fn) delete obj.default; var keys = Object.keys(obj); - var key = req.accepts(keys); + var key = keys.length > 0 + ? req.accepts(keys) + : false; this.vary("Accept"); diff --git a/test/res.format.js b/test/res.format.js index 28534a199a1..2b0dfd517e7 100644 --- a/test/res.format.js +++ b/test/res.format.js @@ -67,6 +67,14 @@ app4.use(function(err, req, res, next){ res.send(err.status, 'Supports: ' + err.types.join(', ')); }) +var app5 = express(); + +app5.use(function (req, res, next) { + res.format({ + default: function () { res.send('hey') } + }); +}); + describe('res', function(){ describe('.format(obj)', function(){ describe('with canonicalized mime types', function(){ @@ -102,6 +110,13 @@ describe('res', function(){ .set('Accept', 'text/html') .expect('default', done); }) + + it('should work when only .default is provided', function (done) { + request(app5) + .get('/') + .set('Accept', '*/*') + .expect('hey', done); + }) }) describe('in router', function(){ From e66bb4f328c80540ba1b66ec4b8275d1a43941b5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Jun 2015 23:15:13 -0400 Subject: [PATCH 25/39] deps: path-to-regexp@0.1.4 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 7c33d28450f..4db593509e8 100644 --- a/History.md +++ b/History.md @@ -36,6 +36,7 @@ unreleased - Add defined behavior for HTTP `CONNECT` requests - Add defined behavior for HTTP `Upgrade` requests - deps: ee-first@1.1.1 + * deps: path-to-regexp@0.1.4 * deps: send@0.13.0 - Allow Node.js HTTP server to set `Date` response header - Fix incorrectly removing `Content-Location` on 304 response diff --git a/package.json b/package.json index 0d1858911e5..ba69a020565 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "methods": "~1.1.1", "on-finished": "~2.3.0", "parseurl": "~1.3.0", - "path-to-regexp": "0.1.3", + "path-to-regexp": "0.1.4", "proxy-addr": "~1.0.8", "qs": "2.4.2", "range-parser": "~1.0.2", From 60e2008dee01a90551623371da939de41c05422e Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Fri, 19 Jun 2015 22:13:57 +1000 Subject: [PATCH 26/39] deps: path-to-regexp@0.1.6 fixes #2491 fixes #2617 closes #2637 closes #2683 --- History.md | 4 +++- lib/router/layer.js | 16 +++++----------- package.json | 2 +- test/app.router.js | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/History.md b/History.md index 4db593509e8..c6b3cf81f8f 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ unreleased * Fix `res.format` error when only `default` provided * Fix issue where `next('route')` in `app.param` would incorrectly skip values + * Fix using `*` before params in routes + * Fix using capture groups before params in routes * Use `array-flatten` module for flattening arrays * deps: accepts@~1.2.9 - deps: mime-types@~2.1.1 @@ -36,7 +38,7 @@ unreleased - Add defined behavior for HTTP `CONNECT` requests - Add defined behavior for HTTP `Upgrade` requests - deps: ee-first@1.1.1 - * deps: path-to-regexp@0.1.4 + * deps: path-to-regexp@0.1.6 * deps: send@0.13.0 - Allow Node.js HTTP server to set `Date` response header - Fix incorrectly removing `Content-Location` on 304 response diff --git a/lib/router/layer.js b/lib/router/layer.js index 4747f70bea4..b5c1f58958b 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -133,17 +133,11 @@ Layer.prototype.match = function match(path) { var keys = this.keys; var params = this.params; - var prop; - var n = 0; - var key; - var val; - - for (var i = 1, len = m.length; i < len; ++i) { - key = keys[i - 1]; - prop = key - ? key.name - : n++; - val = decode_param(m[i]); + + for (var i = 1; i < m.length; i++) { + var key = keys[i - 1]; + var prop = key.name; + var val = decode_param(m[i]); if (val !== undefined || !(hasOwnProperty.call(params, prop))) { params[prop] = val; diff --git a/package.json b/package.json index ba69a020565..95a4a472f87 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "methods": "~1.1.1", "on-finished": "~2.3.0", "parseurl": "~1.3.0", - "path-to-regexp": "0.1.4", + "path-to-regexp": "0.1.6", "proxy-addr": "~1.0.8", "qs": "2.4.2", "range-parser": "~1.0.2", diff --git a/test/app.router.js b/test/app.router.js index def50da34fb..491de358f07 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -641,6 +641,30 @@ describe('app.router', function(){ .get('/file') .expect(404, done); }) + + it('should keep correct parameter indexes', function(done){ + var app = express(); + + app.get('/*/user/:id', function (req, res) { + res.send(req.params); + }); + + request(app) + .get('/1/user/2') + .expect(200, '{"0":"1","id":"2"}', done); + }) + + it('should work within arrays', function(done){ + var app = express(); + + app.get(['/user/:id', '/foo/*', '/:bar'], function (req, res) { + res.send(req.params.bar); + }); + + request(app) + .get('/test') + .expect(200, 'test', done); + }) }) describe(':name', function(){ @@ -680,6 +704,23 @@ describe('app.router', function(){ .expect('editing tj', done); }) + it('should work following a partial capture group', function(done){ + var app = express(); + var cb = after(2, done); + + app.get('/user(s)?/:user/:op', function(req, res){ + res.end(req.params.op + 'ing ' + req.params.user + (req.params[0] ? ' (old)' : '')); + }); + + request(app) + .get('/user/tj/edit') + .expect('editing tj', cb); + + request(app) + .get('/users/tj/edit') + .expect('editing tj (old)', cb); + }) + it('should work in array of paths', function(done){ var app = express(); var cb = after(2, done); From 0634e7e189a0ea12261b8fa81c7ca7234994b26d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 12:54:52 -0400 Subject: [PATCH 27/39] tests: add test for rendering extensionless file without view engine --- test/res.render.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/res.render.js b/test/res.render.js index a843b2af159..d4d2a7616d1 100644 --- a/test/res.render.js +++ b/test/res.render.js @@ -34,6 +34,20 @@ describe('res', function(){ .expect('

tobi

', done); }) + it('should error without "view engine" set and no file extension', function (done) { + var app = createApp(); + + app.locals.user = { name: 'tobi' }; + + app.use(function(req, res){ + res.render(__dirname + '/fixtures/user'); + }); + + request(app) + .get('/') + .expect(500, /No default engine was specified/, done); + }) + it('should expose app.locals', function(done){ var app = createApp(); From a8a8564459688bdc0b2653da2f28a4fefde7dfdb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 13:06:08 -0400 Subject: [PATCH 28/39] perf: remove argument reassignments in View --- History.md | 1 + lib/view.js | 73 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/History.md b/History.md index c6b3cf81f8f..c1cef158219 100644 --- a/History.md +++ b/History.md @@ -66,6 +66,7 @@ unreleased - perf: reduce try block size - perf: remove bitwise operations * perf: enable strict mode + * perf: remove argument reassignments in `View` * perf: use saved reference to `http.STATUS_CODES` 4.12.4 / 2015-05-17 diff --git a/lib/view.js b/lib/view.js index 072422180c6..52415d4c28b 100644 --- a/lib/view.js +++ b/lib/view.js @@ -10,6 +10,7 @@ /** * Module dependencies. + * @private */ var debug = require('debug')('express:view'); @@ -29,7 +30,8 @@ var join = path.join; var resolve = path.resolve; /** - * Expose `View`. + * Module exports. + * @public */ module.exports = View; @@ -43,30 +45,51 @@ module.exports = View; * - `engines` template engine require() cache * - `root` root path for view lookup * - * @param {String} name - * @param {Object} options - * @api private + * @param {string} name + * @param {object} options + * @public */ function View(name, options) { - options = options || {}; + var opts = options || {}; + + this.defaultEngine = opts.defaultEngine; + this.ext = extname(name); this.name = name; - this.root = options.root; - var engines = options.engines; - this.defaultEngine = options.defaultEngine; - var ext = this.ext = extname(name); - if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.'); - if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine); - this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express); - this.path = this.lookup(name); + this.root = opts.root; + + if (!this.ext && !this.defaultEngine) { + throw new Error('No default engine was specified and no extension was provided.'); + } + + var fileName = name; + + if (!this.ext) { + // get extension from default engine name + this.ext = this.defaultEngine[0] !== '.' + ? '.' + this.defaultEngine + : this.defaultEngine; + + fileName += this.ext; + } + + if (!opts.engines[this.ext]) { + // load engine + opts.engines[this.ext] = require(this.ext.substr(1)).__express; + } + + // store loaded engine + this.engine = opts.engines[this.ext]; + + // lookup path + this.path = this.lookup(fileName); } /** * Lookup view by the given `name` * - * @param {String} name - * @return {String} - * @api private + * @param {string} name + * @private */ View.prototype.lookup = function lookup(name) { @@ -91,16 +114,16 @@ View.prototype.lookup = function lookup(name) { }; /** - * Render with the given `options` and callback `fn(err, str)`. + * Render with the given options. * - * @param {Object} options - * @param {Function} fn - * @api private + * @param {object} options + * @param {function} callback + * @private */ -View.prototype.render = function render(options, fn) { +View.prototype.render = function render(options, callback) { debug('render "%s"', this.path); - this.engine(this.path, options, fn); + this.engine(this.path, options, callback); }; /** @@ -113,12 +136,10 @@ View.prototype.render = function render(options, fn) { View.prototype.resolve = function resolve(dir, file) { var ext = this.ext; - var path; - var stat; // . - path = join(dir, file); - stat = tryStat(path); + var path = join(dir, file); + var stat = tryStat(path); if (stat && stat.isFile()) { return path; From 10502480d0f286442654852dba4ec57f8d3391fd Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 13:31:03 -0400 Subject: [PATCH 29/39] perf: remove argument reassignments in application --- History.md | 1 + lib/application.js | 174 ++++++++++++++++++++++++++------------------- 2 files changed, 101 insertions(+), 74 deletions(-) diff --git a/History.md b/History.md index c1cef158219..84738af0966 100644 --- a/History.md +++ b/History.md @@ -66,6 +66,7 @@ unreleased - perf: reduce try block size - perf: remove bitwise operations * perf: enable strict mode + * perf: remove argument reassignments in application * perf: remove argument reassignments in `View` * perf: use saved reference to `http.STATUS_CODES` diff --git a/lib/application.js b/lib/application.js index b31c88b7b05..7db0f14d4ac 100644 --- a/lib/application.js +++ b/lib/application.js @@ -10,7 +10,7 @@ /** * Module dependencies. - * @api private + * @private */ var finalhandler = require('finalhandler'); @@ -38,7 +38,7 @@ var app = exports = module.exports = {}; /** * Variable for trust proxy inheritance back-compat - * @api private + * @private */ var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default'; @@ -50,27 +50,28 @@ var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default'; * - setup default middleware * - setup route reflection methods * - * @api private + * @private */ -app.init = function(){ +app.init = function init() { this.cache = {}; - this.settings = {}; this.engines = {}; + this.settings = {}; + this.defaultConfiguration(); }; /** * Initialize application configuration. - * - * @api private + * @private */ -app.defaultConfiguration = function(){ +app.defaultConfiguration = function defaultConfiguration() { + var env = process.env.NODE_ENV || 'development'; + // default settings this.enable('x-powered-by'); this.set('etag', 'weak'); - var env = process.env.NODE_ENV || 'development'; this.set('env', env); this.set('query parser', 'extended'); this.set('subdomain offset', 2); @@ -130,9 +131,9 @@ app.defaultConfiguration = function(){ * We cannot add the base router in the defaultConfiguration because * it reads app settings which might be set after that has run. * - * @api private + * @private */ -app.lazyrouter = function() { +app.lazyrouter = function lazyrouter() { if (!this._router) { this._router = new Router({ caseSensitive: this.enabled('case sensitive routing'), @@ -147,17 +148,17 @@ app.lazyrouter = function() { /** * Dispatch a req, res pair into the application. Starts pipeline processing. * - * If no _done_ callback is provided, then default error handlers will respond + * If no callback is provided, then default error handlers will respond * in the event of an error bubbling through the stack. * - * @api private + * @private */ -app.handle = function(req, res, done) { +app.handle = function handle(req, res, callback) { var router = this._router; // final handler - done = done || finalhandler(req, res, { + var done = callback || finalhandler(req, res, { env: this.get('env'), onerror: logerror.bind(this) }); @@ -179,7 +180,7 @@ app.handle = function(req, res, done) { * If the _fn_ parameter is an express app, then it will be * mounted at the _route_ specified. * - * @api public + * @public */ app.use = function use(fn) { @@ -246,10 +247,10 @@ app.use = function use(fn) { * Routes are isolated middleware stacks for specific paths. * See the Route api docs for details. * - * @api public + * @public */ -app.route = function(path){ +app.route = function route(path) { this.lazyrouter(); return this._router.route(path); }; @@ -285,13 +286,22 @@ app.route = function(path){ * @param {String} ext * @param {Function} fn * @return {app} for chaining - * @api public + * @public */ -app.engine = function(ext, fn){ - if ('function' != typeof fn) throw new Error('callback function required'); - if ('.' != ext[0]) ext = '.' + ext; - this.engines[ext] = fn; +app.engine = function engine(ext, fn) { + if (typeof fn !== 'function') { + throw new Error('callback function required'); + } + + // get file extension + var extension = ext[0] !== '.' + ? '.' + ext + : ext; + + // store engine + this.engines[extension] = fn; + return this; }; @@ -304,20 +314,22 @@ app.engine = function(ext, fn){ * @param {String|Array} name * @param {Function} fn * @return {app} for chaining - * @api public + * @public */ -app.param = function(name, fn){ +app.param = function param(name, fn) { this.lazyrouter(); if (Array.isArray(name)) { - name.forEach(function(key) { - this.param(key, fn); - }, this); + for (var i = 0; i < name.length; i++) { + this.param(name[i], fn); + } + return this; } this._router.param(name, fn); + return this; }; @@ -333,10 +345,10 @@ app.param = function(name, fn){ * @param {String} setting * @param {*} [val] * @return {Server} for chaining - * @api public + * @public */ -app.set = function(setting, val){ +app.set = function set(setting, val) { if (arguments.length === 1) { // app.get(setting) return this.settings[setting]; @@ -382,10 +394,10 @@ app.set = function(setting, val){ * return value would be "/blog/admin". * * @return {String} - * @api private + * @private */ -app.path = function(){ +app.path = function path() { return this.parent ? this.parent.path() + this.mountpath : ''; @@ -403,11 +415,11 @@ app.path = function(){ * * @param {String} setting * @return {Boolean} - * @api public + * @public */ -app.enabled = function(setting){ - return !!this.set(setting); +app.enabled = function enabled(setting) { + return Boolean(this.set(setting)); }; /** @@ -422,10 +434,10 @@ app.enabled = function(setting){ * * @param {String} setting * @return {Boolean} - * @api public + * @public */ -app.disabled = function(setting){ +app.disabled = function disabled(setting) { return !this.set(setting); }; @@ -434,10 +446,10 @@ app.disabled = function(setting){ * * @param {String} setting * @return {app} for chaining - * @api public + * @public */ -app.enable = function(setting){ +app.enable = function enable(setting) { return this.set(setting, true); }; @@ -446,10 +458,10 @@ app.enable = function(setting){ * * @param {String} setting * @return {app} for chaining - * @api public + * @public */ -app.disable = function(setting){ +app.disable = function disable(setting) { return this.set(setting, false); }; @@ -459,7 +471,10 @@ app.disable = function(setting){ methods.forEach(function(method){ app[method] = function(path){ - if ('get' == method && 1 == arguments.length) return this.set(path); + if (method === 'get' && arguments.length === 1) { + // app.get(setting) + return this.set(path); + } this.lazyrouter(); @@ -476,17 +491,18 @@ methods.forEach(function(method){ * @param {String} path * @param {Function} ... * @return {app} for chaining - * @api public + * @public */ -app.all = function(path){ +app.all = function all(path) { this.lazyrouter(); var route = this._router.route(path); var args = slice.call(arguments, 1); - methods.forEach(function(method){ - route[method].apply(route, args); - }); + + for (var i = 0; i < methods.length; i++) { + route[methods[i]].apply(route, args); + } return this; }; @@ -508,43 +524,50 @@ app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead'); * * @param {String} name * @param {String|Function} options or fn - * @param {Function} fn - * @api public + * @param {Function} callback + * @public */ -app.render = function(name, options, fn){ - var opts = {}; +app.render = function render(name, options, callback) { var cache = this.cache; + var done = callback; var engines = this.engines; + var opts = options; + var renderOptions = {}; var view; // support callback function as second arg - if ('function' == typeof options) { - fn = options, options = {}; + if (typeof options === 'function') { + done = options; + opts = {}; } // merge app.locals - merge(opts, this.locals); + merge(renderOptions, this.locals); // merge options._locals - if (options._locals) { - merge(opts, options._locals); + if (opts._locals) { + merge(renderOptions, opts._locals); } // merge options - merge(opts, options); + merge(renderOptions, opts); // set .cache unless explicitly provided - opts.cache = null == opts.cache - ? this.enabled('view cache') - : opts.cache; + if (renderOptions.cache == null) { + renderOptions.cache = this.enabled('view cache'); + } // primed cache - if (opts.cache) view = cache[name]; + if (renderOptions.cache) { + view = cache[name]; + } // view if (!view) { - view = new (this.get('view'))(name, { + var View = this.get('view'); + + view = new View(name, { defaultEngine: this.get('view engine'), root: this.get('views'), engines: engines @@ -556,18 +579,20 @@ app.render = function(name, options, fn){ : 'directory "' + view.root + '"' var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs); err.view = view; - return fn(err); + return done(err); } // prime the cache - if (opts.cache) cache[name] = view; + if (renderOptions.cache) { + cache[name] = view; + } } // render try { - view.render(opts, fn); + view.render(renderOptions, done); } catch (err) { - fn(err); + done(err); } }; @@ -589,21 +614,22 @@ app.render = function(name, options, fn){ * https.createServer({ ... }, app).listen(443); * * @return {http.Server} - * @api public + * @public */ -app.listen = function(){ +app.listen = function listen() { var server = http.createServer(this); return server.listen.apply(server, arguments); }; /** -* Log error using console.error. -* -* @param {Error} err -* @api private -*/ + * Log error using console.error. + * + * @param {Error} err + * @private + */ -function logerror(err){ +function logerror(err) { + /* istanbul ignore next */ if (this.get('env') !== 'test') console.error(err.stack || err.toString()); } From f5a240636d71781c7875191d2048279efce5ad56 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 13:36:40 -0400 Subject: [PATCH 30/39] perf: isolate app.render try block --- History.md | 1 + lib/application.js | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index 84738af0966..a50fb367407 100644 --- a/History.md +++ b/History.md @@ -66,6 +66,7 @@ unreleased - perf: reduce try block size - perf: remove bitwise operations * perf: enable strict mode + * perf: isolate `app.render` try block * perf: remove argument reassignments in application * perf: remove argument reassignments in `View` * perf: use saved reference to `http.STATUS_CODES` diff --git a/lib/application.js b/lib/application.js index 7db0f14d4ac..b230ad8d629 100644 --- a/lib/application.js +++ b/lib/application.js @@ -589,11 +589,7 @@ app.render = function render(name, options, callback) { } // render - try { - view.render(renderOptions, done); - } catch (err) { - done(err); - } + tryRender(view, renderOptions, done); }; /** @@ -633,3 +629,16 @@ function logerror(err) { /* istanbul ignore next */ if (this.get('env') !== 'test') console.error(err.stack || err.toString()); } + +/** + * Try rendering a view. + * @private + */ + +function tryRender(view, options, callback) { + try { + view.render(options, callback); + } catch (err) { + callback(err); + } +} From d414a2dc733167114e9a37107cc27f078181d1c2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 13:48:58 -0400 Subject: [PATCH 31/39] perf: remove argument reassignments in request prototype --- History.md | 1 + lib/request.js | 72 +++++++++++++++++++++++++++++--------------------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/History.md b/History.md index a50fb367407..68d9f7db2ed 100644 --- a/History.md +++ b/History.md @@ -68,6 +68,7 @@ unreleased * perf: enable strict mode * perf: isolate `app.render` try block * perf: remove argument reassignments in application + * perf: remove argument reassignments in request prototype * perf: remove argument reassignments in `View` * perf: use saved reference to `http.STATUS_CODES` diff --git a/lib/request.js b/lib/request.js index 962f48d094d..33cac180ed7 100644 --- a/lib/request.js +++ b/lib/request.js @@ -10,6 +10,7 @@ /** * Module dependencies. + * @private */ var accepts = require('accepts'); @@ -51,18 +52,20 @@ var req = exports = module.exports = { * * @param {String} name * @return {String} - * @api public + * @public */ req.get = -req.header = function(name){ - switch (name = name.toLowerCase()) { +req.header = function header(name) { + var lc = name.toLowerCase(); + + switch (lc) { case 'referer': case 'referrer': return this.headers.referrer || this.headers.referer; default: - return this.headers[name]; + return this.headers[lc]; } }; @@ -109,7 +112,7 @@ req.header = function(name){ * * @param {String|Array} type(s) * @return {String|Array|Boolean} - * @api public + * @public */ req.accepts = function(){ @@ -122,7 +125,7 @@ req.accepts = function(){ * * @param {String} ...encoding * @return {String|Array} - * @api public + * @public */ req.acceptsEncodings = function(){ @@ -139,7 +142,7 @@ req.acceptsEncoding = deprecate.function(req.acceptsEncodings, * * @param {String} ...charset * @return {String|Array} - * @api public + * @public */ req.acceptsCharsets = function(){ @@ -156,7 +159,7 @@ req.acceptsCharset = deprecate.function(req.acceptsCharsets, * * @param {String} ...lang * @return {String|Array} - * @api public + * @public */ req.acceptsLanguages = function(){ @@ -184,7 +187,7 @@ req.acceptsLanguage = deprecate.function(req.acceptsLanguages, * * @param {Number} size * @return {Array} - * @api public + * @public */ req.range = function(size){ @@ -207,7 +210,7 @@ req.range = function(size){ * @param {String} name * @param {Mixed} [defaultValue] * @return {String} - * @api public + * @public */ req.param = function param(name, defaultValue) { @@ -248,14 +251,23 @@ req.param = function param(name, defaultValue) { * req.is('html'); * // => false * - * @param {String} type - * @return {Boolean} - * @api public + * @param {String|Array} types... + * @return {String|false|null} + * @public */ -req.is = function(types){ - if (!Array.isArray(types)) types = [].slice.call(arguments); - return typeis(this, types); +req.is = function is(types) { + var arr = types; + + // support flattened arguments + if (!Array.isArray(types)) { + arr = new Array(arguments.length); + for (var i = 0; i < arr.length; i++) { + arr[i] = arguments[i]; + } + } + + return typeis(this, arr); }; /** @@ -269,7 +281,7 @@ req.is = function(types){ * supplies https for you this may be enabled. * * @return {String} - * @api public + * @public */ defineGetter(req, 'protocol', function protocol(){ @@ -294,11 +306,11 @@ defineGetter(req, 'protocol', function protocol(){ * req.protocol == 'https' * * @return {Boolean} - * @api public + * @public */ defineGetter(req, 'secure', function secure(){ - return 'https' == this.protocol; + return this.protocol === 'https'; }); /** @@ -308,7 +320,7 @@ defineGetter(req, 'secure', function secure(){ * "trust proxy" is set. * * @return {String} - * @api public + * @public */ defineGetter(req, 'ip', function ip(){ @@ -325,7 +337,7 @@ defineGetter(req, 'ip', function ip(){ * "proxy2" were trusted. * * @return {Array} - * @api public + * @public */ defineGetter(req, 'ips', function ips() { @@ -346,7 +358,7 @@ defineGetter(req, 'ips', function ips() { * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. * * @return {Array} - * @api public + * @public */ defineGetter(req, 'subdomains', function subdomains() { @@ -366,7 +378,7 @@ defineGetter(req, 'subdomains', function subdomains() { * Short-hand for `url.parse(req.url).pathname`. * * @return {String} - * @api public + * @public */ defineGetter(req, 'path', function path() { @@ -381,7 +393,7 @@ defineGetter(req, 'path', function path() { * be trusted. * * @return {String} - * @api public + * @public */ defineGetter(req, 'hostname', function hostname(){ @@ -400,7 +412,7 @@ defineGetter(req, 'hostname', function hostname(){ : 0; var index = host.indexOf(':', offset); - return ~index + return index !== -1 ? host.substring(0, index) : host; }); @@ -417,7 +429,7 @@ defineGetter(req, 'host', deprecate.function(function host(){ * still match. * * @return {Boolean} - * @api public + * @public */ defineGetter(req, 'fresh', function(){ @@ -441,7 +453,7 @@ defineGetter(req, 'fresh', function(){ * resource has changed. * * @return {Boolean} - * @api public + * @public */ defineGetter(req, 'stale', function stale(){ @@ -452,12 +464,12 @@ defineGetter(req, 'stale', function stale(){ * Check if the request was an _XMLHttpRequest_. * * @return {Boolean} - * @api public + * @public */ defineGetter(req, 'xhr', function xhr(){ var val = this.get('X-Requested-With') || ''; - return 'xmlhttprequest' == val.toLowerCase(); + return val.toLowerCase() === 'xmlhttprequest'; }); /** @@ -466,7 +478,7 @@ defineGetter(req, 'xhr', function xhr(){ * @param {Object} obj * @param {String} name * @param {Function} getter - * @api private + * @private */ function defineGetter(obj, name, getter) { Object.defineProperty(obj, name, { From bb53b20d4c72548b03af97742bbef4ca15a4801c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 14:36:48 -0400 Subject: [PATCH 32/39] perf: remove argument reassignments in response prototype --- History.md | 1 + lib/response.js | 217 +++++++++++++++++++++++++++--------------------- 2 files changed, 124 insertions(+), 94 deletions(-) diff --git a/History.md b/History.md index 68d9f7db2ed..bc5a3d95eab 100644 --- a/History.md +++ b/History.md @@ -69,6 +69,7 @@ unreleased * perf: isolate `app.render` try block * perf: remove argument reassignments in application * perf: remove argument reassignments in request prototype + * perf: remove argument reassignments in response prototype * perf: remove argument reassignments in `View` * perf: use saved reference to `http.STATUS_CODES` diff --git a/lib/response.js b/lib/response.js index 5334515eeb4..b9d6cc0e9bc 100644 --- a/lib/response.js +++ b/lib/response.js @@ -9,7 +9,7 @@ /** * Module dependencies. - * @api private + * @private */ var contentDisposition = require('content-disposition'); @@ -40,15 +40,22 @@ var res = module.exports = { __proto__: http.ServerResponse.prototype }; +/** + * Module variables. + * @private + */ + +var charsetRegExp = /;\s*charset\s*=/; + /** * Set status `code`. * * @param {Number} code * @return {ServerResponse} - * @api public + * @public */ -res.status = function(code){ +res.status = function status(code) { this.statusCode = code; return this; }; @@ -65,7 +72,7 @@ res.status = function(code){ * * @param {Object} links * @return {ServerResponse} - * @api public + * @public */ res.links = function(links){ @@ -86,7 +93,7 @@ res.links = function(links){ * res.send('

some html

'); * * @param {string|number|boolean|object|Buffer} body - * @api public + * @public */ res.send = function send(body) { @@ -209,7 +216,7 @@ res.send = function send(body) { * res.json({ user: 'tj' }); * * @param {string|number|boolean|object} obj - * @api public + * @public */ res.json = function json(obj) { @@ -251,7 +258,7 @@ res.json = function json(obj) { * res.jsonp({ user: 'tj' }); * * @param {string|number|boolean|object} obj - * @api public + * @public */ res.jsonp = function jsonp(obj) { @@ -322,7 +329,7 @@ res.jsonp = function jsonp(obj) { * res.sendStatus(200); * * @param {number} statusCode - * @api public + * @public */ res.sendStatus = function sendStatus(statusCode) { @@ -338,7 +345,7 @@ res.sendStatus = function sendStatus(statusCode) { * Transfer the file at the given `path`. * * Automatically sets the _Content-Type_ response header field. - * The callback `fn(err)` is invoked when the transfer is complete + * The callback `callback(err)` is invoked when the transfer is complete * or when an error occurs. Be sure to check `res.sentHeader` * if you wish to attempt responding, as the header and some data * may have already been transferred. @@ -372,13 +379,15 @@ res.sendStatus = function sendStatus(statusCode) { * }); * }); * - * @api public + * @public */ -res.sendFile = function sendFile(path, options, fn) { +res.sendFile = function sendFile(path, options, callback) { + var done = callback; var req = this.req; var res = this; var next = req.next; + var opts = options || {}; if (!path) { throw new TypeError('path argument is required to res.sendFile'); @@ -386,23 +395,21 @@ res.sendFile = function sendFile(path, options, fn) { // support function as second arg if (typeof options === 'function') { - fn = options; - options = {}; + done = options; + opts = {}; } - options = options || {}; - - if (!options.root && !isAbsolute(path)) { + if (!opts.root && !isAbsolute(path)) { throw new TypeError('path must be absolute or specify root to res.sendFile'); } // create file stream var pathname = encodeURI(path); - var file = send(req, pathname, options); + var file = send(req, pathname, opts); // transfer - sendfile(res, file, options, function (err) { - if (fn) return fn(err); + sendfile(res, file, opts, function (err) { + if (done) return done(err); if (err && err.code === 'EISDIR') return next(); // next() all but write errors @@ -416,7 +423,7 @@ res.sendFile = function sendFile(path, options, fn) { * Transfer the file at the given `path`. * * Automatically sets the _Content-Type_ response header field. - * The callback `fn(err)` is invoked when the transfer is complete + * The callback `callback(err)` is invoked when the transfer is complete * or when an error occurs. Be sure to check `res.sentHeader` * if you wish to attempt responding, as the header and some data * may have already been transferred. @@ -450,28 +457,28 @@ res.sendFile = function sendFile(path, options, fn) { * }); * }); * - * @api public + * @public */ -res.sendfile = function(path, options, fn){ +res.sendfile = function (path, options, callback) { + var done = callback; var req = this.req; var res = this; var next = req.next; + var opts = options || {}; // support function as second arg if (typeof options === 'function') { - fn = options; - options = {}; + done = options; + opts = {}; } - options = options || {}; - // create file stream - var file = send(req, path, options); + var file = send(req, path, opts); // transfer - sendfile(res, file, options, function (err) { - if (fn) return fn(err); + sendfile(res, file, opts, function (err) { + if (done) return done(err); if (err && err.code === 'EISDIR') return next(); // next() all but write errors @@ -488,33 +495,34 @@ res.sendfile = deprecate.function(res.sendfile, * Transfer the file at the given `path` as an attachment. * * Optionally providing an alternate attachment `filename`, - * and optional callback `fn(err)`. The callback is invoked + * and optional callback `callback(err)`. The callback is invoked * when the data transfer is complete, or when an error has * ocurred. Be sure to check `res.headersSent` if you plan to respond. * * This method uses `res.sendfile()`. * - * @api public + * @public */ -res.download = function download(path, filename, fn) { +res.download = function download(path, filename, callback) { + var done = callback; + var name = filename; + // support function as second arg if (typeof filename === 'function') { - fn = filename; - filename = null; + done = filename; + name = null; } - filename = filename || path; - // set Content-Disposition when file is sent var headers = { - 'Content-Disposition': contentDisposition(filename) + 'Content-Disposition': contentDisposition(name || path) }; // Resolve the full path for sendFile var fullPath = resolve(path); - return this.sendFile(fullPath, { headers: headers }, fn); + return this.sendFile(fullPath, { headers: headers }, done); }; /** @@ -531,14 +539,16 @@ res.download = function download(path, filename, fn) { * * @param {String} type * @return {ServerResponse} for chaining - * @api public + * @public */ res.contentType = -res.type = function(type){ - return this.set('Content-Type', ~type.indexOf('/') - ? type - : mime.lookup(type)); +res.type = function contentType(type) { + var ct = type.indexOf('/') === -1 + ? mime.lookup(type) + : type; + + return this.set('Content-Type', ct); }; /** @@ -595,7 +605,7 @@ res.type = function(type){ * * @param {Object} obj * @return {ServerResponse} for chaining - * @api public + * @public */ res.format = function(obj){ @@ -632,7 +642,7 @@ res.format = function(obj){ * * @param {String} filename * @return {ServerResponse} - * @api public + * @public */ res.attachment = function attachment(filename) { @@ -657,7 +667,7 @@ res.attachment = function attachment(filename) { * @param {String} field * @param {String|Array} val * @return {ServerResponse} for chaining - * @api public + * @public */ res.append = function append(field, val) { @@ -689,19 +699,23 @@ res.append = function append(field, val) { * @param {String|Object} field * @param {String|Array} val * @return {ServerResponse} for chaining - * @api public + * @public */ res.set = res.header = function header(field, val) { if (arguments.length === 2) { - if (Array.isArray(val)) val = val.map(String); - else val = String(val); - if ('content-type' == field.toLowerCase() && !/;\s*charset\s*=/.test(val)) { - var charset = mime.charsets.lookup(val.split(';')[0]); - if (charset) val += '; charset=' + charset.toLowerCase(); + var value = Array.isArray(val) + ? val.map(String) + : String(val); + + // add charset to content-type + if (field.toLowerCase() === 'content-type' && !charsetRegExp.test(value)) { + var charset = mime.charsets.lookup(value.split(';')[0]); + if (charset) value += '; charset=' + charset.toLowerCase(); } - this.setHeader(field, val); + + this.setHeader(field, value); } else { for (var key in field) { this.set(key, field[key]); @@ -715,7 +729,7 @@ res.header = function header(field, val) { * * @param {String} field * @return {String} - * @api public + * @public */ res.get = function(field){ @@ -728,18 +742,17 @@ res.get = function(field){ * @param {String} name * @param {Object} options * @return {ServerResponse} for chaining - * @api public + * @public */ -res.clearCookie = function(name, options){ - var opts = { expires: new Date(1), path: '/' }; - return this.cookie(name, '', options - ? merge(opts, options) - : opts); +res.clearCookie = function clearCookie(name, options) { + var opts = merge({ expires: new Date(1), path: '/' }, options); + + return this.cookie(name, '', opts); }; /** - * Set cookie `name` to `val`, with the given `options`. + * Set cookie `name` to `value`, with the given `options`. * * Options: * @@ -756,26 +769,39 @@ res.clearCookie = function(name, options){ * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) * * @param {String} name - * @param {String|Object} val + * @param {String|Object} value * @param {Options} options * @return {ServerResponse} for chaining - * @api public + * @public */ -res.cookie = function(name, val, options){ - options = merge({}, options); +res.cookie = function (name, value, options) { + var opts = merge({}, options); var secret = this.req.secret; - var signed = options.signed; - if (signed && !secret) throw new Error('cookieParser("secret") required for signed cookies'); - if ('number' == typeof val) val = val.toString(); - if ('object' == typeof val) val = 'j:' + JSON.stringify(val); - if (signed) val = 's:' + sign(val, secret); - if ('maxAge' in options) { - options.expires = new Date(Date.now() + options.maxAge); - options.maxAge /= 1000; + var signed = opts.signed; + + if (signed && !secret) { + throw new Error('cookieParser("secret") required for signed cookies'); } - if (null == options.path) options.path = '/'; - var headerVal = cookie.serialize(name, String(val), options); + + var val = typeof value === 'object' + ? 'j:' + JSON.stringify(value) + : String(value); + + if (signed) { + val = 's:' + sign(val, secret); + } + + if ('maxAge' in opts) { + opts.expires = new Date(Date.now() + opts.maxAge); + opts.maxAge /= 1000; + } + + if (opts.path == null) { + opts.path = '/'; + } + + var headerVal = cookie.serialize(name, String(val), opts); // supports multiple 'res.cookie' calls by getting previous value var prev = this.get('Set-Cookie'); @@ -790,7 +816,6 @@ res.cookie = function(name, val, options){ return this; }; - /** * Set the location header to `url`. * @@ -805,17 +830,19 @@ res.cookie = function(name, val, options){ * * @param {String} url * @return {ServerResponse} for chaining - * @api public + * @public */ -res.location = function(url){ - var req = this.req; +res.location = function location(url) { + var loc = url; // "back" is an alias for the referrer - if ('back' == url) url = req.get('Referrer') || '/'; + if (url === 'back') { + loc = this.req.get('Referrer') || '/'; + } - // Respond - this.set('Location', url); + // set location + this.set('Location', loc); return this; }; @@ -834,7 +861,7 @@ res.location = function(url){ * res.redirect(301, 'http://example.com'); * res.redirect('../login'); // /blog/post/1 -> /blog/login * - * @api public + * @public */ res.redirect = function redirect(url) { @@ -890,7 +917,7 @@ res.redirect = function redirect(url) { * * @param {Array|String} field * @return {ServerResponse} for chaining - * @api public + * @public */ res.vary = function(field){ @@ -915,31 +942,33 @@ res.vary = function(field){ * - `cache` boolean hinting to the engine it should cache * - `filename` filename of the view being rendered * - * @api public + * @public */ -res.render = function(view, options, fn){ - options = options || {}; - var self = this; +res.render = function render(view, options, callback) { + var app = this.req.app; + var done = callback; + var opts = options || {}; var req = this.req; - var app = req.app; + var self = this; // support callback function as second arg - if ('function' == typeof options) { - fn = options, options = {}; + if (typeof options === 'function') { + done = options; + opts = {}; } // merge res.locals - options._locals = self.locals; + opts._locals = self.locals; // default callback to respond - fn = fn || function(err, str){ + done = done || function (err, str) { if (err) return req.next(err); self.send(str); }; // render - app.render(view, options, fn); + app.render(view, opts, done); }; // pipe the send file stream From 5915894af3f14e75dd3121fdc2d92ae55206e398 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 14:38:30 -0400 Subject: [PATCH 33/39] Simplify res.cookie to call res.append --- History.md | 1 + lib/response.js | 12 +----------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/History.md b/History.md index bc5a3d95eab..5778a23bba5 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ unreleased * Fix issue where `next('route')` in `app.param` would incorrectly skip values * Fix using `*` before params in routes * Fix using capture groups before params in routes + * Simplify `res.cookie` to call `res.append` * Use `array-flatten` module for flattening arrays * deps: accepts@~1.2.9 - deps: mime-types@~2.1.1 diff --git a/lib/response.js b/lib/response.js index b9d6cc0e9bc..8f74f951df0 100644 --- a/lib/response.js +++ b/lib/response.js @@ -801,18 +801,8 @@ res.cookie = function (name, value, options) { opts.path = '/'; } - var headerVal = cookie.serialize(name, String(val), opts); + this.append('Set-Cookie', cookie.serialize(name, String(val), opts)); - // supports multiple 'res.cookie' calls by getting previous value - var prev = this.get('Set-Cookie'); - if (prev) { - if (Array.isArray(prev)) { - headerVal = prev.concat(headerVal); - } else { - headerVal = [prev, headerVal]; - } - } - this.set('Set-Cookie', headerVal); return this; }; From 3b3e1fc38a8e2763679fc11ff07aed1617946867 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 15:20:35 -0400 Subject: [PATCH 34/39] Fix hiding platform issues with decodeURIComponent closes #2652 --- History.md | 2 ++ lib/router/layer.js | 13 ++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index 5778a23bba5..b591d9d0d85 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ unreleased * Fix `res.format` error when only `default` provided * Fix issue where `next('route')` in `app.param` would incorrectly skip values + * Fix hiding platform issues with `decodeURIComponent` + - Only `URIError`s are a 400 * Fix using `*` before params in routes * Fix using capture groups before params in routes * Simplify `res.cookie` to call `res.append` diff --git a/lib/router/layer.js b/lib/router/layer.js index b5c1f58958b..a29cf26bfcf 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -152,19 +152,22 @@ Layer.prototype.match = function match(path) { * * @param {string} val * @return {string} - * @api private + * @private */ -function decode_param(val){ +function decode_param(val) { if (typeof val !== 'string') { return val; } try { return decodeURIComponent(val); - } catch (e) { - var err = new TypeError("Failed to decode param '" + val + "'"); - err.status = 400; + } catch (err) { + if (err instanceof URIError) { + err.message = 'Failed to decode param \'' + val + '\''; + err.status = 400; + } + throw err; } } From 7d6c1e5c5c17b88da21e30ffd2e58999881c0d67 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 15:23:35 -0400 Subject: [PATCH 35/39] perf: skip attempting to decode zero length string --- History.md | 1 + lib/router/layer.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index b591d9d0d85..db5c13d953f 100644 --- a/History.md +++ b/History.md @@ -74,6 +74,7 @@ unreleased * perf: remove argument reassignments in request prototype * perf: remove argument reassignments in response prototype * perf: remove argument reassignments in `View` + * perf: skip attempting to decode zero length string * perf: use saved reference to `http.STATUS_CODES` 4.12.4 / 2015-05-17 diff --git a/lib/router/layer.js b/lib/router/layer.js index a29cf26bfcf..b1dd04cf23a 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -156,7 +156,7 @@ Layer.prototype.match = function match(path) { */ function decode_param(val) { - if (typeof val !== 'string') { + if (typeof val !== 'string' || val.length === 0) { return val; } From 5b4d4b4ab1324743534fbcd4709f4e75bb4b4e9d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 15:27:47 -0400 Subject: [PATCH 36/39] Add statusCode properties to two errors --- lib/response.js | 2 +- lib/router/layer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/response.js b/lib/response.js index 8f74f951df0..641704b04ae 100644 --- a/lib/response.js +++ b/lib/response.js @@ -629,7 +629,7 @@ res.format = function(obj){ fn(); } else { var err = new Error('Not Acceptable'); - err.status = 406; + err.status = err.statusCode = 406; err.types = normalizeTypes(keys).map(function(o){ return o.value }); next(err); } diff --git a/lib/router/layer.js b/lib/router/layer.js index b1dd04cf23a..846bdadba01 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -165,7 +165,7 @@ function decode_param(val) { } catch (err) { if (err instanceof URIError) { err.message = 'Failed to decode param \'' + val + '\''; - err.status = 400; + err.status = err.statusCode = 400; } throw err; From 9302acc5e449768b3ca2b03701d5379d86453af5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 16:13:59 -0400 Subject: [PATCH 37/39] perf: remove argument reassignments in routing --- History.md | 1 + lib/router/index.js | 38 +++++++++++++------------ lib/router/layer.js | 11 +++++--- lib/router/route.js | 69 ++++++++++++++++++++++++++++----------------- 4 files changed, 71 insertions(+), 48 deletions(-) diff --git a/History.md b/History.md index db5c13d953f..f69a1335f26 100644 --- a/History.md +++ b/History.md @@ -73,6 +73,7 @@ unreleased * perf: remove argument reassignments in application * perf: remove argument reassignments in request prototype * perf: remove argument reassignments in response prototype + * perf: remove argument reassignments in routing * perf: remove argument reassignments in `View` * perf: skip attempting to decode zero length string * perf: use saved reference to `http.STATUS_CODES` diff --git a/lib/router/index.js b/lib/router/index.js index 8786dc15d3e..1f3ec6d49ce 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -10,6 +10,7 @@ /** * Module dependencies. + * @private */ var Route = require('./route'); @@ -23,6 +24,7 @@ var parseUrl = require('parseurl'); /** * Module variables. + * @private */ var objectRegExp = /^\[object (\S+)\]$/; @@ -34,11 +36,11 @@ var toString = Object.prototype.toString; * * @param {Object} options * @return {Router} which is an callable function - * @api public + * @public */ var proto = module.exports = function(options) { - options = options || {}; + var opts = options || {}; function router(req, res, next) { router.handle(req, res, next); @@ -49,9 +51,9 @@ var proto = module.exports = function(options) { router.params = {}; router._params = []; - router.caseSensitive = options.caseSensitive; - router.mergeParams = options.mergeParams; - router.strict = options.strict; + router.caseSensitive = opts.caseSensitive; + router.mergeParams = opts.mergeParams; + router.strict = opts.strict; router.stack = []; return router; @@ -88,7 +90,7 @@ var proto = module.exports = function(options) { * @param {String} name * @param {Function} fn * @return {app} for chaining - * @api public + * @public */ proto.param = function param(name, fn) { @@ -127,11 +129,10 @@ proto.param = function param(name, fn) { /** * Dispatch a req, res into the router. - * - * @api private + * @private */ -proto.handle = function(req, res, done) { +proto.handle = function handle(req, res, out) { var self = this; debug('dispatching %s %s', req.method, req.url); @@ -155,7 +156,7 @@ proto.handle = function(req, res, done) { // manage inter-router variables var parentParams = req.params; var parentUrl = req.baseUrl || ''; - done = restore(done, req, 'baseUrl', 'next', 'params'); + var done = restore(out, req, 'baseUrl', 'next', 'params'); // setup next layer req.next = next; @@ -315,11 +316,10 @@ proto.handle = function(req, res, done) { /** * Process any parameters for the layer. - * - * @api private + * @private */ -proto.process_params = function(layer, called, req, res, done) { +proto.process_params = function process_params(layer, called, req, res, done) { var params = this.params; // captured parameters from the layer, keys and values @@ -422,7 +422,7 @@ proto.process_params = function(layer, called, req, res, done) { * handlers can operate without any code changes regardless of the "prefix" * pathname. * - * @api public + * @public */ proto.use = function use(fn) { @@ -451,7 +451,9 @@ proto.use = function use(fn) { throw new TypeError('Router.use() requires middleware functions'); } - callbacks.forEach(function (fn) { + for (var i = 0; i < callbacks.length; i++) { + var fn = callbacks[i]; + if (typeof fn !== 'function') { throw new TypeError('Router.use() requires middleware function but got a ' + gettype(fn)); } @@ -468,7 +470,7 @@ proto.use = function use(fn) { layer.route = undefined; this.stack.push(layer); - }, this); + } return this; }; @@ -483,10 +485,10 @@ proto.use = function use(fn) { * * @param {String} path * @return {Route} - * @api public + * @public */ -proto.route = function(path){ +proto.route = function route(path) { var route = new Route(path); var layer = new Layer(path, { diff --git a/lib/router/layer.js b/lib/router/layer.js index 846bdadba01..fe9210cb9de 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -10,6 +10,7 @@ /** * Module dependencies. + * @private */ var pathRegexp = require('path-to-regexp'); @@ -17,12 +18,14 @@ var debug = require('debug')('express:router:layer'); /** * Module variables. + * @private */ var hasOwnProperty = Object.prototype.hasOwnProperty; /** - * Expose `Layer`. + * Module exports. + * @public */ module.exports = Layer; @@ -33,15 +36,15 @@ function Layer(path, options, fn) { } debug('new %s', path); - options = options || {}; + var opts = options || {}; this.handle = fn; this.name = fn.name || ''; this.params = undefined; this.path = undefined; - this.regexp = pathRegexp(path, this.keys = [], options); + this.regexp = pathRegexp(path, this.keys = [], opts); - if (path === '/' && options.end === false) { + if (path === '/' && opts.end === false) { this.regexp.fast_slash = true; } } diff --git a/lib/router/route.js b/lib/router/route.js index dadd2c7b6d4..2788d7b7353 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -10,6 +10,7 @@ /** * Module dependencies. + * @private */ var debug = require('debug')('express:router:route'); @@ -18,7 +19,16 @@ var Layer = require('./layer'); var methods = require('methods'); /** - * Expose `Route`. + * Module variables. + * @private + */ + +var slice = Array.prototype.slice; +var toString = Object.prototype.toString; + +/** + * Module exports. + * @public */ module.exports = Route; @@ -27,20 +37,22 @@ module.exports = Route; * Initialize `Route` with the given `path`, * * @param {String} path - * @api private + * @public */ function Route(path) { - debug('new %s', path); this.path = path; this.stack = []; + debug('new %s', path); + // route handlers for various http methods this.methods = {}; } /** - * @api private + * Determine if the route handles a given method. + * @private */ Route.prototype._handles_method = function _handles_method(method) { @@ -48,18 +60,18 @@ Route.prototype._handles_method = function _handles_method(method) { return true; } - method = method.toLowerCase(); + var name = method.toLowerCase(); - if (method === 'head' && !this.methods['head']) { - method = 'get'; + if (name === 'head' && !this.methods['head']) { + name = 'get'; } - return Boolean(this.methods[method]); + return Boolean(this.methods[name]); }; /** * @return {Array} supported HTTP methods - * @api private + * @private */ Route.prototype._options = function _options() { @@ -80,11 +92,10 @@ Route.prototype._options = function _options() { /** * dispatch req, res into this route - * - * @api private + * @private */ -Route.prototype.dispatch = function(req, res, done){ +Route.prototype.dispatch = function dispatch(req, res, done) { var idx = 0; var stack = this.stack; if (stack.length === 0) { @@ -150,44 +161,50 @@ Route.prototype.dispatch = function(req, res, done){ * @api public */ -Route.prototype.all = function(){ - var callbacks = flatten([].slice.call(arguments)); - callbacks.forEach(function(fn) { - if (typeof fn !== 'function') { - var type = {}.toString.call(fn); +Route.prototype.all = function all() { + var handles = flatten(slice.call(arguments)); + + for (var i = 0; i < handles.length; i++) { + var handle = handles[i]; + + if (typeof handle !== 'function') { + var type = toString.call(handle); var msg = 'Route.all() requires callback functions but got a ' + type; - throw new Error(msg); + throw new TypeError(msg); } - var layer = Layer('/', {}, fn); + var layer = Layer('/', {}, handle); layer.method = undefined; this.methods._all = true; this.stack.push(layer); - }, this); + } return this; }; methods.forEach(function(method){ Route.prototype[method] = function(){ - var callbacks = flatten([].slice.call(arguments)); + var handles = flatten(slice.call(arguments)); + + for (var i = 0; i < handles.length; i++) { + var handle = handles[i]; - callbacks.forEach(function(fn) { - if (typeof fn !== 'function') { - var type = {}.toString.call(fn); + if (typeof handle !== 'function') { + var type = toString.call(handle); var msg = 'Route.' + method + '() requires callback functions but got a ' + type; throw new Error(msg); } debug('%s %s', method, this.path); - var layer = Layer('/', {}, fn); + var layer = Layer('/', {}, handle); layer.method = method; this.methods[method] = true; this.stack.push(layer); - }, this); + } + return this; }; }); From 2a455890b9f68642457698163224f49e31ffff2a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 16:21:12 -0400 Subject: [PATCH 38/39] Add settings to debug output closes #2675 --- History.md | 1 + lib/application.js | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index f69a1335f26..d72226591e2 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Add settings to debug output * Fix `res.format` error when only `default` provided * Fix issue where `next('route')` in `app.param` would incorrectly skip values * Fix hiding platform issues with `decodeURIComponent` diff --git a/lib/application.js b/lib/application.js index b230ad8d629..a9df9103540 100644 --- a/lib/application.js +++ b/lib/application.js @@ -354,21 +354,20 @@ app.set = function set(setting, val) { return this.settings[setting]; } + debug('set "%s" to %o', setting, val); + // set value this.settings[setting] = val; // trigger matched settings switch (setting) { case 'etag': - debug('compile etag %s', val); this.set('etag fn', compileETag(val)); break; case 'query parser': - debug('compile query parser %s', val); this.set('query parser fn', compileQueryParser(val)); break; case 'trust proxy': - debug('compile trust proxy %s', val); this.set('trust proxy fn', compileTrust(val)); // trust proxy inherit back-compat From f73ff9243006ea010fffdaa748f06df3a5b986e7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 20 Jun 2015 19:20:52 -0400 Subject: [PATCH 39/39] build: support io.js 2.x --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index b163d5dc22d..ebdea3cbf62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ node_js: - "0.12" - "1.0" - "1.8" + - "2.0" sudo: false before_install: "npm rm --save-dev connect-redis" script: "npm run-script test-ci" diff --git a/appveyor.yml b/appveyor.yml index 8be4511b02a..aa7554cfd53 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,6 +4,7 @@ environment: - nodejs_version: "0.12" - nodejs_version: "1.0" - nodejs_version: "1.8" + - nodejs_version: "2.0" install: - ps: Install-Product node $env:nodejs_version - npm rm --save-dev connect-redis