From 085a29685acace053be895aef7c2a9b6251a67ab Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 9 Jul 2014 23:03:44 -0400 Subject: [PATCH 001/889] Change req.host to return host --- History.md | 6 ++++++ lib/request.js | 33 ++++++++++++++++++++++----------- test/req.host.js | 4 ++-- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/History.md b/History.md index fc8330b0faf..f372bd40fd3 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +5.x +=== + + * change: + - `req.host` now returns host (`hostname:port`) - use `req.hostname` for only hostname + 4.10.1 / 2014-10-28 =================== diff --git a/lib/request.js b/lib/request.js index 483ee1c149d..c0bc3110e73 100644 --- a/lib/request.js +++ b/lib/request.js @@ -357,7 +357,7 @@ defineGetter(req, 'path', function path() { }); /** - * Parse the "Host" header field to a hostname. + * Parse the "Host" header field to a host. * * When the "trust proxy" setting trusts the socket * address, the "X-Forwarded-Host" header field will @@ -367,14 +367,31 @@ defineGetter(req, 'path', function path() { * @api public */ -defineGetter(req, 'hostname', function hostname(){ +defineGetter(req, 'host', function host(){ var trust = this.app.get('trust proxy fn'); - var host = this.get('X-Forwarded-Host'); + var val = this.get('X-Forwarded-Host'); - if (!host || !trust(this.connection.remoteAddress)) { - host = this.get('Host'); + if (!val || !trust(this.connection.remoteAddress)) { + val = this.get('Host'); } + return val || undefined; +}); + +/** + * Parse the "Host" header field to a hostname. + * + * When the "trust proxy" setting trusts the socket + * address, the "X-Forwarded-Host" header field will + * be trusted. + * + * @return {String} + * @api public + */ + +defineGetter(req, 'hostname', function hostname(){ + var host = this.host; + if (!host) return; // IPv6 literal support @@ -388,12 +405,6 @@ defineGetter(req, 'hostname', function hostname(){ : host; }); -// TODO: change req.host to return host in next major - -defineGetter(req, 'host', deprecate.function(function host(){ - return this.hostname; -}, 'req.host: Use req.hostname instead')); - /** * Check if the request is fresh, aka * Last-Modified and/or the ETag diff --git a/test/req.host.js b/test/req.host.js index 66cfff4e549..211512405df 100644 --- a/test/req.host.js +++ b/test/req.host.js @@ -28,7 +28,7 @@ describe('req', function(){ request(app) .post('/') .set('Host', 'example.com:3000') - .expect('example.com', done); + .expect(200, 'example.com:3000', done); }) it('should return undefined otherwise', function(done){ @@ -67,7 +67,7 @@ describe('req', function(){ request(app) .post('/') .set('Host', '[::1]:3000') - .expect('[::1]', done); + .expect(200, '[::1]:3000', done); }) describe('when "trust proxy" is enabled', function(){ From e66625be5021a080e9a6f1b63324a89f959460f0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 9 Jul 2014 23:18:23 -0400 Subject: [PATCH 002/889] Remove res.send(body, status) signature --- History.md | 2 ++ lib/response.js | 14 ++++---------- test/res.send.js | 15 --------------- 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/History.md b/History.md index f372bd40fd3..e1416078a57 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,8 @@ 5.x === + * remove: + - `res.send(body, status)` signature - use `res.send(status, body)` * change: - `req.host` now returns host (`hostname:port`) - use `req.hostname` for only hostname diff --git a/lib/response.js b/lib/response.js index 34e46ad73a6..efdd21eef80 100644 --- a/lib/response.js +++ b/lib/response.js @@ -89,17 +89,11 @@ res.send = function send(body) { // settings var app = this.app; - // allow status / body + // support res.send(status, body) if (arguments.length === 2) { - // res.send(body, status) backwards compat - if (typeof arguments[0] !== 'number' && typeof arguments[1] === 'number') { - deprecate('res.send(body, status): Use res.status(status).send(body) instead'); - this.statusCode = arguments[1]; - } else { - deprecate('res.send(status, body): Use res.status(status).send(body) instead'); - this.statusCode = arguments[0]; - chunk = arguments[1]; - } + deprecate('res.send(status, body): Use res.status(status).send(body) instead'); + this.statusCode = arguments[0]; + chunk = arguments[1]; } // disambiguate res.send(status) and res.send(status, num) diff --git a/test/res.send.js b/test/res.send.js index 6148e00207e..0ae573d47a2 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -66,21 +66,6 @@ describe('res', function(){ }) }) - describe('.send(body, code)', function(){ - it('should be supported for backwards compat', function(done){ - var app = express(); - - app.use(function(req, res){ - res.send('Bad!', 400); - }); - - request(app) - .get('/') - .expect('Bad!') - .expect(400, done); - }) - }) - describe('.send(code, number)', function(){ it('should send number as json', function(done){ var app = express(); From 164638b24f42a032356574dab96affc5670697df Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 9 Jul 2014 23:20:49 -0400 Subject: [PATCH 003/889] Remove res.json(obj, status) signature --- History.md | 1 + lib/response.js | 14 ++++---------- test/res.json.js | 28 ---------------------------- 3 files changed, 5 insertions(+), 38 deletions(-) diff --git a/History.md b/History.md index e1416078a57..f63c1fba04f 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ === * remove: + - `res.json(obj, status)` signature - use `res.json(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` * change: - `req.host` now returns host (`hostname:port`) - use `req.hostname` for only hostname diff --git a/lib/response.js b/lib/response.js index efdd21eef80..5df55d8fc19 100644 --- a/lib/response.js +++ b/lib/response.js @@ -202,17 +202,11 @@ res.send = function send(body) { res.json = function json(obj) { var val = obj; - // allow status / body + // support res.json(status, obj) if (arguments.length === 2) { - // res.json(body, status) backwards compat - if (typeof arguments[1] === 'number') { - deprecate('res.json(obj, status): Use res.status(status).json(obj) instead'); - this.statusCode = arguments[1]; - } else { - deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); - this.statusCode = arguments[0]; - val = arguments[1]; - } + deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; } // settings diff --git a/test/res.json.js b/test/res.json.js index 69f6723af54..9aab76e5ad4 100644 --- a/test/res.json.js +++ b/test/res.json.js @@ -160,32 +160,4 @@ describe('res', function(){ .expect(201, '{"id":1}', done) }) }) - - describe('.json(object, status)', function(){ - it('should respond with json and set the .statusCode for backwards compat', function(done){ - var app = express(); - - app.use(function(req, res){ - res.json({ id: 1 }, 201); - }); - - request(app) - .get('/') - .expect('Content-Type', 'application/json; charset=utf-8') - .expect(201, '{"id":1}', done) - }) - - it('should use status as second number for backwards compat', function(done){ - var app = express(); - - app.use(function(req, res){ - res.json(200, 201); - }); - - request(app) - .get('/') - .expect('Content-Type', 'application/json; charset=utf-8') - .expect(201, '200', done) - }) - }) }) From 88103063fe6f9cb418f0b638f5adaaa2595c95c4 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 9 Jul 2014 23:22:03 -0400 Subject: [PATCH 004/889] Remove res.jsonp(obj, status) signature --- History.md | 1 + lib/response.js | 14 ++++---------- test/res.jsonp.js | 28 ---------------------------- 3 files changed, 5 insertions(+), 38 deletions(-) diff --git a/History.md b/History.md index f63c1fba04f..5f128beb5ca 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ * remove: - `res.json(obj, status)` signature - use `res.json(status, obj)` + - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` * change: - `req.host` now returns host (`hostname:port`) - use `req.hostname` for only hostname diff --git a/lib/response.js b/lib/response.js index 5df55d8fc19..4a23c62343b 100644 --- a/lib/response.js +++ b/lib/response.js @@ -238,17 +238,11 @@ res.json = function json(obj) { res.jsonp = function jsonp(obj) { var val = obj; - // allow status / body + // support res.jsonp(status, obj) if (arguments.length === 2) { - // res.json(body, status) backwards compat - if (typeof arguments[1] === 'number') { - deprecate('res.jsonp(obj, status): Use res.status(status).json(obj) instead'); - this.statusCode = arguments[1]; - } else { - deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead'); - this.statusCode = arguments[0]; - val = arguments[1]; - } + deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; } // settings diff --git a/test/res.jsonp.js b/test/res.jsonp.js index 4892a56ef6f..490daff7f9b 100644 --- a/test/res.jsonp.js +++ b/test/res.jsonp.js @@ -303,34 +303,6 @@ describe('res', function(){ }) }) - describe('.jsonp(object, status)', function(){ - it('should respond with json and set the .statusCode for backwards compat', function(done){ - var app = express(); - - app.use(function(req, res){ - res.jsonp({ id: 1 }, 201); - }); - - request(app) - .get('/') - .expect('Content-Type', 'application/json; charset=utf-8') - .expect(201, '{"id":1}', done) - }) - - it('should use status as second number for backwards compat', function(done){ - var app = express(); - - app.use(function(req, res){ - res.jsonp(200, 201); - }); - - request(app) - .get('/') - .expect('Content-Type', 'application/json; charset=utf-8') - .expect(201, '200', done) - }) - }) - it('should not override previous Content-Types', function(done){ var app = express(); From 8c6f9c42531e0fc5f85981484588d569cca26f63 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 9 Jul 2014 23:23:48 -0400 Subject: [PATCH 005/889] Remove app.router error message --- lib/application.js | 6 ------ test/app.js | 12 ------------ 2 files changed, 18 deletions(-) diff --git a/lib/application.js b/lib/application.js index 2fbb5503c7b..3d931052227 100644 --- a/lib/application.js +++ b/lib/application.js @@ -85,12 +85,6 @@ app.defaultConfiguration = function(){ if (env === 'production') { this.enable('view cache'); } - - Object.defineProperty(this, 'router', { - get: function() { - throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.'); - } - }); }; /** diff --git a/test/app.js b/test/app.js index 117f4dffeb5..0e09040df45 100644 --- a/test/app.js +++ b/test/app.js @@ -55,18 +55,6 @@ describe('app.mountpath', function(){ }) }) -describe('app.router', function(){ - it('should throw with notice', function(done){ - var app = express() - - try { - app.router; - } catch(err) { - done(); - } - }) -}) - describe('app.path()', function(){ it('should return the canonical', function(){ var app = express() From dcc4eaabe86a4309437db2a853c5ef788a854699 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 13 Jul 2014 23:56:37 -0400 Subject: [PATCH 006/889] Change req.query to a getter --- History.md | 2 ++ lib/application.js | 2 -- lib/express.js | 2 +- lib/middleware/query.js | 30 ------------------------------ lib/request.js | 23 +++++++++++++++++++++++ lib/utils.js | 12 ------------ 6 files changed, 26 insertions(+), 45 deletions(-) delete mode 100644 lib/middleware/query.js diff --git a/History.md b/History.md index 5f128beb5ca..fa7e3dff873 100644 --- a/History.md +++ b/History.md @@ -5,8 +5,10 @@ - `res.json(obj, status)` signature - use `res.json(status, obj)` - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` + - `express.query` middleware * change: - `req.host` now returns host (`hostname:port`) - use `req.hostname` for only hostname + - `req.query` is now a getter instead of a plain property 4.10.1 / 2014-10-28 =================== diff --git a/lib/application.js b/lib/application.js index 3d931052227..92ff613bdbf 100644 --- a/lib/application.js +++ b/lib/application.js @@ -7,7 +7,6 @@ var flatten = require('./utils').flatten; var Router = require('./router'); var methods = require('methods'); var middleware = require('./middleware/init'); -var query = require('./middleware/query'); var debug = require('debug')('express:application'); var View = require('./view'); var http = require('http'); @@ -102,7 +101,6 @@ app.lazyrouter = function() { strict: this.enabled('strict routing') }); - this._router.use(query(this.get('query parser fn'))); this._router.use(middleware.init(this)); } }; diff --git a/lib/express.js b/lib/express.js index 8a6c28464a9..6aee19fd633 100644 --- a/lib/express.js +++ b/lib/express.js @@ -56,7 +56,6 @@ exports.Router = Router; * Expose middleware */ -exports.query = require('./middleware/query'); exports.static = require('serve-static'); /** @@ -83,6 +82,7 @@ exports.static = require('serve-static'); 'limit', 'multipart', 'staticCache', + 'query', ].forEach(function (name) { Object.defineProperty(exports, name, { get: function () { diff --git a/lib/middleware/query.js b/lib/middleware/query.js deleted file mode 100644 index 092bbd9985d..00000000000 --- a/lib/middleware/query.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Module dependencies. - */ - -var parseUrl = require('parseurl'); -var qs = require('qs'); - -/** - * @param {Object} options - * @return {Function} - * @api public - */ - -module.exports = function query(options) { - var queryparse = qs.parse; - - if (typeof options === 'function') { - queryparse = options; - options = undefined; - } - - return function query(req, res, next){ - if (!req.query) { - var val = parseUrl(req).query; - req.query = queryparse(val, options); - } - - next(); - }; -}; diff --git a/lib/request.js b/lib/request.js index c0bc3110e73..aee842edbb7 100644 --- a/lib/request.js +++ b/lib/request.js @@ -183,6 +183,29 @@ req.range = function(size){ return parseRange(size, range); }; +/** + * Parse the query string of `req.url`. + * + * This uses the "query parser" setting to parse the raw + * string into an object. + * + * @return {String} + * @api public + */ + +defineGetter(req, 'query', function query(){ + var queryparse = this.app.get('query parser fn'); + + if (!queryparse) { + // parsing is disabled + return Object.create(null); + } + + var querystring = parse(this).query; + + return queryparse(querystring); +}); + /** * Return the value of param `name` when present or `defaultValue`. * diff --git a/lib/utils.js b/lib/utils.js index 9814527c0fc..8c4cb8afe4e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -205,7 +205,6 @@ exports.compileQueryParser = function compileQueryParser(val) { fn = querystring.parse; break; case false: - fn = newObject; break; case 'extended': fn = qs.parse; @@ -270,14 +269,3 @@ exports.setCharset = function(type, charset){ // format type return typer.format(parsed); }; - -/** - * Return new empty objet. - * - * @return {Object} - * @api private - */ - -function newObject() { - return {}; -} From 78e50547f16e2adb5763a953586d05308d8aba4c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 14 Jul 2014 00:06:33 -0400 Subject: [PATCH 007/889] Refactor away init middleware --- lib/application.js | 21 ++++++++++++++++++--- lib/middleware/init.js | 26 -------------------------- 2 files changed, 18 insertions(+), 29 deletions(-) delete mode 100644 lib/middleware/init.js diff --git a/lib/application.js b/lib/application.js index 92ff613bdbf..5cef13597e6 100644 --- a/lib/application.js +++ b/lib/application.js @@ -6,7 +6,6 @@ var finalhandler = require('finalhandler'); var flatten = require('./utils').flatten; var Router = require('./router'); var methods = require('methods'); -var middleware = require('./middleware/init'); var debug = require('debug')('express:application'); var View = require('./view'); var http = require('http'); @@ -100,8 +99,6 @@ app.lazyrouter = function() { caseSensitive: this.enabled('case sensitive routing'), strict: this.enabled('strict routing') }); - - this._router.use(middleware.init(this)); } }; @@ -130,6 +127,24 @@ app.handle = function(req, res, done) { return; } + // set powered by header + if (this.enabled('x-powered-by')) { + res.setHeader('X-Powered-By', 'Express'); + } + + // set circular references + req.res = res; + res.req = req; + + // alter the prototypes + req.__proto__ = this.request; + res.__proto__ = this.response; + + // setup locals + if (!res.locals) { + res.locals = Object.create(null); + } + router.handle(req, res, done); }; diff --git a/lib/middleware/init.js b/lib/middleware/init.js deleted file mode 100644 index c09cf0c69c4..00000000000 --- a/lib/middleware/init.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Initialization middleware, exposing the - * request and response to eachother, as well - * as defaulting the X-Powered-By header field. - * - * @param {Function} app - * @return {Function} - * @api private - */ - -exports.init = function(app){ - return function expressInit(req, res, next){ - if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express'); - req.res = res; - res.req = req; - req.next = next; - - req.__proto__ = app.request; - res.__proto__ = app.response; - - res.locals = res.locals || Object.create(null); - - next(); - }; -}; - From 509ebb1aff11749a9608f2a1ed2117766800d883 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 14 Jul 2014 00:27:25 -0400 Subject: [PATCH 008/889] Add app.router reference back --- History.md | 2 ++ lib/application.js | 76 ++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 46 deletions(-) diff --git a/History.md b/History.md index fa7e3dff873..244c56ce8f4 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,8 @@ * change: - `req.host` now returns host (`hostname:port`) - use `req.hostname` for only hostname - `req.query` is now a getter instead of a plain property + * add: + - `app.router` is a reference to the base router 4.10.1 / 2014-10-28 =================== diff --git a/lib/application.js b/lib/application.js index 5cef13597e6..9e4fc6674a9 100644 --- a/lib/application.js +++ b/lib/application.js @@ -34,10 +34,28 @@ var app = exports = module.exports = {}; */ app.init = function(){ + var router = null; + this.cache = {}; this.settings = {}; this.engines = {}; this.defaultConfiguration(); + + // Setup getting to lazily add base router + Object.defineProperty(this, 'router', { + configurable: true, + enumerable: true, + get: function getrouter() { + if (router === null) { + router = new Router({ + caseSensitive: this.enabled('case sensitive routing'), + strict: this.enabled('strict routing') + }); + } + + return router; + } + }); }; /** @@ -85,23 +103,6 @@ app.defaultConfiguration = function(){ } }; -/** - * lazily adds the base router if it has not yet been added. - * - * We cannot add the base router in the defaultConfiguration because - * it reads app settings which might be set after that has run. - * - * @api private - */ -app.lazyrouter = function() { - if (!this._router) { - this._router = new Router({ - caseSensitive: this.enabled('case sensitive routing'), - strict: this.enabled('strict routing') - }); - } -}; - /** * Dispatch a req, res pair into the application. Starts pipeline processing. * @@ -112,21 +113,12 @@ app.lazyrouter = function() { */ app.handle = function(req, res, done) { - var router = this._router; - // final handler done = done || finalhandler(req, res, { env: this.get('env'), onerror: logerror.bind(this) }); - // no routes - if (!router) { - debug('no routes defined on app'); - done(); - return; - } - // set powered by header if (this.enabled('x-powered-by')) { res.setHeader('X-Powered-By', 'Express'); @@ -145,7 +137,7 @@ app.handle = function(req, res, done) { res.locals = Object.create(null); } - router.handle(req, res, done); + this.router.handle(req, res, done); }; /** @@ -184,9 +176,8 @@ app.use = function use(fn) { throw new TypeError('app.use() requires middleware functions'); } - // setup router - this.lazyrouter(); - var router = this._router; + // get router + var router = this.router; fns.forEach(function (fn) { // non-express app @@ -225,9 +216,8 @@ app.use = function use(fn) { * @api public */ -app.route = function(path){ - this.lazyrouter(); - return this._router.route(path); +app.route = function route(path) { + return this.router.route(path); }; /** @@ -283,17 +273,15 @@ app.engine = function(ext, fn){ * @api public */ -app.param = function(name, fn){ - this.lazyrouter(); - +app.param = function param(name, fn) { 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); + this.router.param(name, fn); return this; }; @@ -430,9 +418,7 @@ methods.forEach(function(method){ app[method] = function(path){ if ('get' == method && 1 == arguments.length) return this.set(path); - this.lazyrouter(); - - var route = this._router.route(path); + var route = this.route(path); route[method].apply(route, slice.call(arguments, 1)); return this; }; @@ -449,9 +435,7 @@ methods.forEach(function(method){ */ app.all = function(path){ - this.lazyrouter(); - - var route = this._router.route(path); + var route = this.route(path); var args = slice.call(arguments, 1); methods.forEach(function(method){ route[method].apply(route, args); From f31dcff10cce312a24e09fc233aa31fc0e2cc135 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Nov 2014 20:41:42 -0500 Subject: [PATCH 009/889] Remove app.del --- History.md | 1 + lib/application.js | 5 ----- test/app.del.js | 17 ----------------- test/app.listen.js | 4 ++-- test/app.options.js | 2 +- test/app.router.js | 2 +- 6 files changed, 5 insertions(+), 26 deletions(-) delete mode 100644 test/app.del.js diff --git a/History.md b/History.md index 244c56ce8f4..1bf4451ffa6 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ === * remove: + - `app.del` - use `app.delete` - `res.json(obj, status)` signature - use `res.json(status, obj)` - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` diff --git a/lib/application.js b/lib/application.js index 9e4fc6674a9..c44dd7908bd 100644 --- a/lib/application.js +++ b/lib/application.js @@ -12,7 +12,6 @@ var http = require('http'); var compileETag = require('./utils').compileETag; var compileQueryParser = require('./utils').compileQueryParser; var compileTrust = require('./utils').compileTrust; -var deprecate = require('depd')('express'); var merge = require('utils-merge'); var resolve = require('path').resolve; var slice = Array.prototype.slice; @@ -444,10 +443,6 @@ app.all = function(path){ return this; }; -// del -> delete alias - -app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead'); - /** * Render the given view `name` name with `options` * and a callback accepting an error and the diff --git a/test/app.del.js b/test/app.del.js deleted file mode 100644 index d419fbb1580..00000000000 --- a/test/app.del.js +++ /dev/null @@ -1,17 +0,0 @@ - -var express = require('../') - , request = require('supertest'); - -describe('app.del()', function(){ - it('should alias app.delete()', function(done){ - var app = express(); - - app.del('/tobi', function(req, res){ - res.end('deleted tobi!'); - }); - - request(app) - .del('/tobi') - .expect('deleted tobi!', done); - }) -}) diff --git a/test/app.listen.js b/test/app.listen.js index b6f68578934..f32c357d928 100644 --- a/test/app.listen.js +++ b/test/app.listen.js @@ -6,8 +6,8 @@ describe('app.listen()', function(){ it('should wrap with an HTTP server', function(done){ var app = express(); - app.del('/tobi', function(req, res){ - res.end('deleted tobi!'); + app.get('/tobi', function(req, res){ + res.end('got tobi!'); }); var server = app.listen(9999, function(){ diff --git a/test/app.options.js b/test/app.options.js index 98fefe9a0bd..ceb195b613f 100644 --- a/test/app.options.js +++ b/test/app.options.js @@ -6,7 +6,7 @@ describe('OPTIONS', function(){ it('should default to the routes defined', function(done){ var app = express(); - app.del('/', function(){}); + app.post('/', function(){}); app.get('/users', function(req, res){}); app.put('/users', function(req, res){}); diff --git a/test/app.router.js b/test/app.router.js index 4f170ec64ad..6162489632e 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -34,7 +34,7 @@ describe('app.router', function(){ }) describe('methods', function(){ - methods.concat('del').forEach(function(method){ + methods.forEach(function(method){ if (method === 'connect') return; it('should include ' + method.toUpperCase(), function(done){ From be35e4927c4d4151bf32622e96baf731f6035042 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Nov 2014 20:48:32 -0500 Subject: [PATCH 010/889] Remove utils.contentDisposition --- lib/utils.js | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 8c4cb8afe4e..d3147f903ce 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -2,10 +2,7 @@ * Module dependencies. */ -var contentDisposition = require('content-disposition'); -var deprecate = require('depd')('express'); var mime = require('send').mime; -var basename = require('path').basename; var etag = require('etag'); var proxyaddr = require('proxy-addr'); var qs = require('qs'); @@ -113,18 +110,6 @@ exports.normalizeTypes = function(types){ return ret; }; -/** - * Generate Content-Disposition header appropriate for the filename. - * non-ascii filenames are urlencoded and a filename* parameter is added - * - * @param {String} filename - * @return {String} - * @api private - */ - -exports.contentDisposition = deprecate.function(contentDisposition, - 'utils.contentDisposition: use content-disposition npm module instead'); - /** * Parse accept params `str` returning an * object with `.value`, `.quality` and `.params`. From 7f2532808a876071c09e9c09a91bdf58526a8454 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Nov 2014 20:52:14 -0500 Subject: [PATCH 011/889] Remove req.acceptsCharset --- History.md | 1 + lib/request.js | 3 --- test/req.acceptsCharset.js | 49 -------------------------------------- 3 files changed, 1 insertion(+), 52 deletions(-) delete mode 100644 test/req.acceptsCharset.js diff --git a/History.md b/History.md index 1bf4451ffa6..7f78fe452fc 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ * remove: - `app.del` - use `app.delete` + - `req.acceptsCharset` - use `req.acceptsCharsets` - `res.json(obj, status)` signature - use `res.json(status, obj)` - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` diff --git a/lib/request.js b/lib/request.js index aee842edbb7..d28939f06f4 100644 --- a/lib/request.js +++ b/lib/request.js @@ -137,9 +137,6 @@ req.acceptsCharsets = function(){ return accept.charsets.apply(accept, arguments); }; -req.acceptsCharset = deprecate.function(req.acceptsCharsets, - 'req.acceptsCharset: Use acceptsCharsets instead'); - /** * Check if the given `lang`s are acceptable, * otherwise you should respond with 406 "Not Acceptable". diff --git a/test/req.acceptsCharset.js b/test/req.acceptsCharset.js deleted file mode 100644 index 0d0ed8b5e41..00000000000 --- a/test/req.acceptsCharset.js +++ /dev/null @@ -1,49 +0,0 @@ - -var express = require('../') - , request = require('supertest'); - -describe('req', function(){ - describe('.acceptsCharset(type)', function(){ - describe('when Accept-Charset is not present', function(){ - it('should return true', function(done){ - var app = express(); - - app.use(function(req, res, next){ - res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); - }); - - request(app) - .get('/') - .expect('yes', done); - }) - }) - - describe('when Accept-Charset is not present', function(){ - it('should return true when present', function(done){ - var app = express(); - - app.use(function(req, res, next){ - res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); - }); - - request(app) - .get('/') - .set('Accept-Charset', 'foo, bar, utf-8') - .expect('yes', done); - }) - - it('should return false otherwise', function(done){ - var app = express(); - - app.use(function(req, res, next){ - res.end(req.acceptsCharset('utf-8') ? 'yes' : 'no'); - }); - - request(app) - .get('/') - .set('Accept-Charset', 'foo, bar') - .expect('no', done); - }) - }) - }) -}) From 59f2b4048a4d08e076b06ffd36f29825a023b52a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Nov 2014 20:53:17 -0500 Subject: [PATCH 012/889] Remove acceptsEncoding --- History.md | 1 + lib/request.js | 3 --- test/req.acceptsEncoding.js | 36 ------------------------------------ 3 files changed, 1 insertion(+), 39 deletions(-) delete mode 100644 test/req.acceptsEncoding.js diff --git a/History.md b/History.md index 7f78fe452fc..ce86e4c473d 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ * remove: - `app.del` - use `app.delete` - `req.acceptsCharset` - use `req.acceptsCharsets` + - `req.acceptsEncoding` - use `req.acceptsEncodings` - `res.json(obj, status)` signature - use `res.json(status, obj)` - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` diff --git a/lib/request.js b/lib/request.js index d28939f06f4..8748177f25d 100644 --- a/lib/request.js +++ b/lib/request.js @@ -120,9 +120,6 @@ req.acceptsEncodings = function(){ return accept.encodings.apply(accept, arguments); }; -req.acceptsEncoding = deprecate.function(req.acceptsEncodings, - 'req.acceptsEncoding: Use acceptsEncodings instead'); - /** * Check if the given `charset`s are acceptable, * otherwise you should respond with 406 "Not Acceptable". diff --git a/test/req.acceptsEncoding.js b/test/req.acceptsEncoding.js deleted file mode 100644 index 930b4ea76c1..00000000000 --- a/test/req.acceptsEncoding.js +++ /dev/null @@ -1,36 +0,0 @@ - -var express = require('../') - , request = require('supertest'); - -describe('req', function(){ - describe('.acceptsEncoding', function(){ - it('should be true if encoding accpeted', function(done){ - var app = express(); - - app.use(function(req, res){ - req.acceptsEncoding('gzip').should.be.ok; - req.acceptsEncoding('deflate').should.be.ok; - res.end(); - }); - - request(app) - .get('/') - .set('Accept-Encoding', ' gzip, deflate') - .expect(200, done); - }) - - it('should be false if encoding not accpeted', function(done){ - var app = express(); - - app.use(function(req, res){ - req.acceptsEncoding('bogus').should.not.be.ok; - res.end(); - }); - - request(app) - .get('/') - .set('Accept-Encoding', ' gzip, deflate') - .expect(200, done); - }) - }) -}) From ccdbe4ea375944d31b566b98b03f055b843d7509 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Nov 2014 20:54:29 -0500 Subject: [PATCH 013/889] Remove req.acceptsLanguage --- History.md | 1 + lib/request.js | 4 --- test/req.acceptsLanguage.js | 53 ------------------------------------- 3 files changed, 1 insertion(+), 57 deletions(-) delete mode 100644 test/req.acceptsLanguage.js diff --git a/History.md b/History.md index ce86e4c473d..47778cf14c7 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ - `app.del` - use `app.delete` - `req.acceptsCharset` - use `req.acceptsCharsets` - `req.acceptsEncoding` - use `req.acceptsEncodings` + - `req.acceptsLanguage` - use `req.acceptsLanguages` - `res.json(obj, status)` signature - use `res.json(status, obj)` - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` diff --git a/lib/request.js b/lib/request.js index 8748177f25d..46204520d91 100644 --- a/lib/request.js +++ b/lib/request.js @@ -3,7 +3,6 @@ */ var accepts = require('accepts'); -var deprecate = require('depd')('express'); var isIP = require('net').isIP; var typeis = require('type-is'); var http = require('http'); @@ -148,9 +147,6 @@ req.acceptsLanguages = function(){ return accept.languages.apply(accept, arguments); }; -req.acceptsLanguage = deprecate.function(req.acceptsLanguages, - 'req.acceptsLanguage: Use acceptsLanguages instead'); - /** * Parse Range header field, * capping to the given `size`. diff --git a/test/req.acceptsLanguage.js b/test/req.acceptsLanguage.js deleted file mode 100644 index 36afc47f929..00000000000 --- a/test/req.acceptsLanguage.js +++ /dev/null @@ -1,53 +0,0 @@ - -var express = require('../') - , request = require('supertest'); - -describe('req', function(){ - describe('.acceptsLanguage', function(){ - it('should be true if language accpeted', function(done){ - var app = express(); - - app.use(function(req, res){ - req.acceptsLanguage('en-us').should.be.ok; - req.acceptsLanguage('en').should.be.ok; - res.end(); - }); - - request(app) - .get('/') - .set('Accept-Language', 'en;q=.5, en-us') - .expect(200, done); - }) - - it('should be false if language not accpeted', function(done){ - var app = express(); - - app.use(function(req, res){ - req.acceptsLanguage('es').should.not.be.ok; - res.end(); - }); - - request(app) - .get('/') - .set('Accept-Language', 'en;q=.5, en-us') - .expect(200, done); - }) - - describe('when Accept-Language is not present', function(){ - it('should always return true', function(done){ - var app = express(); - - app.use(function(req, res){ - req.acceptsLanguage('en').should.be.ok; - req.acceptsLanguage('es').should.be.ok; - req.acceptsLanguage('jp').should.be.ok; - res.end(); - }); - - request(app) - .get('/') - .expect(200, done); - }) - }) - }) -}) From 0fc4f0735a762938b5ff4c5fd70f8b95ee3ec704 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Nov 2014 21:03:04 -0500 Subject: [PATCH 014/889] Remove res.sendfile --- History.md | 1 + lib/response.js | 74 +-------- test/res.sendFile.js | 377 ------------------------------------------- 3 files changed, 2 insertions(+), 450 deletions(-) diff --git a/History.md b/History.md index 47778cf14c7..2409ea3784d 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,7 @@ - `res.json(obj, status)` signature - use `res.json(status, obj)` - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` + - `res.sendfile` - use `res.sendFile` instead - `express.query` middleware * change: - `req.host` now returns host (`hostname:port`) - use `req.hostname` for only hostname diff --git a/lib/response.js b/lib/response.js index 4a23c62343b..bcfeee57240 100644 --- a/lib/response.js +++ b/lib/response.js @@ -387,78 +387,6 @@ 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 - * 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. - * - * Options: - * - * - `maxAge` defaulting to 0 (can be string converted by `ms`) - * - `root` root directory for relative filenames - * - `headers` object of headers to serve with file - * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them - * - * Other options are passed along to `send`. - * - * Examples: - * - * The following example illustrates how `res.sendfile()` may - * be used as an alternative for the `static()` middleware for - * dynamic situations. The code backing `res.sendfile()` is actually - * the same code, so HTTP cache support etc is identical. - * - * app.get('/user/:uid/photos/:file', function(req, res){ - * var uid = req.params.uid - * , file = req.params.file; - * - * req.user.mayViewFilesFrom(uid, function(yes){ - * if (yes) { - * res.sendfile('/uploads/' + uid + '/' + file); - * } else { - * res.send(403, 'Sorry! you cant see that.'); - * } - * }); - * }); - * - * @api public - */ - -res.sendfile = function(path, options, fn){ - var req = this.req; - var res = this; - var next = req.next; - - // support function as second arg - if (typeof options === 'function') { - fn = options; - options = {}; - } - - options = options || {}; - - // create file stream - var file = send(req, path, options); - - // transfer - sendfile(res, file, options, function (err) { - if (fn) return fn(err); - if (err && err.code === 'EISDIR') return next(); - - // next() all but aborted errors - if (err && err.code !== 'ECONNABORT') { - next(err); - } - }); -}; - -res.sendfile = deprecate.function(res.sendfile, - 'res.sendfile: Use res.sendFile instead'); - /** * Transfer the file at the given `path` as an attachment. * @@ -467,7 +395,7 @@ res.sendfile = deprecate.function(res.sendfile, * 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()`. + * This method uses `res.sendFile()`. * * @api public */ diff --git a/test/res.sendFile.js b/test/res.sendFile.js index 779f6ca79f9..168dcf00b54 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -207,383 +207,6 @@ describe('res', function(){ .expect(200, 'got it', done); }) }) - - describe('.sendfile(path, fn)', function(){ - it('should invoke the callback when complete', function(done){ - var app = express(); - var cb = after(2, done); - - app.use(function(req, res){ - res.sendfile('test/fixtures/user.html', cb) - }); - - request(app) - .get('/') - .expect(200, cb); - }) - - it('should utilize the same options as express.static()', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile('test/fixtures/user.html', { maxAge: 60000 }); - }); - - request(app) - .get('/') - .expect('Cache-Control', 'public, max-age=60') - .end(done); - }) - - it('should invoke the callback when client aborts', function (done) { - var cb = after(1, done); - var app = express(); - - app.use(function (req, res) { - setImmediate(function () { - res.sendfile('test/fixtures/name.txt', function (err) { - should(err).be.ok; - err.code.should.equal('ECONNABORT'); - cb(); - }); - }); - test.abort(); - }); - - var test = request(app).get('/'); - test.expect(200, cb); - }) - - it('should invoke the callback when client already aborted', function (done) { - var cb = after(1, done); - var app = express(); - - app.use(function (req, res) { - onFinished(res, function () { - res.sendfile('test/fixtures/name.txt', function (err) { - should(err).be.ok; - err.code.should.equal('ECONNABORT'); - cb(); - }); - }); - test.abort(); - }); - - var test = request(app).get('/'); - test.expect(200, cb); - }) - - it('should invoke the callback on 404', function(done){ - var app = express() - , calls = 0; - - app.use(function(req, res){ - res.sendfile('test/fixtures/nope.html', function(err){ - ++calls; - assert(!res.headersSent); - res.send(err.message); - }); - }); - - request(app) - .get('/') - .end(function(err, res){ - assert(1 == calls, 'called too many times'); - res.text.should.startWith("ENOENT, stat"); - res.statusCode.should.equal(200); - done(); - }); - }) - - it('should not override manual content-types', function(done){ - var app = express(); - - app.use(function(req, res){ - res.contentType('txt'); - res.sendfile('test/fixtures/user.html'); - }); - - request(app) - .get('/') - .expect('Content-Type', 'text/plain; charset=utf-8') - .end(done); - }) - - it('should invoke the callback on 403', function(done){ - var app = express() - , calls = 0; - - app.use(function(req, res){ - res.sendfile('test/fixtures/foo/../user.html', function(err){ - assert(!res.headersSent); - ++calls; - res.send(err.message); - }); - }); - - request(app) - .get('/') - .expect('Forbidden') - .expect(200, done); - }) - - it('should invoke the callback on socket error', function(done){ - var app = express() - , calls = 0; - - app.use(function(req, res){ - res.sendfile('test/fixtures/user.html', function(err){ - assert(!res.headersSent); - req.socket.listeners('error').should.have.length(1); // node's original handler - done(); - }); - - req.socket.emit('error', new Error('broken!')); - }); - - request(app) - .get('/') - .end(function(){}); - }) - }) - - describe('.sendfile(path)', function(){ - it('should not serve dotfiles', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile('test/fixtures/.name'); - }); - - request(app) - .get('/') - .expect(404, done); - }) - - it('should accept dotfiles option', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile('test/fixtures/.name', { dotfiles: 'allow' }); - }); - - request(app) - .get('/') - .expect(200, 'tobi', done); - }) - - it('should accept headers option', function(done){ - var app = express(); - var headers = { - 'x-success': 'sent', - 'x-other': 'done' - }; - - app.use(function(req, res){ - res.sendfile('test/fixtures/user.html', { headers: headers }); - }); - - request(app) - .get('/') - .expect('x-success', 'sent') - .expect('x-other', 'done') - .expect(200, done); - }) - - it('should ignore headers option on 404', function(done){ - var app = express(); - var headers = { 'x-success': 'sent' }; - - app.use(function(req, res){ - res.sendfile('test/fixtures/user.nothing', { headers: headers }); - }); - - request(app) - .get('/') - .expect(404, function (err, res) { - if (err) return done(err); - res.headers.should.not.have.property('x-success'); - done(); - }); - }) - - it('should transfer a file', function (done) { - var app = express(); - - app.use(function (req, res) { - res.sendfile('test/fixtures/name.txt'); - }); - - request(app) - .get('/') - .expect(200, 'tobi', done); - }); - - it('should transfer a directory index file', function (done) { - var app = express(); - - app.use(function (req, res) { - res.sendfile('test/fixtures/blog/'); - }); - - request(app) - .get('/') - .expect(200, 'index', done); - }); - - it('should 404 for directory without trailing slash', function (done) { - var app = express(); - - app.use(function (req, res) { - res.sendfile('test/fixtures/blog'); - }); - - request(app) - .get('/') - .expect(404, done); - }); - - it('should transfer a file with urlencoded name', function (done) { - var app = express(); - - app.use(function (req, res) { - res.sendfile('test/fixtures/%25%20of%20dogs.txt'); - }); - - request(app) - .get('/') - .expect(200, '20%', done); - }); - - describe('with an absolute path', function(){ - it('should transfer the file', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile(__dirname + '/fixtures/user.html'); - }); - - request(app) - .get('/') - .end(function(err, res){ - res.text.should.equal('

{{user.name}}

'); - res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); - done(); - }); - }) - }) - - describe('with a relative path', function(){ - it('should transfer the file', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile('test/fixtures/user.html'); - }); - - request(app) - .get('/') - .end(function(err, res){ - res.text.should.equal('

{{user.name}}

'); - res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); - done(); - }); - }) - - it('should serve relative to "root"', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile('user.html', { root: 'test/fixtures/' }); - }); - - request(app) - .get('/') - .end(function(err, res){ - res.text.should.equal('

{{user.name}}

'); - res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); - done(); - }); - }) - - it('should consider ../ malicious when "root" is not set', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile('test/fixtures/foo/../user.html'); - }); - - request(app) - .get('/') - .expect(403, done); - }) - - it('should allow ../ when "root" is set', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile('foo/../user.html', { root: 'test/fixtures' }); - }); - - request(app) - .get('/') - .expect(200, done); - }) - - it('should disallow requesting out of "root"', function(done){ - var app = express(); - - app.use(function(req, res){ - res.sendfile('foo/../../user.html', { root: 'test/fixtures' }); - }); - - request(app) - .get('/') - .expect(403, done); - }) - - it('should next(404) when not found', function(done){ - var app = express() - , calls = 0; - - app.use(function(req, res){ - res.sendfile('user.html'); - }); - - app.use(function(req, res){ - assert(0, 'this should not be called'); - }); - - app.use(function(err, req, res, next){ - ++calls; - next(err); - }); - - request(app) - .get('/') - .end(function(err, res){ - res.statusCode.should.equal(404); - calls.should.equal(1); - done(); - }); - }) - - describe('with non-GET', function(){ - it('should still serve', function(done){ - var app = express() - , calls = 0; - - app.use(function(req, res){ - res.sendfile(__dirname + '/fixtures/name.txt'); - }); - - request(app) - .get('/') - .expect('tobi', done); - }) - }) - }) - }) }) function createApp(path, options, fn) { From 97ccc522073362dad5f7c23f218988780aeb4ab9 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Nov 2014 21:20:46 -0500 Subject: [PATCH 015/889] Remove res.send(status) signature --- History.md | 1 + examples/cors/index.js | 4 ++-- examples/search/index.js | 4 ++-- lib/response.js | 12 ------------ test/app.routes.error.js | 2 +- test/res.send.js | 30 +++++++++++++++--------------- 6 files changed, 21 insertions(+), 32 deletions(-) diff --git a/History.md b/History.md index 2409ea3784d..38945a0114b 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,7 @@ - `res.json(obj, status)` signature - use `res.json(status, obj)` - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)` - `res.send(body, status)` signature - use `res.send(status, body)` + - `res.send(status)` signature - use `res.sendStatus(status)` - `res.sendfile` - use `res.sendFile` instead - `express.query` middleware * change: diff --git a/examples/cors/index.js b/examples/cors/index.js index ac30ac9444e..217e2857045 100644 --- a/examples/cors/index.js +++ b/examples/cors/index.js @@ -28,7 +28,7 @@ api.all('*', function(req, res, next){ res.set('Access-Control-Allow-Methods', 'PUT'); res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'); // res.set('Access-Control-Allow-Max-Age', 3600); - if ('OPTIONS' == req.method) return res.send(200); + if ('OPTIONS' == req.method) return res.sendStatus(200); next(); }); @@ -38,7 +38,7 @@ api.all('*', function(req, res, next){ api.put('/user/:id', function(req, res){ console.log(req.body); - res.send(204); + res.sendStatus(204); }); app.listen(3000); diff --git a/examples/search/index.js b/examples/search/index.js index d614ac24076..5775eb0ece1 100644 --- a/examples/search/index.js +++ b/examples/search/index.js @@ -38,10 +38,10 @@ app.get('/', function(req, res){ * GET search for :query. */ -app.get('/search/:query?', function(req, res){ +app.get('/search/:query?', function(req, res, next){ var query = req.params.query; db.smembers(query, function(err, vals){ - if (err) return res.send(500); + if (err) return next(err); res.send(vals); }); }); diff --git a/lib/response.js b/lib/response.js index bcfeee57240..91e1a3a7cce 100644 --- a/lib/response.js +++ b/lib/response.js @@ -96,18 +96,6 @@ res.send = function send(body) { chunk = arguments[1]; } - // disambiguate res.send(status) and res.send(status, num) - if (typeof chunk === 'number' && arguments.length === 1) { - // res.send(status) will set status message as text string - if (!this.get('Content-Type')) { - this.type('txt'); - } - - deprecate('res.send(status): Use res.sendStatus(status) instead'); - this.statusCode = chunk; - chunk = http.STATUS_CODES[chunk]; - } - switch (typeof chunk) { // string defaulting to html case 'string': diff --git a/test/app.routes.error.js b/test/app.routes.error.js index ac517efdee2..03efe7c6d93 100644 --- a/test/app.routes.error.js +++ b/test/app.routes.error.js @@ -32,7 +32,7 @@ describe('app', function(){ b.should.be.true; c.should.be.true; d.should.be.false; - res.send(204); + res.sendStatus(204); }); request(app) diff --git a/test/res.send.js b/test/res.send.js index 0ae573d47a2..c6d18d1ff31 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -36,48 +36,48 @@ describe('res', function(){ }) }) - describe('.send(code)', function(){ - it('should set .statusCode', function(done){ + describe('.send(code, body)', function(){ + it('should set .statusCode and body', function(done){ var app = express(); app.use(function(req, res){ - res.send(201).should.equal(res); + res.send(201, 'Created :)'); }); request(app) .get('/') - .expect('Created') + .expect('Created :)') .expect(201, done); }) }) - describe('.send(code, body)', function(){ - it('should set .statusCode and body', function(done){ + describe('.send(code, number)', function(){ + it('should send number as json', function(done){ var app = express(); app.use(function(req, res){ - res.send(201, 'Created :)'); + res.send(200, 0.123); }); request(app) .get('/') - .expect('Created :)') - .expect(201, done); + .expect('Content-Type', 'application/json; charset=utf-8') + .expect(200, '0.123', done); }) }) - describe('.send(code, number)', function(){ - it('should send number as json', function(done){ + describe('.send(Number)', function(){ + it('should send as application/json', function(done){ var app = express(); app.use(function(req, res){ - res.send(200, 0.123); + res.send(1000); }); request(app) .get('/') .expect('Content-Type', 'application/json; charset=utf-8') - .expect(200, '0.123', done); + .expect(200, '1000', done) }) }) @@ -399,7 +399,7 @@ describe('res', function(){ app.use(function(req, res){ res.set('etag', '"asdf"'); - res.send(200); + res.send('hello!'); }); app.enable('etag'); @@ -453,7 +453,7 @@ describe('res', function(){ app.use(function(req, res){ res.set('etag', '"asdf"'); - res.send(200); + res.send('hello!'); }); request(app) From 4052c15c7f10b79fb7c54f3837ffe118f7a99811 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Nov 2014 21:52:29 -0500 Subject: [PATCH 016/889] 5.0.0-alpha.1 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 38945a0114b..28dc478df40 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -5.x -=== +5.0.0-alpha.1 / 2014-11-06 +========================== * remove: - `app.del` - use `app.delete` diff --git a/package.json b/package.json index e98cd90db3b..835a9fadfe8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.10.1", + "version": "5.0.0-alpha.1", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From f56e2a2503fdf4631b6e1bd235a64383e7321c2b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 21 Jan 2015 04:01:41 -0500 Subject: [PATCH 017/889] docs: simplify 5.x history --- History.md | 44 +++----------------------------------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/History.md b/History.md index 3881820e6ce..ff2ea114e33 100644 --- a/History.md +++ b/History.md @@ -1,51 +1,13 @@ 5.x === - * Add `res.append(field, val)` to append headers - * Correctly invoke async router callback asynchronously - * Deprecate leading `:` in `name` for `app.param(name, fn)` - * Deprecate `req.param()` -- use `req.params`, `req.body`, or `req.query` instead - * Deprecate `app.param(fn)` - * Fix `Allow` header for `OPTIONS` to not contain duplicate methods - * Fix crash from error within `OPTIONS` response handler - * Fix exception in `req.fresh`/`req.stale` without response headers - * Fix incorrect "Request aborted" for `res.sendFile` when `HEAD` or 304 - * Fix `OPTIONS` responses to include the `HEAD` method properly - * Fix `res.send` double-calling `res.end` for `HEAD` requests - * Fix `res.sendFile` logging standard write errors - * Fix `res.sendFile` not always detecting aborted connection - * Match routes iteratively to prevent stack overflows - * deps: accepts@~1.2.2 - - deps: mime-types@~2.0.7 - - deps: negotiator@0.5.0 - * deps: debug@~2.1.1 - * deps: etag@~1.5.1 - * deps: finalhandler@0.3.3 - - deps: debug@~2.1.1 - - deps: on-finished@~2.2.0 - * deps: methods@~1.1.1 - * deps: on-finished@~2.2.0 - * deps: proxy-addr@~1.0.5 - - deps: ipaddr.js@0.1.6 - * deps: qs@2.3.3 - - Fix `arrayLimit` behavior - * deps: send@0.11.1 - - Fix root path disclosure - - deps: debug@~2.1.1 - - deps: etag@~1.5.1 - - deps: ms@0.7.0 - - deps: on-finished@~2.2.0 - * deps: serve-static@~1.8.1 - - Fix potential open redirect when mounted at root - - Fix redirect loop in Node.js 0.11.14 - - Fix root path disclosure - - deps: send@0.11.1 - * deps: type-is@~1.5.5 - - deps: mime-types@~2.0.7 +This incorporates all changes after 4.10.1 up to 4.11.1. 5.0.0-alpha.1 / 2014-11-06 ========================== +This is the first Express 5.0 alpha release, based off 4.10.1. + * remove: - `app.del` - use `app.delete` - `req.acceptsCharset` - use `req.acceptsCharsets` From 3a1f27fcde4a4399ab2afab74aeb1baad513cd08 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Jul 2015 16:31:51 -0400 Subject: [PATCH 018/889] Remove ":" stripping from app.param() --- History.md | 3 +++ lib/router/index.js | 5 ----- test/app.param.js | 9 ++++----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/History.md b/History.md index e2e6cfd2d1e..ebb0c5909d7 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,9 @@ This incorporates all changes after 4.10.1 up to 4.13.1. + * change: + - The leading `:` character in `name` for `app.param(name, fn)` is no longer removed + 5.0.0-alpha.1 / 2014-11-06 ========================== diff --git a/lib/router/index.js b/lib/router/index.js index 1f3ec6d49ce..5204b2a03a4 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -106,11 +106,6 @@ proto.param = function param(name, fn) { var len = params.length; var ret; - if (name[0] === ':') { - deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.substr(1)) + ', fn) instead'); - name = name.substr(1); - } - for (var i = 0; i < len; ++i) { if (ret = params[i](name, fn)) { fn = ret; diff --git a/test/app.param.js b/test/app.param.js index 30885bcdc89..7a3539822a5 100644 --- a/test/app.param.js +++ b/test/app.param.js @@ -21,7 +21,7 @@ describe('app', function(){ } }) - app.param(':name', /^([a-zA-Z]+)$/); + app.param('name', /^([a-zA-Z]+)$/); app.get('/user/:name', function(req, res){ res.send(req.params.name); @@ -29,18 +29,17 @@ describe('app', function(){ request(app) .get('/user/tj') - .end(function(err, res){ - res.text.should.equal('tj'); + .expect(200, 'tj', function (err) { + if (err) return done(err); request(app) .get('/user/123') .expect(404, done); }); - }) it('should fail if not given fn', function(){ var app = express(); - app.param.bind(app, ':name', 'bob').should.throw(); + app.param.bind(app, 'name', 'bob').should.throw(); }) }) From 1e2951a832d1307ab40ef8c45202e02524991816 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Jul 2015 16:45:09 -0400 Subject: [PATCH 019/889] Remove app.param(fn) signature --- History.md | 2 ++ lib/router/index.js | 30 ++++++++++-------------------- test/Router.js | 10 ++++++++++ test/app.param.js | 40 ---------------------------------------- 4 files changed, 22 insertions(+), 60 deletions(-) diff --git a/History.md b/History.md index ebb0c5909d7..2c768fd8c5a 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ This incorporates all changes after 4.10.1 up to 4.13.1. + * remove: + - `app.param(fn)` * change: - The leading `:` character in `name` for `app.param(name, fn)` is no longer removed diff --git a/lib/router/index.js b/lib/router/index.js index 5204b2a03a4..1eedc563f93 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -50,7 +50,6 @@ var proto = module.exports = function(options) { router.__proto__ = proto; router.params = {}; - router._params = []; router.caseSensitive = opts.caseSensitive; router.mergeParams = opts.mergeParams; router.strict = opts.strict; @@ -94,31 +93,22 @@ var proto = module.exports = function(options) { */ proto.param = function param(name, fn) { - // param logic - if (typeof name === 'function') { - deprecate('router.param(fn): Refactor to use path params'); - this._params.push(name); - return; + if (!fn) { + throw new TypeError('argument fn is required'); } - // apply param functions - var params = this._params; - var len = params.length; - var ret; - - for (var i = 0; i < len; ++i) { - if (ret = params[i](name, fn)) { - fn = ret; - } + if (typeof fn !== 'function') { + throw new TypeError('argument fn must be a function'); } - // ensure we end up with a - // middleware function - if ('function' != typeof fn) { - throw new Error('invalid param() call for ' + name + ', got ' + fn); + var params = this.params[name]; + + if (!params) { + params = this.params[name] = []; } - (this.params[name] = this.params[name] || []).push(fn); + params.push(fn); + return this; }; diff --git a/test/Router.js b/test/Router.js index 21cdff2c6c0..9f28952a44b 100644 --- a/test/Router.js +++ b/test/Router.js @@ -377,6 +377,16 @@ describe('Router', function(){ }) describe('.param', function() { + it('should require function', function () { + var router = new Router(); + assert.throws(router.param.bind(router, 'id'), /argument fn is required/); + }); + + it('should reject non-function', function () { + var router = new Router(); + assert.throws(router.param.bind(router, 'id', 42), /argument fn must be a function/); + }); + it('should call param function when routing VERBS', function(done) { var router = new Router(); diff --git a/test/app.param.js b/test/app.param.js index 7a3539822a5..7996995f885 100644 --- a/test/app.param.js +++ b/test/app.param.js @@ -3,46 +3,6 @@ var express = require('../') , request = require('supertest'); describe('app', function(){ - describe('.param(fn)', function(){ - it('should map app.param(name, ...) logic', function(done){ - var app = express(); - - app.param(function(name, regexp){ - if (Object.prototype.toString.call(regexp) == '[object RegExp]') { // See #1557 - return function(req, res, next, val){ - var captures; - if (captures = regexp.exec(String(val))) { - req.params[name] = captures[1]; - next(); - } else { - next('route'); - } - } - } - }) - - app.param('name', /^([a-zA-Z]+)$/); - - app.get('/user/:name', function(req, res){ - res.send(req.params.name); - }); - - request(app) - .get('/user/tj') - .expect(200, 'tj', function (err) { - if (err) return done(err); - request(app) - .get('/user/123') - .expect(404, done); - }); - }) - - it('should fail if not given fn', function(){ - var app = express(); - app.param.bind(app, 'name', 'bob').should.throw(); - }) - }) - describe('.param(names, fn)', function(){ it('should map the array', function(done){ var app = express(); From 6c751191dd15a3e3154b20fd4c9ffd17cebf250b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Jul 2015 21:12:44 -0400 Subject: [PATCH 020/889] Remove utils.flatten --- lib/utils.js | 12 ------------ test/utils.js | 8 -------- 2 files changed, 20 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index e4f8224f3a8..2be07196a37 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -14,7 +14,6 @@ var mime = require('send').mime; var contentType = require('content-type'); -var deprecate = require('depd')('express'); var etag = require('etag'); var flatten = require('array-flatten'); var proxyaddr = require('proxy-addr'); @@ -69,17 +68,6 @@ exports.isAbsolute = function(path){ if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path }; -/** - * Flatten the given `arr`. - * - * @param {Array} arr - * @return {Array} - * @api private - */ - -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/test/utils.js b/test/utils.js index b7e8b520091..050ebc1a29b 100644 --- a/test/utils.js +++ b/test/utils.js @@ -85,11 +85,3 @@ describe('utils.isAbsolute()', function(){ assert(!utils.isAbsolute('foo/bar')); }) }) - -describe('utils.flatten(arr)', function(){ - it('should flatten an array', function(){ - var arr = ['one', ['two', ['three', 'four'], 'five']]; - utils.flatten(arr) - .should.eql(['one', 'two', 'three', 'four', 'five']); - }) -}) From a7d15f382e8e0fa4380d459fbe61bd363d059a11 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Jul 2015 21:13:49 -0400 Subject: [PATCH 021/889] Remove un-used depd import in router --- lib/router/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/router/index.js b/lib/router/index.js index 1eedc563f93..9ef1c40f76e 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -18,7 +18,6 @@ var Layer = require('./layer'); 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'); From 21d52daafba1bc7247d6ecdcf30719a21ded4e42 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Jul 2015 21:15:16 -0400 Subject: [PATCH 022/889] Remove req.param() --- History.md | 1 + lib/request.js | 35 --------------------------- test/req.param.js | 61 ----------------------------------------------- 3 files changed, 1 insertion(+), 96 deletions(-) delete mode 100644 test/req.param.js diff --git a/History.md b/History.md index 2c768fd8c5a..da7cd1ddc2f 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ This incorporates all changes after 4.10.1 up to 4.13.1. * remove: - `app.param(fn)` + - `req.param()` -- use `req.params`, `req.body`, or `req.query` instead * change: - The leading `:` character in `name` for `app.param(name, fn)` is no longer removed diff --git a/lib/request.js b/lib/request.js index 52abea6cd19..b881df8d2d1 100644 --- a/lib/request.js +++ b/lib/request.js @@ -14,7 +14,6 @@ */ var accepts = require('accepts'); -var deprecate = require('depd')('express'); var isIP = require('net').isIP; var typeis = require('type-is'); var http = require('http'); @@ -210,40 +209,6 @@ defineGetter(req, 'query', function query(){ return queryparse(querystring); }); -/** - * Return the value of param `name` when present or `defaultValue`. - * - * - Checks route placeholders, ex: _/user/:id_ - * - Checks body params, ex: id=12, {"id":12} - * - Checks query string params, ex: ?id=12 - * - * To utilize request bodies, `req.body` - * should be an object. This can be done by using - * the `bodyParser()` middleware. - * - * @param {String} name - * @param {Mixed} [defaultValue] - * @return {String} - * @public - */ - -req.param = function param(name, defaultValue) { - var params = this.params || {}; - var body = this.body || {}; - var query = this.query || {}; - - var args = arguments.length === 1 - ? 'name' - : 'name, default'; - deprecate('req.param(' + args + '): Use req.params, req.body, or req.query instead'); - - if (null != params[name] && params.hasOwnProperty(name)) return params[name]; - if (null != body[name]) return body[name]; - if (null != query[name]) return query[name]; - - return defaultValue; -}; - /** * Check if the incoming request contains the "Content-Type" * header field, and it contains the give mime `type`. diff --git a/test/req.param.js b/test/req.param.js deleted file mode 100644 index 1e827f03058..00000000000 --- a/test/req.param.js +++ /dev/null @@ -1,61 +0,0 @@ - -var express = require('../') - , request = require('supertest') - , bodyParser = require('body-parser') - -describe('req', function(){ - describe('.param(name, default)', function(){ - it('should use the default value unless defined', function(done){ - var app = express(); - - app.use(function(req, res){ - res.end(req.param('name', 'tj')); - }); - - request(app) - .get('/') - .expect('tj', done); - }) - }) - - describe('.param(name)', function(){ - it('should check req.query', function(done){ - var app = express(); - - app.use(function(req, res){ - res.end(req.param('name')); - }); - - request(app) - .get('/?name=tj') - .expect('tj', done); - }) - - it('should check req.body', function(done){ - var app = express(); - - app.use(bodyParser.json()); - - app.use(function(req, res){ - res.end(req.param('name')); - }); - - request(app) - .post('/') - .send({ name: 'tj' }) - .expect('tj', done); - }) - - it('should check req.params', function(done){ - var app = express(); - - app.get('/user/:name', function(req, res){ - res.end(req.param('filter') + req.param('name')); - }); - - request(app) - .get('/user/tj') - .expect('undefinedtj', done); - }) - }) -}) From cec5780db4f07a61e21e139e38af20b02dd5ae3a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Jul 2015 23:46:00 -0400 Subject: [PATCH 023/889] Use router module for routing closes #2411 --- History.md | 1 + lib/application.js | 2 +- lib/express.js | 5 +- lib/router/index.js | 626 -------------------------------------------- lib/router/layer.js | 176 ------------- lib/router/route.js | 210 --------------- package.json | 1 + test/Router.js | 18 +- test/app.options.js | 16 +- test/app.router.js | 2 +- test/app.use.js | 11 +- 11 files changed, 29 insertions(+), 1039 deletions(-) delete mode 100644 lib/router/index.js delete mode 100644 lib/router/layer.js delete mode 100644 lib/router/route.js diff --git a/History.md b/History.md index da7cd1ddc2f..fbc7538cce9 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,7 @@ This incorporates all changes after 4.10.1 up to 4.13.1. - `req.param()` -- use `req.params`, `req.body`, or `req.query` instead * change: - The leading `:` character in `name` for `app.param(name, fn)` is no longer removed + - Use `router` module for routing 5.0.0-alpha.1 / 2014-11-06 ========================== diff --git a/lib/application.js b/lib/application.js index 7419d4bc7e8..bcc509459e4 100644 --- a/lib/application.js +++ b/lib/application.js @@ -14,7 +14,6 @@ */ var finalhandler = require('finalhandler'); -var Router = require('./router'); var methods = require('methods'); var debug = require('debug')('express:application'); var View = require('./view'); @@ -25,6 +24,7 @@ var compileTrust = require('./utils').compileTrust; var flatten = require('array-flatten'); var merge = require('utils-merge'); var resolve = require('path').resolve; +var Router = require('router'); var slice = Array.prototype.slice; /** diff --git a/lib/express.js b/lib/express.js index e5724504358..ff62644c534 100644 --- a/lib/express.js +++ b/lib/express.js @@ -15,8 +15,7 @@ var EventEmitter = require('events').EventEmitter; var mixin = require('merge-descriptors'); var proto = require('./application'); -var Route = require('./router/route'); -var Router = require('./router'); +var Router = require('router'); var req = require('./request'); var res = require('./response'); @@ -59,7 +58,7 @@ exports.response = res; * Expose constructors. */ -exports.Route = Route; +exports.Route = Router.Route; exports.Router = Router; /** diff --git a/lib/router/index.js b/lib/router/index.js deleted file mode 100644 index 9ef1c40f76e..00000000000 --- a/lib/router/index.js +++ /dev/null @@ -1,626 +0,0 @@ -/*! - * express - * Copyright(c) 2009-2013 TJ Holowaychuk - * Copyright(c) 2013 Roman Shtylman - * Copyright(c) 2014-2015 Douglas Christopher Wilson - * MIT Licensed - */ - -'use strict'; - -/** - * Module dependencies. - * @private - */ - -var Route = require('./route'); -var Layer = require('./layer'); -var methods = require('methods'); -var mixin = require('utils-merge'); -var debug = require('debug')('express:router'); -var flatten = require('array-flatten'); -var parseUrl = require('parseurl'); - -/** - * Module variables. - * @private - */ - -var objectRegExp = /^\[object (\S+)\]$/; -var slice = Array.prototype.slice; -var toString = Object.prototype.toString; - -/** - * Initialize a new `Router` with the given `options`. - * - * @param {Object} options - * @return {Router} which is an callable function - * @public - */ - -var proto = module.exports = function(options) { - var opts = options || {}; - - function router(req, res, next) { - router.handle(req, res, next); - } - - // mixin Router class functions - router.__proto__ = proto; - - router.params = {}; - router.caseSensitive = opts.caseSensitive; - router.mergeParams = opts.mergeParams; - router.strict = opts.strict; - router.stack = []; - - return router; -}; - -/** - * Map the given param placeholder `name`(s) to the given callback. - * - * Parameter mapping is used to provide pre-conditions to routes - * which use normalized placeholders. For example a _:user_id_ parameter - * could automatically load a user's information from the database without - * any additional code, - * - * The callback uses the same signature as middleware, the only difference - * being that the value of the placeholder is passed, in this case the _id_ - * of the user. Once the `next()` function is invoked, just like middleware - * it will continue on to execute the route, or subsequent parameter functions. - * - * Just like in middleware, you must either respond to the request or call next - * to avoid stalling the request. - * - * app.param('user_id', function(req, res, next, id){ - * User.find(id, function(err, user){ - * if (err) { - * return next(err); - * } else if (!user) { - * return next(new Error('failed to load user')); - * } - * req.user = user; - * next(); - * }); - * }); - * - * @param {String} name - * @param {Function} fn - * @return {app} for chaining - * @public - */ - -proto.param = function param(name, fn) { - if (!fn) { - throw new TypeError('argument fn is required'); - } - - if (typeof fn !== 'function') { - throw new TypeError('argument fn must be a function'); - } - - var params = this.params[name]; - - if (!params) { - params = this.params[name] = []; - } - - params.push(fn); - - return this; -}; - -/** - * Dispatch a req, res into the router. - * @private - */ - -proto.handle = function handle(req, res, out) { - var self = this; - - debug('dispatching %s %s', req.method, req.url); - - var search = 1 + req.url.indexOf('?'); - var pathlength = search ? search - 1 : req.url.length; - var fqdn = req.url[0] !== '/' && 1 + req.url.substr(0, pathlength).indexOf('://'); - var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : ''; - var idx = 0; - var removed = ''; - var slashAdded = false; - var paramcalled = {}; - - // store options for OPTIONS request - // only used if OPTIONS request - var options = []; - - // middleware and routes - var stack = self.stack; - - // manage inter-router variables - var parentParams = req.params; - var parentUrl = req.baseUrl || ''; - var done = restore(out, req, 'baseUrl', 'next', 'params'); - - // setup next layer - req.next = next; - - // for options requests, respond with a default if nothing else responds - if (req.method === 'OPTIONS') { - done = wrap(done, function(old, err) { - if (err || options.length === 0) return old(err); - sendOptionsResponse(res, options, old); - }); - } - - // setup basic req values - req.baseUrl = parentUrl; - req.originalUrl = req.originalUrl || req.url; - - next(); - - function next(err) { - var layerError = err === 'route' - ? null - : err; - - // remove added slash - if (slashAdded) { - req.url = req.url.substr(1); - slashAdded = false; - } - - // restore altered req.url - if (removed.length !== 0) { - req.baseUrl = parentUrl; - req.url = protohost + removed + req.url.substr(protohost.length); - removed = ''; - } - - // no more matching layers - if (idx >= stack.length) { - setImmediate(done, layerError); - return; - } - - // get pathname of request - var path = getPathname(req); - - if (path == null) { - return done(layerError); - } - - // find next matching layer - var layer; - var match; - var route; - - while (match !== true && idx < stack.length) { - layer = stack[idx++]; - match = matchLayer(layer, path); - route = layer.route; - - if (typeof match !== 'boolean') { - // hold on to layerError - layerError = layerError || match; - } - - if (match !== true) { - continue; - } - - if (!route) { - // process non-route handlers normally - continue; - } - - if (layerError) { - // routes do not match with a pending error - match = false; - continue; - } - - var method = req.method; - var has_method = route._handles_method(method); - - // build up automatic options response - if (!has_method && method === 'OPTIONS') { - appendMethods(options, route._options()); - } - - // don't even bother matching route - if (!has_method && method !== 'HEAD') { - match = false; - continue; - } - } - - // no match - if (match !== true) { - return done(layerError); - } - - // store route for dispatch on change - if (route) { - req.route = route; - } - - // Capture one-time layer values - req.params = self.mergeParams - ? mergeParams(layer.params, parentParams) - : layer.params; - var layerPath = layer.path; - - // this should be done for the layer - self.process_params(layer, paramcalled, req, res, function (err) { - if (err) { - return next(layerError || err); - } - - if (route) { - return layer.handle_request(req, res, next); - } - - trim_prefix(layer, layerError, layerPath, path); - }); - } - - function trim_prefix(layer, layerError, layerPath, path) { - var c = path[layerPath.length]; - if (c && '/' !== c && '.' !== c) return next(layerError); - - // Trim off the part of the url that matches the route - // middleware (.use stuff) needs to have the path stripped - if (layerPath.length !== 0) { - debug('trim prefix (%s) from url %s', layerPath, req.url); - removed = layerPath; - req.url = protohost + req.url.substr(protohost.length + removed.length); - - // Ensure leading slash - if (!fqdn && req.url[0] !== '/') { - req.url = '/' + req.url; - slashAdded = true; - } - - // Setup base URL (no trailing slash) - req.baseUrl = parentUrl + (removed[removed.length - 1] === '/' - ? removed.substring(0, removed.length - 1) - : removed); - } - - debug('%s %s : %s', layer.name, layerPath, req.originalUrl); - - if (layerError) { - layer.handle_error(layerError, req, res, next); - } else { - layer.handle_request(req, res, next); - } - } -}; - -/** - * Process any parameters for the layer. - * @private - */ - -proto.process_params = function process_params(layer, called, req, res, done) { - var params = this.params; - - // captured parameters from the layer, keys and values - var keys = layer.keys; - - // fast track - if (!keys || keys.length === 0) { - return done(); - } - - var i = 0; - var name; - var paramIndex = 0; - var key; - var paramVal; - var paramCallbacks; - var paramCalled; - - // process params in order - // param callbacks can be async - function param(err) { - if (err) { - return done(err); - } - - if (i >= keys.length ) { - return done(); - } - - paramIndex = 0; - key = keys[i++]; - - if (!key) { - return done(); - } - - name = key.name; - paramVal = req.params[name]; - paramCallbacks = params[name]; - paramCalled = called[name]; - - if (paramVal === undefined || !paramCallbacks) { - return param(); - } - - // param previously called with same value or error occurred - if (paramCalled && (paramCalled.match === paramVal - || (paramCalled.error && paramCalled.error !== 'route'))) { - // restore value - req.params[name] = paramCalled.value; - - // next param - return param(paramCalled.error); - } - - called[name] = paramCalled = { - error: null, - match: paramVal, - value: paramVal - }; - - paramCallback(); - } - - // single param callbacks - function paramCallback(err) { - var fn = paramCallbacks[paramIndex++]; - - // store updated value - paramCalled.value = req.params[key.name]; - - if (err) { - // store error - paramCalled.error = err; - param(err); - return; - } - - if (!fn) return param(); - - try { - fn(req, res, paramCallback, paramVal, key.name); - } catch (e) { - paramCallback(e); - } - } - - param(); -}; - -/** - * Use the given middleware function, with optional path, defaulting to "/". - * - * Use (like `.all`) will run for any http METHOD, but it will not add - * handlers for those methods so OPTIONS requests will not consider `.use` - * functions even if they could respond. - * - * The other difference is that _route_ path is stripped and not visible - * to the handler function. The main effect of this feature is that mounted - * handlers can operate without any code changes regardless of the "prefix" - * pathname. - * - * @public - */ - -proto.use = function use(fn) { - var offset = 0; - var path = '/'; - - // default path to '/' - // disambiguate router.use([fn]) - if (typeof fn !== 'function') { - var arg = fn; - - while (Array.isArray(arg) && arg.length !== 0) { - arg = arg[0]; - } - - // first arg is the path - if (typeof arg !== 'function') { - offset = 1; - path = fn; - } - } - - var callbacks = flatten(slice.call(arguments, offset)); - - if (callbacks.length === 0) { - throw new TypeError('Router.use() requires middleware functions'); - } - - 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)); - } - - // add the middleware - debug('use %s %s', path, fn.name || ''); - - var layer = new Layer(path, { - sensitive: this.caseSensitive, - strict: false, - end: false - }, fn); - - layer.route = undefined; - - this.stack.push(layer); - } - - return this; -}; - -/** - * Create a new Route for the given path. - * - * Each route contains a separate middleware stack and VERB handlers. - * - * See the Route api documentation for details on adding handlers - * and middleware to routes. - * - * @param {String} path - * @return {Route} - * @public - */ - -proto.route = function route(path) { - var route = new Route(path); - - var layer = new Layer(path, { - sensitive: this.caseSensitive, - strict: this.strict, - end: true - }, route.dispatch.bind(route)); - - layer.route = route; - - this.stack.push(layer); - return route; -}; - -// create Router#VERB functions -methods.concat('all').forEach(function(method){ - proto[method] = function(path){ - var route = this.route(path) - route[method].apply(route, slice.call(arguments, 1)); - return this; - }; -}); - -// append methods to a list of methods -function appendMethods(list, addition) { - for (var i = 0; i < addition.length; i++) { - var method = addition[i]; - if (list.indexOf(method) === -1) { - list.push(method); - } - } -} - -// get pathname of request -function getPathname(req) { - try { - return parseUrl(req).pathname; - } catch (err) { - return undefined; - } -} - -// get type for error message -function gettype(obj) { - var type = typeof obj; - - if (type !== 'object') { - return type; - } - - // inspect [[Class]] for objects - return toString.call(obj) - .replace(objectRegExp, '$1'); -} - -/** - * Match path to a layer. - * - * @param {Layer} layer - * @param {string} path - * @private - */ - -function matchLayer(layer, path) { - try { - return layer.match(path); - } catch (err) { - return err; - } -} - -// merge params with parent params -function mergeParams(params, parent) { - if (typeof parent !== 'object' || !parent) { - return params; - } - - // make copy of parent for base - var obj = mixin({}, parent); - - // simple non-numeric merging - if (!(0 in params) || !(0 in parent)) { - return mixin(obj, params); - } - - var i = 0; - var o = 0; - - // determine numeric gaps - while (i === o || o in parent) { - if (i in params) i++; - if (o in parent) o++; - } - - // offset numeric indices in params before merge - for (i--; i >= 0; i--) { - params[i + o] = params[i]; - - // create holes for the merge when necessary - if (i < o) { - delete params[i]; - } - } - - return mixin(parent, params); -} - -// restore obj props after function -function restore(fn, obj) { - var props = new Array(arguments.length - 2); - var vals = new Array(arguments.length - 2); - - for (var i = 0; i < props.length; i++) { - props[i] = arguments[i + 2]; - vals[i] = obj[props[i]]; - } - - return function(err){ - // restore vals - for (var i = 0; i < props.length; i++) { - obj[props[i]] = vals[i]; - } - - return fn.apply(this, arguments); - }; -} - -// send an OPTIONS response -function sendOptionsResponse(res, options, next) { - try { - var body = options.join(','); - res.set('Allow', body); - res.send(body); - } catch (err) { - next(err); - } -} - -// wrap a function -function wrap(old, fn) { - return function proxy() { - var args = new Array(arguments.length + 1); - - args[0] = old; - for (var i = 0, len = arguments.length; i < len; i++) { - args[i + 1] = arguments[i]; - } - - fn.apply(this, args); - }; -} diff --git a/lib/router/layer.js b/lib/router/layer.js deleted file mode 100644 index fe9210cb9de..00000000000 --- a/lib/router/layer.js +++ /dev/null @@ -1,176 +0,0 @@ -/*! - * express - * Copyright(c) 2009-2013 TJ Holowaychuk - * Copyright(c) 2013 Roman Shtylman - * Copyright(c) 2014-2015 Douglas Christopher Wilson - * MIT Licensed - */ - -'use strict'; - -/** - * Module dependencies. - * @private - */ - -var pathRegexp = require('path-to-regexp'); -var debug = require('debug')('express:router:layer'); - -/** - * Module variables. - * @private - */ - -var hasOwnProperty = Object.prototype.hasOwnProperty; - -/** - * Module exports. - * @public - */ - -module.exports = Layer; - -function Layer(path, options, fn) { - if (!(this instanceof Layer)) { - return new Layer(path, options, fn); - } - - debug('new %s', path); - var opts = options || {}; - - this.handle = fn; - this.name = fn.name || ''; - this.params = undefined; - this.path = undefined; - this.regexp = pathRegexp(path, this.keys = [], opts); - - if (path === '/' && opts.end === false) { - this.regexp.fast_slash = true; - } -} - -/** - * Handle the error for the layer. - * - * @param {Error} error - * @param {Request} req - * @param {Response} res - * @param {function} next - * @api private - */ - -Layer.prototype.handle_error = function handle_error(error, req, res, next) { - var fn = this.handle; - - if (fn.length !== 4) { - // not a standard error handler - return next(error); - } - - try { - fn(error, req, res, next); - } catch (err) { - next(err); - } -}; - -/** - * Handle the request for the layer. - * - * @param {Request} req - * @param {Response} res - * @param {function} next - * @api private - */ - -Layer.prototype.handle_request = function handle(req, res, next) { - var fn = this.handle; - - if (fn.length > 3) { - // not a standard request handler - return next(); - } - - try { - fn(req, res, next); - } catch (err) { - next(err); - } -}; - -/** - * Check if this route matches `path`, if so - * populate `.params`. - * - * @param {String} path - * @return {Boolean} - * @api private - */ - -Layer.prototype.match = function match(path) { - if (path == null) { - // no path, nothing matches - this.params = undefined; - this.path = undefined; - return false; - } - - if (this.regexp.fast_slash) { - // fast path non-ending match for / (everything matches) - this.params = {}; - this.path = ''; - return true; - } - - var m = this.regexp.exec(path); - - if (!m) { - this.params = undefined; - this.path = undefined; - return false; - } - - // store values - this.params = {}; - this.path = m[0]; - - var keys = this.keys; - var params = this.params; - - 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; - } - } - - return true; -}; - -/** - * Decode param value. - * - * @param {string} val - * @return {string} - * @private - */ - -function decode_param(val) { - if (typeof val !== 'string' || val.length === 0) { - return val; - } - - try { - return decodeURIComponent(val); - } catch (err) { - if (err instanceof URIError) { - err.message = 'Failed to decode param \'' + val + '\''; - err.status = err.statusCode = 400; - } - - throw err; - } -} diff --git a/lib/router/route.js b/lib/router/route.js deleted file mode 100644 index 2788d7b7353..00000000000 --- a/lib/router/route.js +++ /dev/null @@ -1,210 +0,0 @@ -/*! - * express - * Copyright(c) 2009-2013 TJ Holowaychuk - * Copyright(c) 2013 Roman Shtylman - * Copyright(c) 2014-2015 Douglas Christopher Wilson - * MIT Licensed - */ - -'use strict'; - -/** - * Module dependencies. - * @private - */ - -var debug = require('debug')('express:router:route'); -var flatten = require('array-flatten'); -var Layer = require('./layer'); -var methods = require('methods'); - -/** - * Module variables. - * @private - */ - -var slice = Array.prototype.slice; -var toString = Object.prototype.toString; - -/** - * Module exports. - * @public - */ - -module.exports = Route; - -/** - * Initialize `Route` with the given `path`, - * - * @param {String} path - * @public - */ - -function Route(path) { - this.path = path; - this.stack = []; - - debug('new %s', path); - - // route handlers for various http methods - this.methods = {}; -} - -/** - * Determine if the route handles a given method. - * @private - */ - -Route.prototype._handles_method = function _handles_method(method) { - if (this.methods._all) { - return true; - } - - var name = method.toLowerCase(); - - if (name === 'head' && !this.methods['head']) { - name = 'get'; - } - - return Boolean(this.methods[name]); -}; - -/** - * @return {Array} supported HTTP methods - * @private - */ - -Route.prototype._options = function _options() { - var methods = Object.keys(this.methods); - - // append automatic head - if (this.methods.get && !this.methods.head) { - methods.push('head'); - } - - for (var i = 0; i < methods.length; i++) { - // make upper case - methods[i] = methods[i].toUpperCase(); - } - - return methods; -}; - -/** - * dispatch req, res into this route - * @private - */ - -Route.prototype.dispatch = function dispatch(req, res, done) { - var idx = 0; - var stack = this.stack; - if (stack.length === 0) { - return done(); - } - - var method = req.method.toLowerCase(); - if (method === 'head' && !this.methods['head']) { - method = 'get'; - } - - req.route = this; - - next(); - - function next(err) { - if (err && err === 'route') { - return done(); - } - - var layer = stack[idx++]; - if (!layer) { - return done(err); - } - - if (layer.method && layer.method !== method) { - return next(err); - } - - if (err) { - layer.handle_error(err, req, res, next); - } else { - layer.handle_request(req, res, next); - } - } -}; - -/** - * Add a handler for all HTTP verbs to this route. - * - * Behaves just like middleware and can respond or call `next` - * to continue processing. - * - * You can use multiple `.all` call to add multiple handlers. - * - * function check_something(req, res, next){ - * next(); - * }; - * - * function validate_user(req, res, next){ - * next(); - * }; - * - * route - * .all(validate_user) - * .all(check_something) - * .get(function(req, res, next){ - * res.send('hello world'); - * }); - * - * @param {function} handler - * @return {Route} for chaining - * @api public - */ - -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 TypeError(msg); - } - - var layer = Layer('/', {}, handle); - layer.method = undefined; - - this.methods._all = true; - this.stack.push(layer); - } - - return this; -}; - -methods.forEach(function(method){ - Route.prototype[method] = function(){ - 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.' + method + '() requires callback functions but got a ' + type; - throw new Error(msg); - } - - debug('%s %s', method, this.path); - - var layer = Layer('/', {}, handle); - layer.method = method; - - this.methods[method] = true; - this.stack.push(layer); - } - - return this; - }; -}); diff --git a/package.json b/package.json index e4f0f10e54c..724de38fbed 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "proxy-addr": "~1.0.8", "qs": "4.0.0", "range-parser": "~1.0.2", + "router": "~1.1.2", "send": "0.13.0", "serve-static": "~1.10.0", "type-is": "~1.6.4", diff --git a/test/Router.js b/test/Router.js index 9f28952a44b..6ab8651832f 100644 --- a/test/Router.js +++ b/test/Router.js @@ -27,7 +27,7 @@ describe('Router', function(){ }); router.use('/foo', another); - router.handle({ url: '/foo/bar', method: 'GET' }, { end: done }); + router.handle({ url: '/foo/bar', method: 'GET' }, { end: done }, function(){}); }); it('should support dynamic routes', function(done){ @@ -40,7 +40,7 @@ describe('Router', function(){ }); router.use('/:foo', another); - router.handle({ url: '/test/route', method: 'GET' }, { end: done }); + router.handle({ url: '/test/route', method: 'GET' }, { end: done }, function(){}); }); it('should handle blank URL', function(done){ @@ -65,7 +65,7 @@ describe('Router', function(){ res.end(); }); - router.handle({ url: '/', method: 'GET' }, { end: done }); + router.handle({ url: '/', method: 'GET' }, { end: done }, function(){}); }); describe('.handle', function(){ @@ -82,7 +82,7 @@ describe('Router', function(){ done(); } } - router.handle({ url: '/foo', method: 'GET' }, res); + router.handle({ url: '/foo', method: 'GET' }, res, function(){}); }) }) @@ -342,15 +342,15 @@ describe('Router', function(){ describe('.use', function() { it('should require arguments', function(){ var router = new Router(); - router.use.bind(router).should.throw(/requires middleware function/) + assert.throws(router.use.bind(router), /argument handler is required/) }) it('should not accept non-functions', function(){ var router = new Router(); - router.use.bind(router, '/', 'hello').should.throw(/requires middleware function.*string/) - router.use.bind(router, '/', 5).should.throw(/requires middleware function.*number/) - router.use.bind(router, '/', null).should.throw(/requires middleware function.*Null/) - router.use.bind(router, '/', new Date()).should.throw(/requires middleware function.*Date/) + assert.throws(router.use.bind(router, '/', 'hello'), /argument handler must be a function/) + assert.throws(router.use.bind(router, '/', 5), /argument handler must be a function/) + assert.throws(router.use.bind(router, '/', null), /argument handler must be a function/) + assert.throws(router.use.bind(router, '/', new Date()), /argument handler must be a function/) }) it('should accept array of middleware', function(done){ diff --git a/test/app.options.js b/test/app.options.js index 96db91447ab..3f13f1d244b 100644 --- a/test/app.options.js +++ b/test/app.options.js @@ -12,8 +12,8 @@ describe('OPTIONS', function(){ request(app) .options('/users') - .expect('Allow', 'GET,HEAD,PUT') - .expect(200, 'GET,HEAD,PUT', done); + .expect('Allow', 'GET, HEAD, PUT') + .expect(200, 'GET, HEAD, PUT', done); }) it('should only include each method once', function(done){ @@ -26,8 +26,8 @@ describe('OPTIONS', function(){ request(app) .options('/users') - .expect('Allow', 'GET,HEAD,PUT') - .expect(200, 'GET,HEAD,PUT', done); + .expect('Allow', 'GET, HEAD, PUT') + .expect(200, 'GET, HEAD, PUT', done); }) it('should not be affected by app.all', function(done){ @@ -44,8 +44,8 @@ describe('OPTIONS', function(){ request(app) .options('/users') .expect('x-hit', '1') - .expect('Allow', 'GET,HEAD,PUT') - .expect(200, 'GET,HEAD,PUT', done); + .expect('Allow', 'GET, HEAD, PUT') + .expect(200, 'GET, HEAD, PUT', done); }) it('should not respond if the path is not defined', function(done){ @@ -68,8 +68,8 @@ describe('OPTIONS', function(){ request(app) .options('/other') - .expect('Allow', 'GET,HEAD') - .expect(200, 'GET,HEAD', done); + .expect('Allow', 'GET, HEAD') + .expect(200, 'GET, HEAD', done); }) describe('when error occurs in respone handler', function () { diff --git a/test/app.router.js b/test/app.router.js index 27d2390c6ab..3ef7b997832 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -56,7 +56,7 @@ describe('app.router', function(){ it('should reject numbers for app.' + method, function(){ var app = express(); - app[method].bind(app, '/', 3).should.throw(/Number/); + assert.throws(app[method].bind(app, '/', 3), /argument handler must be a function/); }) }); diff --git a/test/app.use.js b/test/app.use.js index b2031e4c56c..4a35c488e81 100644 --- a/test/app.use.js +++ b/test/app.use.js @@ -1,5 +1,6 @@ var after = require('after'); +var assert = require('assert'); var express = require('..'); var request = require('supertest'); @@ -255,15 +256,15 @@ describe('app', function(){ describe('.use(path, middleware)', function(){ it('should reject missing functions', function () { var app = express(); - app.use.bind(app, '/').should.throw(/requires middleware function/); + assert.throws(app.use.bind(app, '/'), /requires middleware function/); }) it('should reject non-functions as middleware', function () { var app = express(); - app.use.bind(app, '/', 'hi').should.throw(/requires middleware function.*string/); - app.use.bind(app, '/', 5).should.throw(/requires middleware function.*number/); - app.use.bind(app, '/', null).should.throw(/requires middleware function.*Null/); - app.use.bind(app, '/', new Date()).should.throw(/requires middleware function.*Date/); + assert.throws(app.use.bind(app, '/', 'hi'), /argument handler must be a function/); + assert.throws(app.use.bind(app, '/', 5), /argument handler must be a function/); + assert.throws(app.use.bind(app, '/', null), /argument handler must be a function/); + assert.throws(app.use.bind(app, '/', new Date()), /argument handler must be a function/); }) it('should strip path from req.url', function (done) { From 694869d2aa7b5ff5886faf1642011858fc779c36 Mon Sep 17 00:00:00 2001 From: Jeremiah Senkpiel Date: Fri, 17 Apr 2015 12:41:27 -0400 Subject: [PATCH 024/889] Use path-is-absolute module for absolute path detection closes #2620 --- History.md | 1 + lib/response.js | 4 ++-- lib/utils.js | 14 -------------- package.json | 1 + test/utils.js | 16 ---------------- 5 files changed, 4 insertions(+), 32 deletions(-) diff --git a/History.md b/History.md index fbc7538cce9..93e431375ad 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,7 @@ This incorporates all changes after 4.10.1 up to 4.13.1. * change: - The leading `:` character in `name` for `app.param(name, fn)` is no longer removed - Use `router` module for routing + - Use `path-is-absolute` module for absolute path detection 5.0.0-alpha.1 / 2014-11-06 ========================== diff --git a/lib/response.js b/lib/response.js index 068cf07b34e..d10d63ee15f 100644 --- a/lib/response.js +++ b/lib/response.js @@ -16,9 +16,9 @@ var contentDisposition = require('content-disposition'); var deprecate = require('depd')('express'); var escapeHtml = require('escape-html'); var http = require('http'); -var isAbsolute = require('./utils').isAbsolute; var onFinished = require('on-finished'); var path = require('path'); +var pathIsAbsolute = require('path-is-absolute'); var merge = require('utils-merge'); var sign = require('cookie-signature').sign; var normalizeType = require('./utils').normalizeType; @@ -369,7 +369,7 @@ res.sendFile = function sendFile(path, options, callback) { opts = {}; } - if (!opts.root && !isAbsolute(path)) { + if (!opts.root && !pathIsAbsolute(path)) { throw new TypeError('path must be absolute or specify root to res.sendFile'); } diff --git a/lib/utils.js b/lib/utils.js index 2be07196a37..8c111eb7b68 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -54,20 +54,6 @@ exports.wetag = function wetag(body, encoding){ return etag(buf, {weak: true}); }; -/** - * Check if `path` looks absolute. - * - * @param {String} path - * @return {Boolean} - * @api private - */ - -exports.isAbsolute = function(path){ - if ('/' == path[0]) return true; - if (':' == path[1] && '\\' == path[2]) return true; - if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path -}; - /** * Normalize the given `type`, for example "html" becomes "text/html". * diff --git a/package.json b/package.json index 724de38fbed..22a75e29ff7 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "methods": "~1.1.1", "on-finished": "~2.3.0", "parseurl": "~1.3.0", + "path-is-absolute": "1.0.0", "path-to-regexp": "0.1.6", "proxy-addr": "~1.0.8", "qs": "4.0.0", diff --git a/test/utils.js b/test/utils.js index 050ebc1a29b..62d34bd105d 100644 --- a/test/utils.js +++ b/test/utils.js @@ -69,19 +69,3 @@ describe('utils.wetag(body, encoding)', function(){ .should.eql('W/"0-1B2M2Y8AsgTpgAmY7PhCfg"'); }) }) - -describe('utils.isAbsolute()', function(){ - it('should support windows', function(){ - assert(utils.isAbsolute('c:\\')); - assert(!utils.isAbsolute(':\\')); - }) - - it('should support windows unc', function(){ - assert(utils.isAbsolute('\\\\foo\\bar')) - }) - - it('should support unices', function(){ - assert(utils.isAbsolute('/foo/bar')); - assert(!utils.isAbsolute('foo/bar')); - }) -}) From 6343288bef29ab2b0a6f2c6d9888f30e49203a9d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 7 Jul 2015 01:02:13 -0400 Subject: [PATCH 025/889] Make res.render callback is always async, even for sync view engines closes #2668 --- History.md | 1 + lib/view.js | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 93e431375ad..d9117764cce 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,7 @@ This incorporates all changes after 4.10.1 up to 4.13.1. - `app.param(fn)` - `req.param()` -- use `req.params`, `req.body`, or `req.query` instead * change: + - `res.render` callback is always async, even for sync view engines - The leading `:` character in `name` for `app.param(name, fn)` is no longer removed - Use `router` module for routing - Use `path-is-absolute` module for absolute path detection diff --git a/lib/view.js b/lib/view.js index 52415d4c28b..759ecc442a7 100644 --- a/lib/view.js +++ b/lib/view.js @@ -122,8 +122,31 @@ View.prototype.lookup = function lookup(name) { */ View.prototype.render = function render(options, callback) { + var sync = true; + debug('render "%s"', this.path); - this.engine(this.path, options, callback); + + // render, normalizing sync callbacks + this.engine(this.path, options, function onRender() { + if (!sync) { + return callback.apply(this, arguments); + } + + // copy arguments + var args = new Array(arguments.length); + var cntx = this; + + for (var i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } + + // force callback to be async + return process.nextTick(function renderTick() { + return callback.apply(cntx, args); + }); + }); + + sync = false; }; /** From 2c668f87c7c14245d9400cd1357b7dbb38526a3c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 7 Jul 2015 01:33:55 -0400 Subject: [PATCH 026/889] 5.0.0-alpha.2 --- History.md | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index d9117764cce..21d5da345f4 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,8 @@ -5.x -=== +5.0.0-alpha.2 / 2015-07-06 +========================== -This incorporates all changes after 4.10.1 up to 4.13.1. +This is the second Express 5.0 alpha release, based off 4.13.1 and includes +changes from 5.0.0-alpha.1. * remove: - `app.param(fn)` diff --git a/package.json b/package.json index 22a75e29ff7..ab4c50b1102 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-alpha.1", + "version": "5.0.0-alpha.2", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From de7ffca33ff30932bdaa2dbe51862af32e8a30b1 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 24 Jul 2015 21:36:56 -0400 Subject: [PATCH 027/889] tests: add test for matching route after error --- test/app.routes.error.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/app.routes.error.js b/test/app.routes.error.js index ac517efdee2..7c49d50ffe2 100644 --- a/test/app.routes.error.js +++ b/test/app.routes.error.js @@ -3,6 +3,22 @@ var express = require('../') describe('app', function(){ describe('.VERB()', function(){ + it('should not get invoked without error handler on error', function(done) { + var app = express(); + + app.use(function(req, res, next){ + next(new Error('boom!')) + }); + + app.get('/bar', function(req, res){ + res.send('hello, world!'); + }); + + request(app) + .post('/bar') + .expect(500, /Error: boom!/, done); + }); + it('should only call an error handling routing callback when an error is propagated', function(done){ var app = express(); From fc95112145a122b9e3aaa56f82b00eae9b8fe001 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 27 Jul 2015 22:09:34 -0400 Subject: [PATCH 028/889] build: should@7.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d78a2576efa..8cf5203b6f1 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "istanbul": "0.3.9", "marked": "0.3.3", "mocha": "2.2.5", - "should": "7.0.1", + "should": "7.0.2", "supertest": "1.0.1" }, "engines": { From d51d1ea57afea4a2df288e3f541d092fce8721b7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 27 Jul 2015 22:11:54 -0400 Subject: [PATCH 029/889] build: ejs@2.3.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8cf5203b6f1..78f40ce989a 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "connect-redis": "~1.5.0", - "ejs": "2.3.2", + "ejs": "2.3.3", "istanbul": "0.3.9", "marked": "0.3.3", "mocha": "2.2.5", From b53feaa1d8b8701b6c0085ff520f59cd1e7dccd8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 27 Jul 2015 22:12:39 -0400 Subject: [PATCH 030/889] deps: vary@~1.0.1 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 581960b7111..27650df168a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +3.x +=== + + * deps: vary@~1.0.1 + - Fix setting empty header from empty `field` + - perf: enable strict mode + - perf: remove argument reassignments + 3.21.1 / 2015-07-05 =================== diff --git a/package.json b/package.json index 78f40ce989a..24fdca64021 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "range-parser": "~1.0.2", "send": "0.13.0", "utils-merge": "1.0.0", - "vary": "~1.0.0" + "vary": "~1.0.1" }, "devDependencies": { "connect-redis": "~1.5.0", From 09c80bf823e16daafafc2ed013b07c62380a6912 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 28 Jul 2015 23:24:00 -0400 Subject: [PATCH 031/889] deps: array-flatten@1.1.1 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 3362daefb49..dbcde7e4053 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +unreleased +========== + + * deps: array-flatten@1.1.1 + - perf: enable strict mode + 4.13.1 / 2015-07-05 =================== diff --git a/package.json b/package.json index 4c4a3b7a767..973067eb653 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ ], "dependencies": { "accepts": "~1.2.10", - "array-flatten": "1.1.0", + "array-flatten": "1.1.1", "content-disposition": "0.5.0", "content-type": "~1.0.1", "cookie": "0.1.3", From 659c0b154c965f4945e061adcc52c2abf6254dbe Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 28 Jul 2015 23:26:31 -0400 Subject: [PATCH 032/889] deps: update example dependencies --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 973067eb653..7b2f63143c2 100644 --- a/package.json +++ b/package.json @@ -62,15 +62,15 @@ "should": "7.0.1", "supertest": "1.0.1", "body-parser": "~1.13.2", - "connect-redis": "~2.3.0", + "connect-redis": "~2.4.1", "cookie-parser": "~1.3.5", "cookie-session": "~1.2.0", "express-session": "~1.11.3", "jade": "~1.11.0", - "method-override": "~2.3.3", + "method-override": "~2.3.4", "morgan": "~1.6.1", "multiparty": "~4.1.2", - "vhost": "~3.0.0" + "vhost": "~3.0.1" }, "engines": { "node": ">= 0.10.0" From 93dd15cd615f29315f68043a453953af37a870dc Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 31 Jul 2015 16:13:09 -0400 Subject: [PATCH 033/889] deps: connect@2.30.2 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 27650df168a..3bb407e7d19 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,14 @@ 3.x === + * deps: connect@2.30.2 + - deps: body-parser@~1.13.3 + - deps: compression@~1.5.2 + - deps: errorhandler@~1.4.2 + - deps: method-override@~2.3.5 + - deps: serve-index@~1.7.2 + - deps: type-is@~1.6.6 + - deps: vhost@~3.0.1 * deps: vary@~1.0.1 - Fix setting empty header from empty `field` - perf: enable strict mode diff --git a/package.json b/package.json index 24fdca64021..486a7e39467 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ ], "dependencies": { "basic-auth": "~1.0.3", - "connect": "2.30.1", + "connect": "2.30.2", "content-disposition": "0.5.0", "content-type": "~1.0.1", "commander": "2.6.0", From ce087e559ea416a7dc2f5a6e5eb0aa4f6be8ff2c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 31 Jul 2015 16:13:41 -0400 Subject: [PATCH 034/889] build: marked@0.3.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 486a7e39467..c129cb95312 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "connect-redis": "~1.5.0", "ejs": "2.3.3", "istanbul": "0.3.9", - "marked": "0.3.3", + "marked": "0.3.5", "mocha": "2.2.5", "should": "7.0.2", "supertest": "1.0.1" From cb59086305367d9fcd7d63b53cfca1a3e4ef77d7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 31 Jul 2015 16:15:06 -0400 Subject: [PATCH 035/889] 3.21.2 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 3bb407e7d19..f95055ae6e0 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -3.x -=== +3.21.2 / 2015-07-31 +=================== * deps: connect@2.30.2 - deps: body-parser@~1.13.3 diff --git a/package.json b/package.json index c129cb95312..321a07e7655 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Sinatra inspired web development framework", - "version": "3.21.1", + "version": "3.21.2", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From e33c5035bb3e96f465e8a6c5678706fcb1bcb236 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Tue, 28 Jul 2015 13:15:34 +1000 Subject: [PATCH 036/889] deps: path-to-regexp@0.1.7 closes #2717 --- History.md | 2 ++ package.json | 2 +- test/app.router.js | 12 ++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index dd2366d32b2..4e7e76c6f86 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ unreleased * deps: array-flatten@1.1.1 - perf: enable strict mode + * deps: path-to-regexp@0.1.7 + - Fix regression with escaped round brackets and matching groups 4.13.1 / 2015-07-05 =================== diff --git a/package.json b/package.json index f952bc1df76..d9981e71dd3 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.6", + "path-to-regexp": "0.1.7", "proxy-addr": "~1.0.8", "qs": "4.0.0", "range-parser": "~1.0.2", diff --git a/test/app.router.js b/test/app.router.js index 491de358f07..f528a4cb21f 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -721,6 +721,18 @@ describe('app.router', function(){ .expect('editing tj (old)', cb); }) + it('should work inside literal paranthesis', function(done){ + var app = express(); + + app.get('/:user\\(:op\\)', function(req, res){ + res.end(req.params.op + 'ing ' + req.params.user); + }); + + request(app) + .get('/tj(edit)') + .expect('editing tj', done); + }) + it('should work in array of paths', function(done){ var app = express(); var cb = after(2, done); From 1cea9cedec212695b298afcebadc7473a28a98e6 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 31 Jul 2015 17:01:35 -0400 Subject: [PATCH 037/889] deps: accepts@~1.2.12 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 4e7e76c6f86..1f1b091fdf0 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,8 @@ unreleased ========== + * deps: accepts@~1.2.12 + - deps: mime-types@~2.1.4 * deps: array-flatten@1.1.1 - perf: enable strict mode * deps: path-to-regexp@0.1.7 diff --git a/package.json b/package.json index d9981e71dd3..3bdb417394d 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "api" ], "dependencies": { - "accepts": "~1.2.10", + "accepts": "~1.2.12", "array-flatten": "1.1.1", "content-disposition": "0.5.0", "content-type": "~1.0.1", From c398a9903df7e4ce50699d597914e1bd7c7019de Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 31 Jul 2015 17:02:10 -0400 Subject: [PATCH 038/889] deps: type-is@~1.6.6 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 1f1b091fdf0..2284ffcc978 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,8 @@ unreleased - perf: enable strict mode * deps: path-to-regexp@0.1.7 - Fix regression with escaped round brackets and matching groups + * deps: type-is@~1.6.6 + - deps: mime-types@~2.1.4 4.13.1 / 2015-07-05 =================== diff --git a/package.json b/package.json index 3bdb417394d..8e8bd20da8e 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.4", + "type-is": "~1.6.6", "utils-merge": "1.0.0", "vary": "~1.0.1" }, From a559ca2d58b0fcf9248148baf472460fd08e36ac Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 31 Jul 2015 17:02:57 -0400 Subject: [PATCH 039/889] build: istanbul@0.3.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8e8bd20da8e..323f8084b37 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "devDependencies": { "after": "0.8.1", "ejs": "2.3.3", - "istanbul": "0.3.9", + "istanbul": "0.3.17", "marked": "0.3.5", "mocha": "2.2.5", "should": "7.0.2", From a4fcd91084eaedb36b7c150157236d5d563a4b02 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 31 Jul 2015 17:03:30 -0400 Subject: [PATCH 040/889] deps: update example dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 323f8084b37..3bee76bc601 100644 --- a/package.json +++ b/package.json @@ -61,13 +61,13 @@ "mocha": "2.2.5", "should": "7.0.2", "supertest": "1.0.1", - "body-parser": "~1.13.2", + "body-parser": "~1.13.3", "connect-redis": "~2.4.1", "cookie-parser": "~1.3.5", "cookie-session": "~1.2.0", "express-session": "~1.11.3", "jade": "~1.11.0", - "method-override": "~2.3.4", + "method-override": "~2.3.5", "morgan": "~1.6.1", "multiparty": "~4.1.2", "vhost": "~3.0.1" From 97b2d70d8adfb4649fd8ca9adc73c47ffcc4bf5b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 31 Jul 2015 17:09:15 -0400 Subject: [PATCH 041/889] 4.13.2 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 2284ffcc978..dc406139c24 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.13.2 / 2015-07-31 +=================== * deps: accepts@~1.2.12 - deps: mime-types@~2.1.4 diff --git a/package.json b/package.json index 3bee76bc601..3b4389e8bfe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.13.1", + "version": "4.13.2", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From ee90042d0c4a32a426842e4c1ad5b24b5c0344ac Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 3 Aug 2015 00:50:48 -0400 Subject: [PATCH 042/889] Fix infinite loop condition using mergeParams: true --- History.md | 5 +++++ lib/router/index.js | 9 ++++++--- test/app.router.js | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index dc406139c24..3cc3e11d21d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Fix infinite loop condition using `mergeParams: true` + 4.13.2 / 2015-07-31 =================== diff --git a/lib/router/index.js b/lib/router/index.js index 1f3ec6d49ce..4b7e4c97eda 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -578,9 +578,12 @@ function mergeParams(params, parent) { var o = 0; // determine numeric gaps - while (i === o || o in parent) { - if (i in params) i++; - if (o in parent) o++; + while (i in params) { + i++; + } + + while (o in parent) { + o++; } // offset numeric indices in params before merge diff --git a/test/app.router.js b/test/app.router.js index f528a4cb21f..aa753e90e76 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -320,6 +320,22 @@ describe('app.router', function(){ .expect(200, '[["0","10"],["1","tj"],["2","profile"]]', done); }) + it('should merge numeric indices req.params when parent has same number', function(done){ + var app = express(); + var router = new express.Router({ mergeParams: true }); + + router.get('/name:(\\w+)', function(req, res){ + var keys = Object.keys(req.params).sort(); + res.send(keys.map(function(k){ return [k, req.params[k]] })); + }); + + app.use('/user/id:(\\d+)', router); + + request(app) + .get('/user/id:10/name:tj') + .expect(200, '[["0","10"],["1","tj"]]', done); + }) + it('should ignore invalid incoming req.params', function(done){ var app = express(); var router = new express.Router({ mergeParams: true }); From 11a77a3fffb0476a460c4e68536ce20f5b3c542f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 3 Aug 2015 01:01:16 -0400 Subject: [PATCH 043/889] Fix inner numeric indices incorrectly altering parent req.params --- History.md | 1 + lib/router/index.js | 2 +- test/app.router.js | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 3cc3e11d21d..d4eff1f7345 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ unreleased ========== * Fix infinite loop condition using `mergeParams: true` + * Fix inner numeric indices incorrectly altering parent `req.params` 4.13.2 / 2015-07-31 =================== diff --git a/lib/router/index.js b/lib/router/index.js index 4b7e4c97eda..504ed9ce0ee 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -596,7 +596,7 @@ function mergeParams(params, parent) { } } - return mixin(parent, params); + return mixin(obj, params); } // restore obj props after function diff --git a/test/app.router.js b/test/app.router.js index aa753e90e76..03b43eb081a 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -354,6 +354,26 @@ describe('app.router', function(){ .get('/user/tj') .expect(200, '[["name","tj"]]', done); }) + + it('should restore req.params', function(done){ + var app = express(); + var router = new express.Router({ mergeParams: true }); + + router.get('/user:(\\w+)/*', function (req, res, next) { + next(); + }); + + app.use('/user/id:(\\d+)', function (req, res, next) { + router(req, res, function (err) { + var keys = Object.keys(req.params).sort(); + res.send(keys.map(function(k){ return [k, req.params[k]] })); + }); + }); + + request(app) + .get('/user/id:42/user:tj/profile') + .expect(200, '[["0","42"]]', done); + }) }) describe('trailing slashes', function(){ From ef7ad681b245fba023843ce94f6bcb8e275bbb8e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 3 Aug 2015 01:02:22 -0400 Subject: [PATCH 044/889] 4.13.3 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index d4eff1f7345..be89c8e7230 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.13.3 / 2015-08-02 +=================== * Fix infinite loop condition using `mergeParams: true` * Fix inner numeric indices incorrectly altering parent `req.params` diff --git a/package.json b/package.json index 3b4389e8bfe..3f299bada86 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.13.2", + "version": "4.13.3", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 2f8ac6726fa20ab5b4a05c112c886752868ac8ce Mon Sep 17 00:00:00 2001 From: Brendan Ashworth Date: Thu, 25 Jun 2015 00:30:19 -0700 Subject: [PATCH 045/889] tests: fix redirect tests for change in 302 status message closes #2690 --- test/res.redirect.js | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/test/res.redirect.js b/test/res.redirect.js index 4044ad49ee5..7ebc1ef01dc 100644 --- a/test/res.redirect.js +++ b/test/res.redirect.js @@ -1,6 +1,7 @@ -var express = require('../') - , request = require('supertest'); +var http = require('http'); +var express = require('..'); +var request = require('supertest'); describe('res', function(){ describe('.redirect(url)', function(){ @@ -83,11 +84,9 @@ describe('res', function(){ request(app) .get('/') .set('Accept', 'text/html') - .end(function(err, res){ - res.headers.should.have.property('location', 'http://google.com/'); - res.text.should.equal('

Moved Temporarily. Redirecting to http://google.com

'); - done(); - }) + .expect('Content-Type', /html/) + .expect('Location', 'http://google.com/') + .expect(302, '

' + http.STATUS_CODES[302] + '. Redirecting to http://google.com

', done); }) it('should escape the url', function(done){ @@ -101,10 +100,9 @@ describe('res', function(){ .get('/') .set('Host', 'http://example.com/') .set('Accept', 'text/html') - .end(function(err, res){ - res.text.should.equal('

Moved Temporarily. Redirecting to <lame>

'); - done(); - }) + .expect('Content-Type', /html/) + .expect('Location', '') + .expect(302, '

' + http.STATUS_CODES[302] + '. Redirecting to <lame>

', done); }) it('should include the redirect type', function(done){ @@ -134,12 +132,9 @@ describe('res', function(){ request(app) .get('/') .set('Accept', 'text/plain, */*') - .end(function(err, res){ - res.headers.should.have.property('location', 'http://google.com/'); - res.headers.should.have.property('content-length', '51'); - res.text.should.equal('Moved Temporarily. Redirecting to http://google.com'); - done(); - }) + .expect('Content-Type', /plain/) + .expect('Location', 'http://google.com/') + .expect(302, http.STATUS_CODES[302] + '. Redirecting to http://google.com', done); }) it('should encode the url', function(done){ @@ -153,10 +148,9 @@ describe('res', function(){ .get('/') .set('Host', 'http://example.com/') .set('Accept', 'text/plain, */*') - .end(function(err, res){ - res.text.should.equal('Moved Temporarily. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E'); - done(); - }) + .expect('Content-Type', /plain/) + .expect('Location', 'http://example.com/?param=%3Cscript%3Ealert("hax");') + .expect(302, http.STATUS_CODES[302] + '. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E', done); }) it('should include the redirect type', function(done){ From 5a4310e9da32bd1dc49977247615be253f56b1f7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 6 Nov 2015 22:09:47 -0500 Subject: [PATCH 046/889] build: reduce runtime versions to one per major --- .travis.yml | 2 -- appveyor.yml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index df087b4a0f7..f1f609b5922 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,7 @@ language: node_js node_js: - "0.10" - "0.12" - - "1.0" - "1.8" - - "2.0" - "2.3" sudo: false before_install: "npm rm --save-dev connect-redis" diff --git a/appveyor.yml b/appveyor.yml index b1f13d167bd..5a8f3080bf1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,9 +2,7 @@ environment: matrix: - nodejs_version: "0.10" - nodejs_version: "0.12" - - nodejs_version: "1.0" - nodejs_version: "1.8" - - nodejs_version: "2.0" - nodejs_version: "2.3" install: - ps: Install-Product node $env:nodejs_version From 2f96412636ef04c5639e38768de0f2b526f02e32 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 6 Nov 2015 22:16:06 -0500 Subject: [PATCH 047/889] build: io.js@2.5 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f1f609b5922..7c98d22d8eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ node_js: - "0.10" - "0.12" - "1.8" - - "2.3" + - "2.5" 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 5a8f3080bf1..bce7c64deeb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,7 +3,7 @@ environment: - nodejs_version: "0.10" - nodejs_version: "0.12" - nodejs_version: "1.8" - - nodejs_version: "2.3" + - nodejs_version: "2.5" install: - ps: Install-Product node $env:nodejs_version - npm rm --save-dev connect-redis From 963d795d24ee951ce5382ccb0554f8a1960641e2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 6 Nov 2015 22:47:15 -0500 Subject: [PATCH 048/889] build: support io.js 3.x --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7c98d22d8eb..cc679216af1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ node_js: - "0.12" - "1.8" - "2.5" + - "3.3" 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 bce7c64deeb..40ee0765374 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,6 +4,7 @@ environment: - nodejs_version: "0.12" - nodejs_version: "1.8" - nodejs_version: "2.5" + - nodejs_version: "3.3" install: - ps: Install-Product node $env:nodejs_version - npm rm --save-dev connect-redis From 1a59246746045ff78d31a0cd997d3679010b7f4e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 6 Nov 2015 22:49:44 -0500 Subject: [PATCH 049/889] build: mocha@2.3.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f299bada86..99b8f85a949 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "ejs": "2.3.3", "istanbul": "0.3.17", "marked": "0.3.5", - "mocha": "2.2.5", + "mocha": "2.3.3", "should": "7.0.2", "supertest": "1.0.1", "body-parser": "~1.13.3", From 2f37f4b28d52c3ae18e5e1930ccc776647f86531 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 6 Nov 2015 22:51:09 -0500 Subject: [PATCH 050/889] build: istanbul@0.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 99b8f85a949..2a432203aea 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "devDependencies": { "after": "0.8.1", "ejs": "2.3.3", - "istanbul": "0.3.17", + "istanbul": "0.4.0", "marked": "0.3.5", "mocha": "2.3.3", "should": "7.0.2", From 9665aa2153c5eca8b6ccdc22ce43a0934475fae8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 6 Nov 2015 22:57:04 -0500 Subject: [PATCH 051/889] build: supertest@1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2a432203aea..25186caf064 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "marked": "0.3.5", "mocha": "2.3.3", "should": "7.0.2", - "supertest": "1.0.1", + "supertest": "1.1.0", "body-parser": "~1.13.3", "connect-redis": "~2.4.1", "cookie-parser": "~1.3.5", From 747fccfb44c61f309e1258959c6c3ad61bdc767c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 6 Nov 2015 22:59:46 -0500 Subject: [PATCH 052/889] build: should@7.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 25186caf064..2b983b810dc 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "istanbul": "0.4.0", "marked": "0.3.5", "mocha": "2.3.3", - "should": "7.0.2", + "should": "7.1.1", "supertest": "1.1.0", "body-parser": "~1.13.3", "connect-redis": "~2.4.1", From 5699d64b99412bb3251d265f272ba25be03fa0d3 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 7 Nov 2015 00:15:39 -0500 Subject: [PATCH 053/889] build: ejs@2.3.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b983b810dc..27c165bb6c6 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ }, "devDependencies": { "after": "0.8.1", - "ejs": "2.3.3", + "ejs": "2.3.4", "istanbul": "0.4.0", "marked": "0.3.5", "mocha": "2.3.3", From e5ec966b2f068e935ea1b33374fac133dd06cdc8 Mon Sep 17 00:00:00 2001 From: Alexander Shemetovsky Date: Tue, 25 Aug 2015 21:03:05 +0300 Subject: [PATCH 054/889] Fix param definition is jsdoc for app.render fixes #2741 --- lib/application.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/application.js b/lib/application.js index a9df9103540..0ee4def3890 100644 --- a/lib/application.js +++ b/lib/application.js @@ -522,7 +522,7 @@ app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead'); * }) * * @param {String} name - * @param {String|Function} options or fn + * @param {Object|Function} options or fn * @param {Function} callback * @public */ From 7a3b5aea11abbae6ce4be9094c3acd74e4af95c2 Mon Sep 17 00:00:00 2001 From: Ricardo Bin Date: Tue, 27 Oct 2015 09:50:42 -0200 Subject: [PATCH 055/889] tests: add test for res.send() without arguments closes #2778 closes #2783 --- test/res.send.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/res.send.js b/test/res.send.js index 23aa5f7911f..6eafb944966 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -5,6 +5,20 @@ var methods = require('methods'); var request = require('supertest'); describe('res', function(){ + describe('.send()', function(){ + it('should set body to ""', function(done){ + var app = express(); + + app.use(function(req, res){ + res.send(); + }); + + request(app) + .get('/') + .expect(200, '', done); + }) + }) + describe('.send(null)', function(){ it('should set body to ""', function(done){ var app = express(); From 42b944295a12e09426bc220aae0cd5c1b2410ae2 Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Fri, 13 Nov 2015 13:35:09 -0800 Subject: [PATCH 056/889] Add Security document closes #2733 closes #2804 --- Readme.md | 4 ++++ Security.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 Security.md diff --git a/Readme.md b/Readme.md index 8da83a517e1..d0c081ccfed 100644 --- a/Readme.md +++ b/Readme.md @@ -47,6 +47,10 @@ $ npm install express **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/strongloop/express/wiki/New-features-in-4.x). +###Security Issues + +If you discover a security vulnerability in Express, please see [Security Policies and Procedures](security.md). + ## Quick Start The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below: diff --git a/Security.md b/Security.md new file mode 100644 index 00000000000..0c6d82324f1 --- /dev/null +++ b/Security.md @@ -0,0 +1,53 @@ +# Security Policies and Procedures + +This document outlines security procedures and general policies for the Express +project. + + * [Reporting a Bug](#reporting-a-bug) + * [Disclosure Policy](#disclosure-policy) + * [Receiving Security Updates](#receiving-security-updates) + * [Comments on this Policy](#comments-on-this-policy) + +## Reporting a Bug + +The Express team and community take all security bugs in Express seriously. +Thank you for improving the security of Express. We appreciate your efforts and +responsible disclosure and will make every effort to acknowledge your +contributions. + +Report security bugs by emailing security@expressjs.com. Email to this address +is delivered to a subset of the core team who handle security issues. + +The security team will acknowledge your email within 24 hours, and will send a +more detailed response within 48 hours indicating the next steps in handling +your report. After the initial reply to your report, the security team will +endeavor to keep you informed of the progress towards a fix and full +announcement, and may ask for additional information or guidance. + +Report security bugs in third-party modules to the person or team maintaining +the module. You can also report a vulnerability through the +[Node Security Project](https://nodesecurity.io/report). + +## Disclosure Policy + +When the security team receives a security bug report, they will assign it to a +primary handler. This person will coordinate the fix and release process, +involving the following steps: + + * Confirm the problem and determine the affected versions. + * Audit code to find any potential similar problems. + * Prepare fixes for all releases still under maintenance. These fixes will be + released as fast as possible to npm. + +## Receiving Security Updates + +Security notifications will be distributed via the following methods. + + * https://groups.google.com/forum/#!forum/express-js + * http://blog.strongloop.com + * http://expressjs.com/advanced/security-updates.html + +## Comments on this Policy + +If you have suggestions on how this process could be improved please submit a +pull request or email security@expressjs.com to discuss. From 67116cc5e6fa34b64bc7444c65642c188a6ce0db Mon Sep 17 00:00:00 2001 From: Young Jae Sim Date: Thu, 3 Dec 2015 02:27:25 +0900 Subject: [PATCH 057/889] docs: remove link to Korean translation closes #2820 --- Readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Readme.md b/Readme.md index d0c081ccfed..0f3f40ff14e 100644 --- a/Readme.md +++ b/Readme.md @@ -43,7 +43,6 @@ $ npm install express * Visit the [Wiki](https://github.com/strongloop/express/wiki) * [Google Group](https://groups.google.com/group/express-js) for discussion * [Русскоязычная документация](http://jsman.ru/express/) - * [한국어 문서](http://expressjs.kr) - [[website repo](https://github.com/Hanul/expressjs.kr)] **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/strongloop/express/wiki/New-features-in-4.x). From 23f021a3e1643d72110de30925228350b4454d2e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 14 Dec 2015 23:10:31 -0500 Subject: [PATCH 058/889] build: support Node.js 4.x closes #2751 closes #2754 closes #2757 --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index cc679216af1..90852320663 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ node_js: - "1.8" - "2.5" - "3.3" + - "4.2" 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 40ee0765374..242bb8b0cb5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,6 +5,7 @@ environment: - nodejs_version: "1.8" - nodejs_version: "2.5" - nodejs_version: "3.3" + - nodejs_version: "4.2" install: - ps: Install-Product node $env:nodejs_version - npm rm --save-dev connect-redis From 60f8e77d66563757a85e489fd2966d9bac3a84d8 Mon Sep 17 00:00:00 2001 From: ChALkeR Date: Fri, 13 Nov 2015 10:04:40 +0300 Subject: [PATCH 059/889] deps: cookie@0.1.5 closes #2799 closes #2800 closes #2801 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index be89c8e7230..1820824c069 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +unreleased +========== + + * deps: cookie@0.1.5 + - Throw on invalid values provided to `serialize` + 4.13.3 / 2015-08-02 =================== diff --git a/package.json b/package.json index 27c165bb6c6..90ea2e77790 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "array-flatten": "1.1.1", "content-disposition": "0.5.0", "content-type": "~1.0.1", - "cookie": "0.1.3", + "cookie": "0.1.5", "cookie-signature": "1.0.6", "debug": "~2.2.0", "depd": "~1.0.1", From 4416fb2746f01a76e4a4fc94100cdff1107130be Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Tue, 15 Dec 2015 10:19:19 -0800 Subject: [PATCH 060/889] docs: fix link to Security.md in Readme.md closes #2829 --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 0f3f40ff14e..9e2424ce915 100644 --- a/Readme.md +++ b/Readme.md @@ -48,7 +48,7 @@ $ npm install express ###Security Issues -If you discover a security vulnerability in Express, please see [Security Policies and Procedures](security.md). +If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). ## Quick Start From 2b2a1b28f3cf92a27a87f4f8569e9fa3489b783c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 17 Dec 2015 20:51:32 -0500 Subject: [PATCH 061/889] deps: escape-html@~1.0.3 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 1820824c069..63b6f72457d 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,10 @@ unreleased * deps: cookie@0.1.5 - Throw on invalid values provided to `serialize` + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion 4.13.3 / 2015-08-02 =================== diff --git a/package.json b/package.json index 90ea2e77790..3a3007bb53a 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.2", + "escape-html": "~1.0.3", "etag": "~1.7.0", "finalhandler": "0.4.0", "fresh": "0.3.0", From 7d9350391413aa6cbacaad93271316e2c758501c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 17 Dec 2015 20:56:04 -0500 Subject: [PATCH 062/889] deps: finalhandler@0.4.1 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 63b6f72457d..4b16fc8714e 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,8 @@ unreleased - perf: enable strict mode - perf: optimize string replacement - perf: use faster string coercion + * deps: finalhandler@0.4.1 + - deps: escape-html@~1.0.3 4.13.3 / 2015-08-02 =================== diff --git a/package.json b/package.json index 3a3007bb53a..8b4f6b93d61 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "depd": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.7.0", - "finalhandler": "0.4.0", + "finalhandler": "0.4.1", "fresh": "0.3.0", "merge-descriptors": "1.0.0", "methods": "~1.1.1", From c95a1077d21e2fd58e24b4435cb9c40dd4495376 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 17 Dec 2015 20:58:41 -0500 Subject: [PATCH 063/889] deps: proxy-addr@~1.0.10 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 4b16fc8714e..6398655b286 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,9 @@ unreleased - perf: use faster string coercion * deps: finalhandler@0.4.1 - deps: escape-html@~1.0.3 + * deps: proxy-addr@~1.0.10 + - deps: ipaddr.js@1.0.5 + - perf: enable strict mode 4.13.3 / 2015-08-02 =================== diff --git a/package.json b/package.json index 8b4f6b93d61..33ac81687be 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.0", "path-to-regexp": "0.1.7", - "proxy-addr": "~1.0.8", + "proxy-addr": "~1.0.10", "qs": "4.0.0", "range-parser": "~1.0.2", "send": "0.13.0", From 4f8167f23fddc80ecb12cff3a21c610e639fe738 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 17 Dec 2015 20:59:12 -0500 Subject: [PATCH 064/889] deps: range-parser@~1.0.3 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 6398655b286..28c4648bfa5 100644 --- a/History.md +++ b/History.md @@ -12,6 +12,8 @@ unreleased * deps: proxy-addr@~1.0.10 - deps: ipaddr.js@1.0.5 - perf: enable strict mode + * deps: range-parser@~1.0.3 + - perf: enable strict mode 4.13.3 / 2015-08-02 =================== diff --git a/package.json b/package.json index 33ac81687be..1d701344fc9 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "path-to-regexp": "0.1.7", "proxy-addr": "~1.0.10", "qs": "4.0.0", - "range-parser": "~1.0.2", + "range-parser": "~1.0.3", "send": "0.13.0", "serve-static": "~1.10.0", "type-is": "~1.6.6", From c73b1bee51f72fd11ca7afa497f2737399decd57 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 17 Dec 2015 21:02:22 -0500 Subject: [PATCH 065/889] build: istanbul@0.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d701344fc9..06e53ef9aa0 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "devDependencies": { "after": "0.8.1", "ejs": "2.3.4", - "istanbul": "0.4.0", + "istanbul": "0.4.1", "marked": "0.3.5", "mocha": "2.3.3", "should": "7.1.1", From 249323919211fbb83363da09adaaf7060a123534 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 18 Dec 2015 15:09:34 -0500 Subject: [PATCH 066/889] build: mocha@2.3.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 06e53ef9aa0..bc8c9733b9a 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "ejs": "2.3.4", "istanbul": "0.4.1", "marked": "0.3.5", - "mocha": "2.3.3", + "mocha": "2.3.4", "should": "7.1.1", "supertest": "1.1.0", "body-parser": "~1.13.3", From e44f024dab675fbfa493136aa6305f093d7d2055 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 18 Dec 2015 15:10:33 -0500 Subject: [PATCH 067/889] deps: update example dependencies --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index bc8c9733b9a..960a0578730 100644 --- a/package.json +++ b/package.json @@ -61,11 +61,11 @@ "mocha": "2.3.4", "should": "7.1.1", "supertest": "1.1.0", - "body-parser": "~1.13.3", + "body-parser": "~1.14.2", "connect-redis": "~2.4.1", - "cookie-parser": "~1.3.5", + "cookie-parser": "~1.4.1", "cookie-session": "~1.2.0", - "express-session": "~1.11.3", + "express-session": "~1.13.0", "jade": "~1.11.0", "method-override": "~2.3.5", "morgan": "~1.6.1", From f2cf28c2f3c0a3b5d5ab976a148a83f7e763ae18 Mon Sep 17 00:00:00 2001 From: Jordan Larson Date: Wed, 13 Jan 2016 15:32:08 -0600 Subject: [PATCH 068/889] docs: add link to Gitter --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 9e2424ce915..d2407279fa5 100644 --- a/Readme.md +++ b/Readme.md @@ -42,6 +42,7 @@ $ npm install express * [Github Organization](https://github.com/expressjs) for Official Middleware & Modules * Visit the [Wiki](https://github.com/strongloop/express/wiki) * [Google Group](https://groups.google.com/group/express-js) for discussion + * [Gitter](https://gitter.im/strongloop/express) for support and discussion * [Русскоязычная документация](http://jsman.ru/express/) **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/strongloop/express/wiki/New-features-in-4.x). From bd118c47dfdbc05a57cc10d4b791cdb91a203a7f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 16 Jan 2016 23:54:41 -0500 Subject: [PATCH 069/889] deps: serve-static@~1.10.1 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 28c4648bfa5..ca4f6556c0f 100644 --- a/History.md +++ b/History.md @@ -14,6 +14,9 @@ unreleased - perf: enable strict mode * deps: range-parser@~1.0.3 - perf: enable strict mode + * deps: serve-static@~1.10.1 + - deps: escape-html@~1.0.3 + - deps: send@0.13.1 4.13.3 / 2015-08-02 =================== diff --git a/package.json b/package.json index 960a0578730..eaf0fbd242b 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "qs": "4.0.0", "range-parser": "~1.0.3", "send": "0.13.0", - "serve-static": "~1.10.0", + "serve-static": "~1.10.1", "type-is": "~1.6.6", "utils-merge": "1.0.0", "vary": "~1.0.1" From 53ee474c442e268abae9bea5b49f68464bf61f4e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 16 Jan 2016 23:56:09 -0500 Subject: [PATCH 070/889] deps: send@0.13.1 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ca4f6556c0f..6f1904567b2 100644 --- a/History.md +++ b/History.md @@ -14,6 +14,11 @@ unreleased - perf: enable strict mode * deps: range-parser@~1.0.3 - perf: enable strict mode + * deps: send@0.13.1 + - deps: depd@~1.1.0 + - deps: destroy@~1.0.4 + - deps: escape-html@~1.0.3 + - deps: range-parser@~1.0.3 * deps: serve-static@~1.10.1 - deps: escape-html@~1.0.3 - deps: send@0.13.1 diff --git a/package.json b/package.json index eaf0fbd242b..1e9fc8a14d7 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "proxy-addr": "~1.0.10", "qs": "4.0.0", "range-parser": "~1.0.3", - "send": "0.13.0", + "send": "0.13.1", "serve-static": "~1.10.1", "type-is": "~1.6.6", "utils-merge": "1.0.0", From 7c8456fcde6006faceab1fca659b088c7a915207 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 16 Jan 2016 23:57:07 -0500 Subject: [PATCH 071/889] deps: depd@~1.1.0 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 6f1904567b2..1e93e7bdb47 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,9 @@ unreleased * deps: cookie@0.1.5 - Throw on invalid values provided to `serialize` + * deps: depd@~1.1.0 + - Support web browser loading + - perf: enable strict mode * deps: escape-html@~1.0.3 - perf: enable strict mode - perf: optimize string replacement diff --git a/package.json b/package.json index 1e9fc8a14d7..de8b09324a6 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "cookie": "0.1.5", "cookie-signature": "1.0.6", "debug": "~2.2.0", - "depd": "~1.0.1", + "depd": "~1.1.0", "escape-html": "~1.0.3", "etag": "~1.7.0", "finalhandler": "0.4.1", From 8eee818e0b697f85418d5eee9a86ab3a8e45105f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 16 Jan 2016 23:58:27 -0500 Subject: [PATCH 072/889] build: istanbul@0.4.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index de8b09324a6..2299579285b 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "devDependencies": { "after": "0.8.1", "ejs": "2.3.4", - "istanbul": "0.4.1", + "istanbul": "0.4.2", "marked": "0.3.5", "mocha": "2.3.4", "should": "7.1.1", From 547ea368c2e1b915ed3ff1d844978d754b11c0ee Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 17 Jan 2016 18:00:59 -0500 Subject: [PATCH 073/889] deps: content-disposition@0.5.1 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 1e93e7bdb47..f71dac4875b 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,8 @@ unreleased ========== + * deps: content-disposition@0.5.1 + - perf: enable strict mode * deps: cookie@0.1.5 - Throw on invalid values provided to `serialize` * deps: depd@~1.1.0 diff --git a/package.json b/package.json index 2299579285b..2f08acd9f37 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "dependencies": { "accepts": "~1.2.12", "array-flatten": "1.1.1", - "content-disposition": "0.5.0", + "content-disposition": "0.5.1", "content-type": "~1.0.1", "cookie": "0.1.5", "cookie-signature": "1.0.6", From 1589ce215348197f4c6a19effe7a07feff991c1d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 17 Jan 2016 18:51:24 -0500 Subject: [PATCH 074/889] deps: merge-descriptors@1.0.1 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index f71dac4875b..78fb70063a7 100644 --- a/History.md +++ b/History.md @@ -14,6 +14,8 @@ unreleased - perf: use faster string coercion * deps: finalhandler@0.4.1 - deps: escape-html@~1.0.3 + * deps: merge-descriptors@1.0.1 + - perf: enable strict mode * deps: proxy-addr@~1.0.10 - deps: ipaddr.js@1.0.5 - perf: enable strict mode diff --git a/package.json b/package.json index 2f08acd9f37..941c0a041a6 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "etag": "~1.7.0", "finalhandler": "0.4.1", "fresh": "0.3.0", - "merge-descriptors": "1.0.0", + "merge-descriptors": "1.0.1", "methods": "~1.1.1", "on-finished": "~2.3.0", "parseurl": "~1.3.0", From e83eab85e4c97a51088822c1bc4bb8a1faf06f88 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 17 Jan 2016 22:17:13 -0500 Subject: [PATCH 075/889] deps: methods@~1.1.2 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 78fb70063a7..5b7a1fbb87d 100644 --- a/History.md +++ b/History.md @@ -16,6 +16,8 @@ unreleased - deps: escape-html@~1.0.3 * deps: merge-descriptors@1.0.1 - perf: enable strict mode + * deps: methods@~1.1.2 + - perf: enable strict mode * deps: proxy-addr@~1.0.10 - deps: ipaddr.js@1.0.5 - perf: enable strict mode diff --git a/package.json b/package.json index 941c0a041a6..14c6143664d 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "finalhandler": "0.4.1", "fresh": "0.3.0", "merge-descriptors": "1.0.1", - "methods": "~1.1.1", + "methods": "~1.1.2", "on-finished": "~2.3.0", "parseurl": "~1.3.0", "path-to-regexp": "0.1.7", From f627ca8d0b434c8c0b8c66b82a453a49220d8a1f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 20 Jan 2016 00:56:56 -0500 Subject: [PATCH 076/889] deps: serve-static@~1.10.2 --- History.md | 3 ++- package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 5b7a1fbb87d..897ee5c2459 100644 --- a/History.md +++ b/History.md @@ -28,8 +28,9 @@ unreleased - deps: destroy@~1.0.4 - deps: escape-html@~1.0.3 - deps: range-parser@~1.0.3 - * deps: serve-static@~1.10.1 + * deps: serve-static@~1.10.2 - deps: escape-html@~1.0.3 + - deps: parseurl@~1.3.0 - deps: send@0.13.1 4.13.3 / 2015-08-02 diff --git a/package.json b/package.json index 14c6143664d..9081300a16d 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "qs": "4.0.0", "range-parser": "~1.0.3", "send": "0.13.1", - "serve-static": "~1.10.1", + "serve-static": "~1.10.2", "type-is": "~1.6.6", "utils-merge": "1.0.0", "vary": "~1.0.1" From 68474059742afae6bbcf60dafaccfa7a648e1de0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 20 Jan 2016 00:58:09 -0500 Subject: [PATCH 077/889] deps: parseurl@~1.3.1 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 897ee5c2459..45d426aaf6f 100644 --- a/History.md +++ b/History.md @@ -18,6 +18,8 @@ unreleased - perf: enable strict mode * deps: methods@~1.1.2 - perf: enable strict mode + * deps: parseurl@~1.3.1 + - perf: enable strict mode * deps: proxy-addr@~1.0.10 - deps: ipaddr.js@1.0.5 - perf: enable strict mode diff --git a/package.json b/package.json index 9081300a16d..1920a126e32 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", - "parseurl": "~1.3.0", + "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "~1.0.10", "qs": "4.0.0", From e7a02f6a256a06b670fec65bc1460bc858c9e60e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Jan 2016 20:59:53 -0500 Subject: [PATCH 078/889] build: move repository to expressjs --- Contributing.md | 6 +----- Readme.md | 18 +++++++----------- Security.md | 15 +++------------ examples/view-constructor/index.js | 4 ++-- examples/web-service/index.js | 2 +- package.json | 3 +-- test/acceptance/web-service.js | 2 +- 7 files changed, 16 insertions(+), 34 deletions(-) diff --git a/Contributing.md b/Contributing.md index 6dab84f125d..ce33ccd41c9 100644 --- a/Contributing.md +++ b/Contributing.md @@ -1,7 +1,4 @@ - -## Website Issues - -Issues for the expressjs.com website go here https://github.com/strongloop/expressjs.com +# Contributing ## PRs and Code contributions @@ -22,4 +19,3 @@ Things that will help get your question issue looked at: * Steps you have taken to debug it yourself. If you post a question and do not outline the above items or make it easy for us to understand and reproduce your issue, it will be closed. - diff --git a/Readme.md b/Readme.md index d2407279fa5..6e08454b263 100644 --- a/Readme.md +++ b/Readme.md @@ -37,16 +37,12 @@ $ npm install express ## Docs & Community - * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/strongloop/expressjs.com)] * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC * [Github Organization](https://github.com/expressjs) for Official Middleware & Modules - * Visit the [Wiki](https://github.com/strongloop/express/wiki) * [Google Group](https://groups.google.com/group/express-js) for discussion - * [Gitter](https://gitter.im/strongloop/express) for support and discussion + * [Gitter](https://gitter.im/expressjs/express) for support and discussion * [Русскоязычная документация](http://jsman.ru/express/) -**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/strongloop/express/wiki/New-features-in-4.x). - ###Security Issues If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). @@ -94,7 +90,7 @@ $ npm start To view the examples, clone the Express repo and install the dependencies: ```bash -$ git clone git://github.com/strongloop/express.git --depth 1 +$ git clone git://github.com/expressjs/express.git --depth 1 $ cd express $ npm install ``` @@ -120,7 +116,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) [![TJ' The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) [![Doug's Gratipay][gratipay-image-dougwilson]][gratipay-url-dougwilson] -[List of all contributors](https://github.com/strongloop/express/graphs/contributors) +[List of all contributors](https://github.com/expressjs/express/graphs/contributors) ## License @@ -130,12 +126,12 @@ The current lead maintainer is [Douglas Christopher Wilson](https://github.com/d [npm-url]: https://npmjs.org/package/express [downloads-image]: https://img.shields.io/npm/dm/express.svg [downloads-url]: https://npmjs.org/package/express -[travis-image]: https://img.shields.io/travis/strongloop/express/master.svg?label=linux -[travis-url]: https://travis-ci.org/strongloop/express +[travis-image]: https://img.shields.io/travis/expressjs/express/master.svg?label=linux +[travis-url]: https://travis-ci.org/expressjs/express [appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/express/master.svg?label=windows [appveyor-url]: https://ci.appveyor.com/project/dougwilson/express -[coveralls-image]: https://img.shields.io/coveralls/strongloop/express/master.svg -[coveralls-url]: https://coveralls.io/r/strongloop/express?branch=master +[coveralls-image]: https://img.shields.io/coveralls/expressjs/express/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master [gratipay-image-visionmedia]: https://img.shields.io/gratipay/visionmedia.svg [gratipay-url-visionmedia]: https://gratipay.com/visionmedia/ [gratipay-image-dougwilson]: https://img.shields.io/gratipay/dougwilson.svg diff --git a/Security.md b/Security.md index 0c6d82324f1..d965a87bb0a 100644 --- a/Security.md +++ b/Security.md @@ -15,10 +15,9 @@ Thank you for improving the security of Express. We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions. -Report security bugs by emailing security@expressjs.com. Email to this address -is delivered to a subset of the core team who handle security issues. +Report security bugs by emailing the lead maintainer in the Readme.md file. -The security team will acknowledge your email within 24 hours, and will send a +The lead maintainer will acknowledge your email within 48 hours, and will send a more detailed response within 48 hours indicating the next steps in handling your report. After the initial reply to your report, the security team will endeavor to keep you informed of the progress towards a fix and full @@ -39,15 +38,7 @@ involving the following steps: * Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible to npm. -## Receiving Security Updates - -Security notifications will be distributed via the following methods. - - * https://groups.google.com/forum/#!forum/express-js - * http://blog.strongloop.com - * http://expressjs.com/advanced/security-updates.html - ## Comments on this Policy If you have suggestions on how this process could be improved please submit a -pull request or email security@expressjs.com to discuss. +pull request. diff --git a/examples/view-constructor/index.js b/examples/view-constructor/index.js index 173663f8095..195d32db0eb 100644 --- a/examples/view-constructor/index.js +++ b/examples/view-constructor/index.js @@ -23,7 +23,7 @@ app.engine('md', function(str, options, fn){ }); // pointing to a particular github repo to load files from it -app.set('views', 'strongloop/express'); +app.set('views', 'expressjs/express'); // register a new view constructor app.set('view', GithubView); @@ -36,7 +36,7 @@ app.get('/', function(req, res){ }); app.get('/Readme.md', function(req, res){ - // rendering a view from https://github.com/strongloop/express/blob/master/Readme.md + // rendering a view from https://github.com/expressjs/express/blob/master/Readme.md res.render('Readme.md'); }); diff --git a/examples/web-service/index.js b/examples/web-service/index.js index 4958c22450c..694e121d91b 100644 --- a/examples/web-service/index.js +++ b/examples/web-service/index.js @@ -49,7 +49,7 @@ var apiKeys = ['foo', 'bar', 'baz']; // these two objects will serve as our faux database var repos = [ - { name: 'express', url: 'http://github.com/strongloop/express' } + { name: 'express', url: 'http://github.com/expressjs/express' } , { name: 'stylus', url: 'http://github.com/learnboost/stylus' } , { name: 'cluster', url: 'http://github.com/learnboost/cluster' } ]; diff --git a/package.json b/package.json index 1920a126e32..798f43c935c 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "Young Jae Sim " ], "license": "MIT", - "repository": "strongloop/express", - "homepage": "http://expressjs.com/", + "repository": "expressjs/express", "keywords": [ "express", "framework", diff --git a/test/acceptance/web-service.js b/test/acceptance/web-service.js index 5868e92df95..521fa9fa28d 100644 --- a/test/acceptance/web-service.js +++ b/test/acceptance/web-service.js @@ -53,7 +53,7 @@ describe('web-service', function(){ .get('/api/repos?api-key=foo') .expect('Content-Type', 'application/json; charset=utf-8') .expect(/"name":"express"/) - .expect(/"url":"http:\/\/github.com\/strongloop\/express"/) + .expect(/"url":"http:\/\/github.com\/expressjs\/express"/) .expect(200, done) }) }) From 193bed2649c55c1fd362e46cd4702c773f3e7434 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Jan 2016 21:10:45 -0500 Subject: [PATCH 079/889] 4.13.4 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 45d426aaf6f..c72241b98d5 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.13.4 / 2016-01-21 +=================== * deps: content-disposition@0.5.1 - perf: enable strict mode diff --git a/package.json b/package.json index 798f43c935c..3165cc44d3d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.13.3", + "version": "4.13.4", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 943f28f05f11f789e4156bf7dcb37f548c96b6aa Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Jan 2016 21:26:03 -0500 Subject: [PATCH 080/889] deps: router@~1.1.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8c89a1dce4..5eaafe28786 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "proxy-addr": "~1.0.10", "qs": "4.0.0", "range-parser": "~1.0.3", - "router": "~1.1.2", + "router": "~1.1.3", "send": "0.13.1", "serve-static": "~1.10.2", "type-is": "~1.6.6", From 8a387d3ede7bd0e040c7b19def0007040b25d5f9 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Jan 2016 21:28:24 -0500 Subject: [PATCH 081/889] deps: array-flatten@2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5eaafe28786..856b054b1ef 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ ], "dependencies": { "accepts": "~1.2.12", - "array-flatten": "1.1.1", + "array-flatten": "2.0.0", "content-disposition": "0.5.1", "content-type": "~1.0.1", "cookie": "0.1.5", From 05136550c7fa9d7671a03960cc86a717f0964d21 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 10 Feb 2016 18:21:46 -0500 Subject: [PATCH 082/889] docs: fix some links messed up from repository move commit closes #2861 closes #2867 --- Contributing.md | 5 ++++- Readme.md | 4 ++++ package.json | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index ce33ccd41c9..45bc153823f 100644 --- a/Contributing.md +++ b/Contributing.md @@ -1,4 +1,7 @@ -# Contributing + +## Website Issues + +Issues for the expressjs.com website go here https://github.com/strongloop/expressjs.com ## PRs and Code contributions diff --git a/Readme.md b/Readme.md index 6e08454b263..e9bfaeba20d 100644 --- a/Readme.md +++ b/Readme.md @@ -37,12 +37,16 @@ $ npm install express ## Docs & Community + * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/strongloop/expressjs.com)] * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC * [Github Organization](https://github.com/expressjs) for Official Middleware & Modules + * Visit the [Wiki](https://github.com/expressjs/express/wiki) * [Google Group](https://groups.google.com/group/express-js) for discussion * [Gitter](https://gitter.im/expressjs/express) for support and discussion * [Русскоязычная документация](http://jsman.ru/express/) +**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x). + ###Security Issues If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). diff --git a/package.json b/package.json index 3165cc44d3d..0b0e791d1f5 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ ], "license": "MIT", "repository": "expressjs/express", + "homepage": "http://expressjs.com/", "keywords": [ "express", "framework", From b5a280111f94728e70aa1a22687e64aaf31abd81 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Tue, 9 Feb 2016 14:25:32 -0800 Subject: [PATCH 083/889] Fix jsdoc comment for res.get closes #2882 --- lib/response.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/response.js b/lib/response.js index 641704b04ae..e813c52ec1e 100644 --- a/lib/response.js +++ b/lib/response.js @@ -740,7 +740,7 @@ res.get = function(field){ * Clear cookie `name`. * * @param {String} name - * @param {Object} options + * @param {Object} [options] * @return {ServerResponse} for chaining * @public */ From 4bcbf67482471ac096fb39bf076ba5d40c0fe4da Mon Sep 17 00:00:00 2001 From: Sian January Date: Mon, 8 Feb 2016 13:52:23 +0000 Subject: [PATCH 084/889] docs: add branch & fork steps to contributing documentation closes #2881 --- Contributing.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Contributing.md b/Contributing.md index 45bc153823f..84c5b9ccef6 100644 --- a/Contributing.md +++ b/Contributing.md @@ -9,6 +9,18 @@ Issues for the expressjs.com website go here https://github.com/strongloop/expre * Follow existing coding style. * If you fix a bug, add a test. +## Branches + +* Use the `master` branch for bug fixes or minor work that is intended for the current release stream +* Use the correspondingly named branch, e.g. `5.0`, for anything intended for a future release of Express + +## Steps for contributing + +* [Create an issue](https://github.com/strongloop/express/issues/new) for the bug you want to fix or the feature that you want to add. +* Create your own [fork](https://github.com/strongloop/express) on github, then checkout your fork. +* Write your code in your local copy. It's good practice to create a branch for each new issue you work on, although not compulsory. +* To run the test suite, first install the dependencies by running `npm install`, then run `npm test`. +* If the tests pass, you can commit your changes to your fork and then create a pull request from there. Make sure to reference your issue from the pull request comments by including the issue number e.g. #123. ## Issues which are questions From dd2b8977747203343b37318a34b221d481e789e8 Mon Sep 17 00:00:00 2001 From: Muhammad Saqib Date: Thu, 25 Feb 2016 07:46:14 +0500 Subject: [PATCH 085/889] examples: comment the usage of process.nextTick closes #2903 closes #2908 --- examples/error/index.js | 3 +++ examples/view-locals/user.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/examples/error/index.js b/examples/error/index.js index d7db5015a13..94b3b4a4da3 100644 --- a/examples/error/index.js +++ b/examples/error/index.js @@ -31,6 +31,9 @@ app.get('/', function(req, res){ app.get('/next', function(req, res, next){ // We can also pass exceptions to next() + // The reason for process.nextTick() is to show that + // next() can be called inside an async operation, + // in real life it can be a DB read or HTTP request. process.nextTick(function(){ next(new Error('oh no!')); }); diff --git a/examples/view-locals/user.js b/examples/view-locals/user.js index 0e3373d548c..90ab1f389df 100644 --- a/examples/view-locals/user.js +++ b/examples/view-locals/user.js @@ -9,6 +9,9 @@ function User(name, age, species) { } User.all = function(fn){ + // process.nextTick makes sure this function API + // behaves in an asynchronous manner, like if it + // was a real DB query to read all users. process.nextTick(function(){ fn(null, users); }); From f3d99a4fdbe1531ea609e92c4d4ae6c269d78c7a Mon Sep 17 00:00:00 2001 From: Mikeal Rogers Date: Mon, 29 Feb 2016 11:26:14 -0800 Subject: [PATCH 086/889] docs: add base contributing guide closes #2918 --- Collaborator-Guide.md | 36 +++++++++++++++ Contributing.md | 102 ++++++++++++++++++++++++++++++++---------- 2 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 Collaborator-Guide.md diff --git a/Collaborator-Guide.md b/Collaborator-Guide.md new file mode 100644 index 00000000000..84c5b9ccef6 --- /dev/null +++ b/Collaborator-Guide.md @@ -0,0 +1,36 @@ + +## Website Issues + +Issues for the expressjs.com website go here https://github.com/strongloop/expressjs.com + +## PRs and Code contributions + +* Tests must pass. +* Follow existing coding style. +* If you fix a bug, add a test. + +## Branches + +* Use the `master` branch for bug fixes or minor work that is intended for the current release stream +* Use the correspondingly named branch, e.g. `5.0`, for anything intended for a future release of Express + +## Steps for contributing + +* [Create an issue](https://github.com/strongloop/express/issues/new) for the bug you want to fix or the feature that you want to add. +* Create your own [fork](https://github.com/strongloop/express) on github, then checkout your fork. +* Write your code in your local copy. It's good practice to create a branch for each new issue you work on, although not compulsory. +* To run the test suite, first install the dependencies by running `npm install`, then run `npm test`. +* If the tests pass, you can commit your changes to your fork and then create a pull request from there. Make sure to reference your issue from the pull request comments by including the issue number e.g. #123. + +## Issues which are questions + +We will typically close any vague issues or questions that are specific to some app you are writing. Please double check the docs and other references before being trigger happy with posting a question issue. + +Things that will help get your question issue looked at: + +* Full and runnable JS code. +* Clear description of the problem or unexpected behavior. +* Clear description of the expected result. +* Steps you have taken to debug it yourself. + +If you post a question and do not outline the above items or make it easy for us to understand and reproduce your issue, it will be closed. diff --git a/Contributing.md b/Contributing.md index 84c5b9ccef6..3fb2b7c25f1 100644 --- a/Contributing.md +++ b/Contributing.md @@ -1,36 +1,92 @@ +# Node.js Community Contributing Guide 1.0 -## Website Issues +This document describes a very simple process suitable for most projects +in the Node.js ecosystem. Projects are encouraged to adopt this whether they +are hosted in the Node.js Foundation or not. -Issues for the expressjs.com website go here https://github.com/strongloop/expressjs.com +The goal of this document is to create a contribution process that: -## PRs and Code contributions +* Encourages new contributions. +* Encourages contributors to remain involved. +* Avoids unnecessary processes and bureaucracy whenever possible. +* Creates a transparent decision making process which makes it clear how +contributors can be involved in decision making. -* Tests must pass. -* Follow existing coding style. -* If you fix a bug, add a test. +This document is based on much prior art in the Node.js community, io.js, +and the Node.js project. -## Branches +## Vocabulary -* Use the `master` branch for bug fixes or minor work that is intended for the current release stream -* Use the correspondingly named branch, e.g. `5.0`, for anything intended for a future release of Express +* A **Contributor** is any individual creating or commenting on an issue or pull request. +* A **Committer** is a subset of contributors who have been given write access to the repository. +* A **TC (Technical Committee)** is a group of committers representing the required technical +expertise to resolve rare disputes. -## Steps for contributing +# Logging Issues -* [Create an issue](https://github.com/strongloop/express/issues/new) for the bug you want to fix or the feature that you want to add. -* Create your own [fork](https://github.com/strongloop/express) on github, then checkout your fork. -* Write your code in your local copy. It's good practice to create a branch for each new issue you work on, although not compulsory. -* To run the test suite, first install the dependencies by running `npm install`, then run `npm test`. -* If the tests pass, you can commit your changes to your fork and then create a pull request from there. Make sure to reference your issue from the pull request comments by including the issue number e.g. #123. +Log an issue for any question or problem you might have. When in doubt, log an issue, +any additional policies about what to include will be provided in the responses. The only +exception is security dislosures which should be sent privately. -## Issues which are questions +Committers may direct you to another repository, ask for additional clarifications, and +add appropriate metadata before the issue is addressed. -We will typically close any vague issues or questions that are specific to some app you are writing. Please double check the docs and other references before being trigger happy with posting a question issue. +Please be courteous, respectful, and every participant is expected to follow the +project's Code of Conduct. -Things that will help get your question issue looked at: +# Contributions + +Any change to resources in this repository must be through pull requests. This applies to all changes +to documentation, code, binary files, etc. Even long term committers and TC members must use +pull requests. + +No pull request can be merged without being reviewed. + +For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that +contributors in other timezones have time to review. Consideration should also be given to +weekends and other holiday periods to ensure active committers all have reasonable time to +become involved in the discussion and review process if they wish. + +The default for each contribution is that it is accepted once no committer has an objection. +During review committers may also request that a specific contributor who is most versed in a +particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off" +process for contributions to land. Once all issues brought by committers are addressed it can +be landed by any committer. + +In the case of an objection being raised in a pull request by another committer, all involved +committers should seek to arrive at a consensus by way of addressing concerns being expressed +by discussion, compromise on the proposed change, or withdrawal of the proposed change. + +If a contribution is controversial and committers cannot agree about how to get it to land +or if it should land then it should be escalated to the TC. TC members should regularly +discuss pending contributions in order to find a resolution. It is expected that only a +small minority of issues be brought to the TC for resolution and that discussion and +compromise among committers be the default resolution mechanism. + +# Becoming a Committer + +All contributors who land a non-trivial contribution should be on-boarded in a timely manner, +and added as a committer, and be given write access to the repository. + +Committers are expected to follow this policy and continue to send pull requests, go through +proper review, and have other committers merge their pull requests. + +# TC Process + +The TC uses a "consensus seeking" process for issues that are escalated to the TC. +The group tries to find a resolution that has no open objections among TC members. +If a consensus cannot be reached that has no objections then a majority wins vote +is called. It is also expected that the majority of decisions made by the TC are via +a consensus seeking process and that voting is only used as a last-resort. + +Resolution may involve returning the issue to committers with suggestions on how to +move forward towards a consensus. It is not expected that a meeting of the TC +will resolve all issues on its agenda during that meeting and may prefer to continue +the discussion happening among the committers. + +Members can be added to the TC at any time. Any committer can nominate another committer +to the TC and the TC uses its standard consensus seeking process to evaluate whether or +not to add this new member. Members who do not participate consistently at the level of +a majority of the other members are expected to resign. -* Full and runnable JS code. -* Clear description of the problem or unexpected behavior. -* Clear description of the expected result. -* Steps you have taken to debug it yourself. -If you post a question and do not outline the above items or make it easy for us to understand and reproduce your issue, it will be closed. From bb84cf955f5f84edc8938c00ec8590599861abca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 5 May 2016 10:34:40 +0200 Subject: [PATCH 087/889] tests: add test for signed cookie without secret closes #2986 --- test/res.cookie.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/res.cookie.js b/test/res.cookie.js index 8de6c0c6e37..543af99dcdd 100644 --- a/test/res.cookie.js +++ b/test/res.cookie.js @@ -150,6 +150,22 @@ describe('res', function(){ }) }) + describe('signed without secret', function(){ + it('should throw an error', function(done){ + var app = express(); + + app.use(cookieParser()); + + app.use(function(req, res){ + res.cookie('name', 'tobi', { signed: true }).end(); + }); + + request(app) + .get('/') + .expect(500, /secret\S+ required for signed cookies/, done); + }) + }) + describe('.signedCookie(name, string)', function(){ it('should set a signed cookie', function(done){ var app = express(); From 8931b2311a096515a59398702c8898d88d21515c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 10 May 2016 12:42:16 -0400 Subject: [PATCH 088/889] build: Node.js@4.4 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 90852320663..53b5041a6b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ node_js: - "1.8" - "2.5" - "3.3" - - "4.2" + - "4.4" 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 242bb8b0cb5..4484e8224c1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ environment: - nodejs_version: "1.8" - nodejs_version: "2.5" - nodejs_version: "3.3" - - nodejs_version: "4.2" + - nodejs_version: "4.4" install: - ps: Install-Product node $env:nodejs_version - npm rm --save-dev connect-redis From 12bc16e72fe34ce7e3658679b694e47dce56ae7a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 10 May 2016 12:34:26 -0400 Subject: [PATCH 089/889] tests: use supertest to check response header values closes #2983 closes #2992 --- test/acceptance/cookies.js | 19 +++++------- test/acceptance/downloads.js | 7 ++--- test/middleware.basic.js | 9 ++---- test/res.jsonp.js | 8 ++--- test/res.location.js | 6 ++-- test/res.redirect.js | 29 ++++++------------ test/res.send.js | 59 +++++++++++------------------------- test/res.sendFile.js | 36 +++++++--------------- test/res.vary.js | 11 ++----- test/support/utils.js | 24 +++++++++++++++ 10 files changed, 81 insertions(+), 127 deletions(-) create mode 100644 test/support/utils.js diff --git a/test/acceptance/cookies.js b/test/acceptance/cookies.js index 86add660c73..aa9e1faef44 100644 --- a/test/acceptance/cookies.js +++ b/test/acceptance/cookies.js @@ -1,6 +1,7 @@ var app = require('../../examples/cookies') , request = require('supertest'); +var utils = require('../support/utils'); describe('cookies', function(){ describe('GET /', function(){ @@ -13,10 +14,8 @@ describe('cookies', function(){ it('should respond with no cookies', function(done){ request(app) .get('/') - .end(function(err, res){ - res.headers.should.not.have.property('set-cookie') - done() - }) + .expect(utils.shouldNotHaveHeader('Set-Cookie')) + .expect(200, done) }) it('should respond to cookie', function(done){ @@ -57,20 +56,16 @@ describe('cookies', function(){ .post('/') .type('urlencoded') .send({ remember: 1 }) - .expect(302, function(err, res){ - res.headers.should.have.property('set-cookie') - done() - }) + .expect('Set-Cookie', /remember=1/) + .expect(302, done) }) it('should no set cookie w/o reminder', function(done){ request(app) .post('/') .send({}) - .expect(302, function(err, res){ - res.headers.should.not.have.property('set-cookie') - done() - }) + .expect(utils.shouldNotHaveHeader('Set-Cookie')) + .expect(302, done) }) }) }) diff --git a/test/acceptance/downloads.js b/test/acceptance/downloads.js index ed9a02f9ced..a0aa7b75d9f 100644 --- a/test/acceptance/downloads.js +++ b/test/acceptance/downloads.js @@ -15,11 +15,8 @@ describe('downloads', function(){ it('should have a download header', function(done){ request(app) .get('/files/amazing.txt') - .end(function(err, res){ - res.status.should.equal(200); - res.headers.should.have.property('content-disposition', 'attachment; filename="amazing.txt"') - done() - }) + .expect('Content-Disposition', 'attachment; filename="amazing.txt"') + .expect(200, done) }) }) diff --git a/test/middleware.basic.js b/test/middleware.basic.js index 3e1f1813848..28a4dd18f2e 100644 --- a/test/middleware.basic.js +++ b/test/middleware.basic.js @@ -32,13 +32,8 @@ describe('middleware', function(){ .get('/') .set('Content-Type', 'application/json') .send('{"foo":"bar"}') - .end(function(err, res){ - if (err) return done(err); - res.headers.should.have.property('content-type', 'application/json'); - res.statusCode.should.equal(200); - res.text.should.equal('{"foo":"bar"}'); - done(); - }) + .expect('Content-Type', 'application/json') + .expect(200, '{"foo":"bar"}', done) }) }) }) diff --git a/test/res.jsonp.js b/test/res.jsonp.js index 4892a56ef6f..64b41fb9a6b 100644 --- a/test/res.jsonp.js +++ b/test/res.jsonp.js @@ -2,6 +2,7 @@ var express = require('../') , request = require('supertest') , assert = require('assert'); +var utils = require('./support/utils'); describe('res', function(){ describe('.jsonp(object)', function(){ @@ -136,11 +137,8 @@ describe('res', function(){ request(app) .get('/') .expect('Content-Type', 'application/vnd.example+json; charset=utf-8') - .expect(200, '{"hello":"world"}', function (err, res) { - if (err) return done(err); - res.headers.should.not.have.property('x-content-type-options'); - done(); - }); + .expect(utils.shouldNotHaveHeader('X-Content-Type-Options')) + .expect(200, '{"hello":"world"}', done); }) it('should override previous Content-Types with callback', function(done){ diff --git a/test/res.location.js b/test/res.location.js index 6481160174a..2b42bf358d4 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -13,10 +13,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.headers.should.have.property('location', 'http://google.com/'); - done(); - }) + .expect('Location', 'http://google.com/') + .expect(200, done) }) }) }) diff --git a/test/res.redirect.js b/test/res.redirect.js index 7ebc1ef01dc..8511c40f2ab 100644 --- a/test/res.redirect.js +++ b/test/res.redirect.js @@ -2,6 +2,7 @@ var http = require('http'); var express = require('..'); var request = require('supertest'); +var utils = require('./support/utils'); describe('res', function(){ describe('.redirect(url)', function(){ @@ -29,11 +30,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.statusCode.should.equal(303); - res.headers.should.have.property('location', 'http://google.com/'); - done(); - }) + .expect('Location', 'http://google.com/') + .expect(303, done) }) }) @@ -47,11 +45,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.statusCode.should.equal(303); - res.headers.should.have.property('location', 'http://google.com/'); - done(); - }) + .expect('Location', 'http://google.com/') + .expect(303, done) }) }) @@ -65,11 +60,8 @@ describe('res', function(){ request(app) .head('/') - .end(function(err, res){ - res.headers.should.have.property('location', 'http://google.com/'); - res.text.should.equal(''); - done(); - }) + .expect('Location', 'http://google.com/') + .expect(302, '', done) }) }) @@ -182,11 +174,8 @@ describe('res', function(){ .set('Accept', 'application/octet-stream') .expect('location', 'http://google.com/') .expect('content-length', '0') - .expect(302, '', function(err, res){ - if (err) return done(err) - res.headers.should.not.have.property('content-type'); - done(); - }) + .expect(utils.shouldNotHaveHeader('Content-Type')) + .expect(302, '', done) }) }) }) diff --git a/test/res.send.js b/test/res.send.js index 6eafb944966..719424657c4 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -3,6 +3,7 @@ var assert = require('assert'); var express = require('..'); var methods = require('methods'); var request = require('supertest'); +var utils = require('./support/utils'); describe('res', function(){ describe('.send()', function(){ @@ -118,12 +119,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.headers.should.have.property('content-type', 'text/html; charset=utf-8'); - res.text.should.equal('

hey

'); - res.statusCode.should.equal(200); - done(); - }) + .expect('Content-Type', 'text/html; charset=utf-8') + .expect(200, '

hey

', done); }) it('should set ETag', function (done) { @@ -190,12 +187,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.headers.should.have.property('content-type', 'application/octet-stream'); - res.text.should.equal('hello'); - res.statusCode.should.equal(200); - done(); - }) + .expect('Content-Type', 'application/octet-stream') + .expect(200, 'hello', done); }) it('should set ETag', function (done) { @@ -221,12 +214,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.headers.should.have.property('content-type', 'text/plain; charset=utf-8'); - res.text.should.equal('hey'); - res.statusCode.should.equal(200); - done(); - }) + .expect('Content-Type', 'text/plain; charset=utf-8') + .expect(200, 'hey', done); }) }) @@ -269,13 +258,10 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.headers.should.not.have.property('content-type'); - res.headers.should.not.have.property('content-length'); - res.headers.should.not.have.property('transfer-encoding'); - res.text.should.equal(''); - done(); - }) + .expect(utils.shouldNotHaveHeader('Content-Type')) + .expect(utils.shouldNotHaveHeader('Content-Length')) + .expect(utils.shouldNotHaveHeader('Transfer-Encoding')) + .expect(204, '', done); }) }) @@ -289,13 +275,10 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.headers.should.not.have.property('content-type'); - res.headers.should.not.have.property('content-length'); - res.headers.should.not.have.property('transfer-encoding'); - res.text.should.equal(''); - done(); - }) + .expect(utils.shouldNotHaveHeader('Content-Type')) + .expect(utils.shouldNotHaveHeader('Content-Length')) + .expect(utils.shouldNotHaveHeader('Transfer-Encoding')) + .expect(304, '', done); }) }) @@ -451,7 +434,7 @@ describe('res', function(){ request(app) .get('/') - .expect(shouldNotHaveHeader('ETag')) + .expect(utils.shouldNotHaveHeader('ETag')) .expect(200, done); }) }); @@ -469,7 +452,7 @@ describe('res', function(){ request(app) .get('/') - .expect(shouldNotHaveHeader('ETag')) + .expect(utils.shouldNotHaveHeader('ETag')) .expect(200, done); }); @@ -559,15 +542,9 @@ describe('res', function(){ request(app) .get('/') - .expect(shouldNotHaveHeader('ETag')) + .expect(utils.shouldNotHaveHeader('ETag')) .expect(200, done); }) }) }) }) - -function shouldNotHaveHeader(header) { - return function (res) { - assert.ok(!(header.toLowerCase() in res.headers), 'should not have header ' + header) - } -} diff --git a/test/res.sendFile.js b/test/res.sendFile.js index f4868b39766..78013a50ebd 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -7,6 +7,7 @@ var onFinished = require('on-finished'); var path = require('path'); var should = require('should'); var fixtures = path.join(__dirname, 'fixtures'); +var utils = require('./support/utils'); describe('res', function(){ describe('.sendFile(path)', function () { @@ -154,11 +155,8 @@ describe('res', function(){ request(app) .get('/') - .expect(404, function (err, res) { - if (err) return done(err); - res.headers.should.not.have.property('x-success'); - done(); - }); + .expect(utils.shouldNotHaveHeader('X-Success')) + .expect(404, done); }); }); @@ -509,11 +507,8 @@ describe('res', function(){ request(app) .get('/') - .expect(404, function (err, res) { - if (err) return done(err); - res.headers.should.not.have.property('x-success'); - done(); - }); + .expect(utils.shouldNotHaveHeader('X-Success')) + .expect(404, done); }) it('should transfer a file', function (done) { @@ -595,11 +590,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.text.should.equal('

{{user.name}}

'); - res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); - done(); - }); + .expect('Content-Type', 'text/html; charset=UTF-8') + .expect(200, '

{{user.name}}

', done); }) }) @@ -613,11 +605,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.text.should.equal('

{{user.name}}

'); - res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); - done(); - }); + .expect('Content-Type', 'text/html; charset=UTF-8') + .expect(200, '

{{user.name}}

', done); }) it('should serve relative to "root"', function(done){ @@ -629,11 +618,8 @@ describe('res', function(){ request(app) .get('/') - .end(function(err, res){ - res.text.should.equal('

{{user.name}}

'); - res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); - done(); - }); + .expect('Content-Type', 'text/html; charset=UTF-8') + .expect(200, '

{{user.name}}

', done); }) it('should consider ../ malicious when "root" is not set', function(done){ diff --git a/test/res.vary.js b/test/res.vary.js index 13c3af2bb70..9a2edd24c09 100644 --- a/test/res.vary.js +++ b/test/res.vary.js @@ -2,6 +2,7 @@ var assert = require('assert'); var express = require('..'); var request = require('supertest'); +var utils = require('./support/utils'); describe('res.vary()', function(){ describe('with no arguments', function(){ @@ -15,7 +16,7 @@ describe('res.vary()', function(){ request(app) .get('/') - .expect(shouldNotHaveHeader('Vary')) + .expect(utils.shouldNotHaveHeader('Vary')) .expect(200, done); }) }) @@ -31,7 +32,7 @@ describe('res.vary()', function(){ request(app) .get('/') - .expect(shouldNotHaveHeader('Vary')) + .expect(utils.shouldNotHaveHeader('Vary')) .expect(200, done); }) }) @@ -88,9 +89,3 @@ describe('res.vary()', function(){ }) }) }) - -function shouldNotHaveHeader(header) { - return function (res) { - assert.ok(!(header.toLowerCase() in res.headers), 'should not have header ' + header); - }; -} diff --git a/test/support/utils.js b/test/support/utils.js new file mode 100644 index 00000000000..ec6b801bc09 --- /dev/null +++ b/test/support/utils.js @@ -0,0 +1,24 @@ + +/** + * Module dependencies. + * @private + */ +var assert = require('assert'); + +/** + * Module exports. + * @public + */ +exports.shouldNotHaveHeader = shouldNotHaveHeader; + +/** + * Assert that a supertest response does not have a header. + * + * @param {string} header Header name to check + * @returns {function} + */ +function shouldNotHaveHeader(header) { + return function (res) { + assert.ok(!(header.toLowerCase() in res.headers), 'should not have header ' + header); + }; +} From 3d56e7374d7d1e812c7851eacb7593bd41963a23 Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Thu, 12 May 2016 14:18:43 -0700 Subject: [PATCH 090/889] docs: update location of expressjs.com repo closes #2995 --- Collaborator-Guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Collaborator-Guide.md b/Collaborator-Guide.md index 84c5b9ccef6..abbfc109429 100644 --- a/Collaborator-Guide.md +++ b/Collaborator-Guide.md @@ -1,7 +1,7 @@ ## Website Issues -Issues for the expressjs.com website go here https://github.com/strongloop/expressjs.com +Open issues for the expressjs.com website in https://github.com/expressjs/expressjs.com. ## PRs and Code contributions @@ -16,8 +16,8 @@ Issues for the expressjs.com website go here https://github.com/strongloop/expre ## Steps for contributing -* [Create an issue](https://github.com/strongloop/express/issues/new) for the bug you want to fix or the feature that you want to add. -* Create your own [fork](https://github.com/strongloop/express) on github, then checkout your fork. +* [Create an issue](https://github.com/expressjs/express/issues/new) for the bug you want to fix or the feature that you want to add. +* Create your own [fork](https://github.com/expressjs/express) on github, then checkout your fork. * Write your code in your local copy. It's good practice to create a branch for each new issue you work on, although not compulsory. * To run the test suite, first install the dependencies by running `npm install`, then run `npm test`. * If the tests pass, you can commit your changes to your fork and then create a pull request from there. Make sure to reference your issue from the pull request comments by including the issue number e.g. #123. From 741a5aac9cf287ce4072e3e458c2bbaab0bca355 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 22:12:31 -0400 Subject: [PATCH 091/889] build: cache node_modules on CI --- .travis.yml | 11 ++++++++++- appveyor.yml | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 53b5041a6b4..38998527547 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,15 @@ node_js: - "3.3" - "4.4" sudo: false -before_install: "npm rm --save-dev connect-redis" +cache: + directories: + - node_modules +before_install: + # Remove all non-test dependencies + - "npm rm --save-dev connect-redis" + + # Update Node.js modules + - "test ! -d node_modules || npm prune" + - "test ! -d node_modules || npm rebuild" script: "npm run-script test-ci" after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls" diff --git a/appveyor.yml b/appveyor.yml index 4484e8224c1..ce5e52ff1b9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,9 +6,13 @@ environment: - nodejs_version: "2.5" - nodejs_version: "3.3" - nodejs_version: "4.4" +cache: + - node_modules install: - ps: Install-Product node $env:nodejs_version - npm rm --save-dev connect-redis + - if exist node_modules npm prune + - if exist node_modules npm rebuild - npm install build: off test_script: From 20a25489de13f3726d68c606411861a73acfa6b5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 22:39:59 -0400 Subject: [PATCH 092/889] build: ejs@2.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0b0e791d1f5..5f90cc4e9f8 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ }, "devDependencies": { "after": "0.8.1", - "ejs": "2.3.4", + "ejs": "2.4.1", "istanbul": "0.4.2", "marked": "0.3.5", "mocha": "2.3.4", From 992cd085fb4af69ec838d42b3f51d44c9d852968 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 22:41:26 -0400 Subject: [PATCH 093/889] build: istanbul@0.4.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f90cc4e9f8..6f950674682 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "devDependencies": { "after": "0.8.1", "ejs": "2.4.1", - "istanbul": "0.4.2", + "istanbul": "0.4.3", "marked": "0.3.5", "mocha": "2.3.4", "should": "7.1.1", From d7ae24228dbce8d8e384aa9f9e054fc24d4309eb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 22:44:48 -0400 Subject: [PATCH 094/889] build: mocha@2.5.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f950674682..c9ddea9d261 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "ejs": "2.4.1", "istanbul": "0.4.3", "marked": "0.3.5", - "mocha": "2.3.4", + "mocha": "2.5.1", "should": "7.1.1", "supertest": "1.1.0", "body-parser": "~1.14.2", From fd48bfe8fe0f8d0cfd3c58475bb89deabb9edb36 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 22:47:25 -0400 Subject: [PATCH 095/889] build: should@8.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c9ddea9d261..404a3dea739 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "istanbul": "0.4.3", "marked": "0.3.5", "mocha": "2.5.1", - "should": "7.1.1", + "should": "8.4.0", "supertest": "1.1.0", "body-parser": "~1.14.2", "connect-redis": "~2.4.1", From e3dd191d54a0a4adfb906af4b12e5fdc4627a2d3 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 23:00:43 -0400 Subject: [PATCH 096/889] examples: escape HTML in markdown example --- examples/markdown/index.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/examples/markdown/index.js b/examples/markdown/index.js index db2f16fb482..430628701fd 100644 --- a/examples/markdown/index.js +++ b/examples/markdown/index.js @@ -2,9 +2,10 @@ * Module dependencies. */ +var escapeHtml = require('escape-html'); var express = require('../..'); var fs = require('fs'); -var md = require('marked').parse; +var marked = require('marked'); var app = module.exports = express(); @@ -13,15 +14,10 @@ var app = module.exports = express(); app.engine('md', function(path, options, fn){ fs.readFile(path, 'utf8', function(err, str){ if (err) return fn(err); - try { - var html = md(str); - html = html.replace(/\{([^}]+)\}/g, function(_, name){ - return options[name] || ''; - }); - fn(null, html); - } catch(err) { - fn(err); - } + var html = marked.parse(str).replace(/\{([^}]+)\}/g, function(_, name){ + return escapeHtml(options[name] || ''); + }); + fn(null, html); }); }); From 31dd549f350accd7b4e3685c13f745e857557827 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 23:03:13 -0400 Subject: [PATCH 097/889] tests: add test for dispatching to empty route --- test/Route.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Route.js b/test/Route.js index c979fb110c6..ada54086bf0 100644 --- a/test/Route.js +++ b/test/Route.js @@ -7,6 +7,11 @@ var express = require('../') , assert = require('assert'); describe('Route', function(){ + it('should work without handlers', function(done) { + var req = { method: 'GET', url: '/' } + var route = new Route('/foo') + route.dispatch(req, {}, done) + }) describe('.all', function(){ it('should add handler', function(done){ From e5502690d2db1b2ca9f78d0025176b29d834c3ba Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 23:15:52 -0400 Subject: [PATCH 098/889] deps: accepts@~1.3.3 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c72241b98d5..562e7214a4b 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,14 @@ +unreleased +========== + + * deps: accepts@~1.3.3 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Many performance improvments + - deps: mime-types@~2.1.11 + - deps: negotiator@0.6.1 + 4.13.4 / 2016-01-21 =================== diff --git a/package.json b/package.json index 404a3dea739..dc21ce4f673 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "api" ], "dependencies": { - "accepts": "~1.2.12", + "accepts": "~1.3.3", "array-flatten": "1.1.1", "content-disposition": "0.5.1", "content-type": "~1.0.1", From 2cf830b29e7260afe1e414a80850a014556ba429 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 May 2016 23:18:41 -0400 Subject: [PATCH 099/889] deps: content-type@~1.0.2 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 562e7214a4b..a88d5a76e17 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,8 @@ unreleased - Many performance improvments - deps: mime-types@~2.1.11 - deps: negotiator@0.6.1 + * deps: content-type@~1.0.2 + - perf: enable strict mode 4.13.4 / 2016-01-21 =================== diff --git a/package.json b/package.json index dc21ce4f673..278adfa0f6b 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "accepts": "~1.3.3", "array-flatten": "1.1.1", "content-disposition": "0.5.1", - "content-type": "~1.0.1", + "content-type": "~1.0.2", "cookie": "0.1.5", "cookie-signature": "1.0.6", "debug": "~2.2.0", From 76c56d1ab88dd253e90b39e621dcef20219a7204 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 29 May 2016 14:25:27 -0400 Subject: [PATCH 100/889] deps: vary@~1.1.0 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index a88d5a76e17..7e4b0571f53 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,8 @@ unreleased - deps: negotiator@0.6.1 * deps: content-type@~1.0.2 - perf: enable strict mode + * deps: vary@~1.1.0 + - Only accept valid field names in the `field` argument 4.13.4 / 2016-01-21 =================== diff --git a/package.json b/package.json index 278adfa0f6b..4a9101ebc59 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "serve-static": "~1.10.2", "type-is": "~1.6.6", "utils-merge": "1.0.0", - "vary": "~1.0.1" + "vary": "~1.1.0" }, "devDependencies": { "after": "0.8.1", From bdf604a77e8bab6c7f47e85eca77c21b84d5b33e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 31 May 2016 00:08:16 -0400 Subject: [PATCH 101/889] deps: cookie@0.3.1 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 7e4b0571f53..347b4d9607c 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,17 @@ unreleased - deps: negotiator@0.6.1 * deps: content-type@~1.0.2 - perf: enable strict mode + * deps: cookie@0.3.1 + - Add `sameSite` option + - Fix cookie `Max-Age` to never be a floating point number + - Improve error message when `encode` is not a function + - Improve error message when `expires` is not a `Date` + - Throw better error for invalid argument to parse + - Throw on invalid values provided to `serialize` + - perf: enable strict mode + - perf: hoist regular expression + - perf: use for loop in parse + - perf: use string concatination for serialization * deps: vary@~1.1.0 - Only accept valid field names in the `field` argument diff --git a/package.json b/package.json index 4a9101ebc59..0202c782265 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "array-flatten": "1.1.1", "content-disposition": "0.5.1", "content-type": "~1.0.2", - "cookie": "0.1.5", + "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "~2.2.0", "depd": "~1.1.0", From c6039af39d6bc50edfbdd7c822c79e97ba86fc4f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 31 May 2016 00:12:54 -0400 Subject: [PATCH 102/889] deps: proxy-addr@~1.1.2 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 347b4d9607c..9aa6b0acc03 100644 --- a/History.md +++ b/History.md @@ -21,6 +21,12 @@ unreleased - perf: hoist regular expression - perf: use for loop in parse - perf: use string concatination for serialization + * deps: proxy-addr@~1.1.2 + - Fix accepting various invalid netmasks + - Fix IPv6-mapped IPv4 validation edge cases + - IPv4 netmasks must be contingous + - IPv6 addresses cannot be used as a netmask + - deps: ipaddr.js@1.1.1 * deps: vary@~1.1.0 - Only accept valid field names in the `field` argument diff --git a/package.json b/package.json index 0202c782265..1206e08e991 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", - "proxy-addr": "~1.0.10", + "proxy-addr": "~1.1.2", "qs": "4.0.0", "range-parser": "~1.0.3", "send": "0.13.1", From b69b7605b07b41273acc931d25ab585377bcd107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Mon, 3 Aug 2015 23:21:38 +0200 Subject: [PATCH 103/889] perf: use strict equality when possible closes #2722 --- History.md | 1 + lib/request.js | 6 +++--- lib/response.js | 2 +- lib/router/index.js | 2 +- lib/utils.js | 8 ++++---- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/History.md b/History.md index 9aa6b0acc03..764974d0788 100644 --- a/History.md +++ b/History.md @@ -29,6 +29,7 @@ unreleased - deps: ipaddr.js@1.1.1 * deps: vary@~1.1.0 - Only accept valid field names in the `field` argument + * perf: use strict equality when possible 4.13.4 / 2016-01-21 =================== diff --git a/lib/request.js b/lib/request.js index 33cac180ed7..4fdc279ebcb 100644 --- a/lib/request.js +++ b/lib/request.js @@ -303,7 +303,7 @@ defineGetter(req, 'protocol', function protocol(){ /** * Short-hand for: * - * req.protocol == 'https' + * req.protocol === 'https' * * @return {Boolean} * @public @@ -437,10 +437,10 @@ defineGetter(req, 'fresh', function(){ var s = this.res.statusCode; // GET or HEAD for weak freshness validation only - if ('GET' != method && 'HEAD' != method) return false; + if ('GET' !== method && 'HEAD' !== method) return false; // 2xx or 304 as per rfc2616 14.26 - if ((s >= 200 && s < 300) || 304 == s) { + if ((s >= 200 && s < 300) || 304 === s) { return fresh(this.headers, (this.res._headers || {})); } diff --git a/lib/response.js b/lib/response.js index e813c52ec1e..b93459cff56 100644 --- a/lib/response.js +++ b/lib/response.js @@ -189,7 +189,7 @@ res.send = function send(body) { if (req.fresh) this.statusCode = 304; // strip irrelevant headers - if (204 == this.statusCode || 304 == this.statusCode) { + if (204 === this.statusCode || 304 === this.statusCode) { this.removeHeader('Content-Type'); this.removeHeader('Content-Length'); this.removeHeader('Transfer-Encoding'); diff --git a/lib/router/index.js b/lib/router/index.js index 504ed9ce0ee..dac2514815b 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -119,7 +119,7 @@ proto.param = function param(name, fn) { // ensure we end up with a // middleware function - if ('function' != typeof fn) { + if ('function' !== typeof fn) { throw new Error('invalid param() call for ' + name + ', got ' + fn); } diff --git a/lib/utils.js b/lib/utils.js index 3d54247ad28..465b31f5367 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -66,9 +66,9 @@ exports.wetag = function wetag(body, encoding){ */ exports.isAbsolute = function(path){ - if ('/' == path[0]) return true; - if (':' == path[1] && '\\' == path[2]) return true; - if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path + if ('/' === path[0]) return true; + if (':' === path[1] && '\\' === path[2]) return true; + if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path }; /** @@ -142,7 +142,7 @@ function acceptParams(str, index) { for (var i = 1; i < parts.length; ++i) { var pms = parts[i].split(/ *= */); - if ('q' == pms[0]) { + if ('q' === pms[0]) { ret.quality = parseFloat(pms[1]); } else { ret.params[pms[0]] = pms[1]; From f90f9dde3fe02cd9f4b081c16441415817b297b0 Mon Sep 17 00:00:00 2001 From: Benjamin Tan Date: Mon, 22 Feb 2016 06:22:35 +0800 Subject: [PATCH 104/889] Improve performance for res.json/res.jsonp in most cases closes #2900 --- History.md | 1 + lib/response.js | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 764974d0788..6d1eb43643b 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Improve performance for `res.json`/`res.jsonp` in most cases * deps: accepts@~1.3.3 - Fix including type extensions in parameters in `Accept` parsing - Fix parsing `Accept` parameters with quoted equals diff --git a/lib/response.js b/lib/response.js index b93459cff56..ad502ad8b58 100644 --- a/lib/response.js +++ b/lib/response.js @@ -239,7 +239,7 @@ res.json = function json(obj) { var app = this.app; var replacer = app.get('json replacer'); var spaces = app.get('json spaces'); - var body = JSON.stringify(val, replacer, spaces); + var body = stringify(val, replacer, spaces); // content-type if (!this.get('Content-Type')) { @@ -281,7 +281,7 @@ res.jsonp = function jsonp(obj) { var app = this.app; var replacer = app.get('json replacer'); var spaces = app.get('json spaces'); - var body = JSON.stringify(val, replacer, spaces); + var body = stringify(val, replacer, spaces); var callback = this.req.query[app.get('jsonp callback name')]; // content-type @@ -1051,3 +1051,16 @@ function sendfile(res, file, options, callback) { // pipe file.pipe(res); } + +/** + * Stringify JSON, like JSON.stringify, but v8 optimized. + * @private + */ + +function stringify(value, replacer, spaces) { + // v8 checks arguments.length for optimizing simple call + // https://bugs.chromium.org/p/v8/issues/detail?id=4730 + return replacer || spaces + ? JSON.stringify(value, replacer, spaces) + : JSON.stringify(value); +} From cc25a04d10aace04addb1f4a4a53611f364b86c5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 31 May 2016 14:25:41 -0400 Subject: [PATCH 105/889] deps: type-is@~1.6.13 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 6d1eb43643b..5fd9623b6c8 100644 --- a/History.md +++ b/History.md @@ -28,6 +28,9 @@ unreleased - IPv4 netmasks must be contingous - IPv6 addresses cannot be used as a netmask - deps: ipaddr.js@1.1.1 + * deps: type-is@~1.6.13 + - Fix type error when given invalid type to match against + - deps: mime-types@~2.1.11 * deps: vary@~1.1.0 - Only accept valid field names in the `field` argument * perf: use strict equality when possible diff --git a/package.json b/package.json index 1206e08e991..8a35cdece25 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "range-parser": "~1.0.3", "send": "0.13.1", "serve-static": "~1.10.2", - "type-is": "~1.6.6", + "type-is": "~1.6.13", "utils-merge": "1.0.0", "vary": "~1.1.0" }, From 999546dfdeb874c20b360ad58346ed07917f3ac0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 31 May 2016 14:28:20 -0400 Subject: [PATCH 106/889] deps: qs@6.2.0 --- History.md | 2 ++ lib/middleware/query.js | 11 +++-------- lib/utils.js | 1 - package.json | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/History.md b/History.md index 5fd9623b6c8..ddb0c9a7e8a 100644 --- a/History.md +++ b/History.md @@ -28,6 +28,8 @@ unreleased - IPv4 netmasks must be contingous - IPv6 addresses cannot be used as a netmask - deps: ipaddr.js@1.1.1 + * deps: qs@6.2.0 + - Add `decoder` option in `parse` function * deps: type-is@~1.6.13 - Fix type error when given invalid type to match against - deps: mime-types@~2.1.11 diff --git a/lib/middleware/query.js b/lib/middleware/query.js index a665f3f1431..5f76f8458f0 100644 --- a/lib/middleware/query.js +++ b/lib/middleware/query.js @@ -30,14 +30,9 @@ module.exports = function query(options) { opts = undefined; } - if (opts !== undefined) { - if (opts.allowDots === undefined) { - opts.allowDots = false; - } - - if (opts.allowPrototypes === undefined) { - opts.allowPrototypes = true; - } + if (opts !== undefined && opts.allowPrototypes === undefined) { + // back-compat for qs module + opts.allowPrototypes = true; } return function query(req, res, next){ diff --git a/lib/utils.js b/lib/utils.js index 465b31f5367..c2d3af1d620 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -283,7 +283,6 @@ exports.setCharset = function setCharset(type, charset) { function parseExtendedQueryString(str) { return qs.parse(str, { - allowDots: false, allowPrototypes: true }); } diff --git a/package.json b/package.json index 8a35cdece25..2478c634926 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.2", - "qs": "4.0.0", + "qs": "6.2.0", "range-parser": "~1.0.3", "send": "0.13.1", "serve-static": "~1.10.2", From 2e1284beb6210444932d050b9d31d3908afb7591 Mon Sep 17 00:00:00 2001 From: huaoguo Date: Wed, 1 Jun 2016 12:56:27 +0800 Subject: [PATCH 107/889] Fix Windows absolute path check using forward slashes closes #3017 --- History.md | 1 + lib/utils.js | 2 +- test/utils.js | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ddb0c9a7e8a..d1a248ec18e 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Fix Windows absolute path check using forward slashes * Improve performance for `res.json`/`res.jsonp` in most cases * deps: accepts@~1.3.3 - Fix including type extensions in parameters in `Accept` parsing diff --git a/lib/utils.js b/lib/utils.js index c2d3af1d620..f418c5807c7 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -67,7 +67,7 @@ exports.wetag = function wetag(body, encoding){ exports.isAbsolute = function(path){ if ('/' === path[0]) return true; - if (':' === path[1] && '\\' === path[2]) return true; + if (':' === path[1] && ('\\' === path[2] || '/' === path[2])) return true; // Windows device path if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path }; diff --git a/test/utils.js b/test/utils.js index b7e8b520091..b6731962601 100644 --- a/test/utils.js +++ b/test/utils.js @@ -73,6 +73,7 @@ describe('utils.wetag(body, encoding)', function(){ describe('utils.isAbsolute()', function(){ it('should support windows', function(){ assert(utils.isAbsolute('c:\\')); + assert(utils.isAbsolute('c:/')); assert(!utils.isAbsolute(':\\')); }) From 98224d2c4f60708dcd6cb43bc50654ab804665d2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Jun 2016 17:22:15 -0400 Subject: [PATCH 108/889] build: ejs@2.4.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2478c634926..ba3e9c8cb68 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ }, "devDependencies": { "after": "0.8.1", - "ejs": "2.4.1", + "ejs": "2.4.2", "istanbul": "0.4.3", "marked": "0.3.5", "mocha": "2.5.1", From c9531ac1f19a2bab4af819bfab6cb6dfab49e101 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Jun 2016 17:24:08 -0400 Subject: [PATCH 109/889] build: mocha@2.5.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ba3e9c8cb68..1c6d1ae0d7c 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "ejs": "2.4.2", "istanbul": "0.4.3", "marked": "0.3.5", - "mocha": "2.5.1", + "mocha": "2.5.3", "should": "8.4.0", "supertest": "1.1.0", "body-parser": "~1.14.2", From d03868965858af94a712fbd4ad68827023199462 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Jun 2016 17:27:06 -0400 Subject: [PATCH 110/889] build: should@9.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c6d1ae0d7c..141f12c76f1 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "istanbul": "0.4.3", "marked": "0.3.5", "mocha": "2.5.3", - "should": "8.4.0", + "should": "9.0.0", "supertest": "1.1.0", "body-parser": "~1.14.2", "connect-redis": "~2.4.1", From 8ddab697cc1d7b4c3d6d24b8e265be116ddccc0b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Jun 2016 17:31:10 -0400 Subject: [PATCH 111/889] build: supertest@1.2.0 --- package.json | 2 +- test/req.query.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 141f12c76f1..1af28db9801 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "marked": "0.3.5", "mocha": "2.5.3", "should": "9.0.0", - "supertest": "1.1.0", + "supertest": "1.2.0", "body-parser": "~1.14.2", "connect-redis": "~2.4.1", "cookie-parser": "~1.4.1", diff --git a/test/req.query.js b/test/req.query.js index 19151411995..d3d29abd16d 100644 --- a/test/req.query.js +++ b/test/req.query.js @@ -43,7 +43,7 @@ describe('req', function(){ var app = createApp('simple'); request(app) - .get('/?user[name]=tj') + .get('/?user%5Bname%5D=tj') .expect(200, '{"user[name]":"tj"}', done); }); }); @@ -55,7 +55,7 @@ describe('req', function(){ }); request(app) - .get('/?user[name]=tj') + .get('/?user%5Bname%5D=tj') .expect(200, '{"length":17}', done); }); }); @@ -65,7 +65,7 @@ describe('req', function(){ var app = createApp(false); request(app) - .get('/?user[name]=tj') + .get('/?user%5Bname%5D=tj') .expect(200, '{}', done); }); }); @@ -75,7 +75,7 @@ describe('req', function(){ var app = createApp(true); request(app) - .get('/?user[name]=tj') + .get('/?user%5Bname%5D=tj') .expect(200, '{"user[name]":"tj"}', done); }); }); From 7ee41cc23f2f7237ad8e3b1cfbad03900f14314d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Jun 2016 18:54:11 -0400 Subject: [PATCH 112/889] deps: range-parser@~1.2.0 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index d1a248ec18e..77552f8411f 100644 --- a/History.md +++ b/History.md @@ -31,6 +31,10 @@ unreleased - deps: ipaddr.js@1.1.1 * deps: qs@6.2.0 - Add `decoder` option in `parse` function + * deps: range-parser@~1.2.0 + - Add `combine` option to combine overlapping ranges + - Fix incorrectly returning -1 when there is at least one valid range + - perf: remove internal function * deps: type-is@~1.6.13 - Fix type error when given invalid type to match against - deps: mime-types@~2.1.11 diff --git a/package.json b/package.json index 1af28db9801..303524a3e5c 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.2", "qs": "6.2.0", - "range-parser": "~1.0.3", + "range-parser": "~1.2.0", "send": "0.13.1", "serve-static": "~1.10.2", "type-is": "~1.6.13", From 7fcf1d7d5b021d4c285f377d99e0d40dbf26a9b1 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Jun 2016 19:04:02 -0400 Subject: [PATCH 113/889] docs: update the req.range jsdoc comment --- lib/request.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/request.js b/lib/request.js index 4fdc279ebcb..17eb47c33c7 100644 --- a/lib/request.js +++ b/lib/request.js @@ -171,26 +171,26 @@ req.acceptsLanguage = deprecate.function(req.acceptsLanguages, 'req.acceptsLanguage: Use acceptsLanguages instead'); /** - * Parse Range header field, - * capping to the given `size`. + * Parse Range header field, capping to the given `size`. * - * Unspecified ranges such as "0-" require - * knowledge of your resource length. In - * the case of a byte range this is of course - * the total number of bytes. If the Range - * header field is not given `null` is returned, - * `-1` when unsatisfiable, `-2` when syntactically invalid. + * Unspecified ranges such as "0-" require knowledge of your resource length. In + * the case of a byte range this is of course the total number of bytes. If the + * Range header field is not given `undefined` is returned, `-1` when unsatisfiable, + * and `-2` when syntactically invalid. * - * NOTE: remember that ranges are inclusive, so - * for example "Range: users=0-3" should respond - * with 4 users when available, not 3. + * When ranges are returned, the array has a "type" property which is the type of + * range that is required (most commonly, "bytes"). Each array element is an object + * with a "start" and "end" property for the portion of the range. * - * @param {Number} size - * @return {Array} + * NOTE: remember that ranges are inclusive, so for example "Range: users=0-3" + * should respond with 4 users when available, not 3. + * + * @param {number} size + * @return {number|array} * @public */ -req.range = function(size){ +req.range = function range(size) { var range = this.get('Range'); if (!range) return; return parseRange(size, range); From 5d642af8c34c49b54b1ea2f9a300440ec5656fef Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Jun 2016 19:13:36 -0400 Subject: [PATCH 114/889] Add "options" argument to req.range --- History.md | 2 ++ lib/request.js | 9 +++++++-- test/req.range.js | 16 +++++++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index 77552f8411f..a184efbf8a9 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,8 @@ unreleased ========== + * Add `options` argument to `req.range` + - Includes the `combine` option * Fix Windows absolute path check using forward slashes * Improve performance for `res.json`/`res.jsonp` in most cases * deps: accepts@~1.3.3 diff --git a/lib/request.js b/lib/request.js index 17eb47c33c7..ef0e101a001 100644 --- a/lib/request.js +++ b/lib/request.js @@ -182,18 +182,23 @@ req.acceptsLanguage = deprecate.function(req.acceptsLanguages, * range that is required (most commonly, "bytes"). Each array element is an object * with a "start" and "end" property for the portion of the range. * + * The "combine" option can be set to `true` and overlapping & adjacent ranges + * will be combined into a single range. + * * NOTE: remember that ranges are inclusive, so for example "Range: users=0-3" * should respond with 4 users when available, not 3. * * @param {number} size + * @param {object} [options] + * @param {boolean} [options.combine=false] * @return {number|array} * @public */ -req.range = function range(size) { +req.range = function range(size, options) { var range = this.get('Range'); if (!range) return; - return parseRange(size, range); + return parseRange(size, range, options); }; /** diff --git a/test/req.range.js b/test/req.range.js index 08cf8f91e92..d530d85a645 100644 --- a/test/req.range.js +++ b/test/req.range.js @@ -12,9 +12,9 @@ function req(ret) { describe('req', function(){ describe('.range(size)', function(){ it('should return parsed ranges', function(){ - var ret = [{ start: 0, end: 50 }, { start: 60, end: 100 }]; - ret.type = 'bytes'; - req('bytes=0-50,60-100').range(120).should.eql(ret); + var ranges = [{ start: 0, end: 50 }, { start: 51, end: 100 }] + ranges.type = 'bytes' + assert.deepEqual(req('bytes=0-50,51-100').range(120), ranges) }) it('should cap to the given size', function(){ @@ -35,4 +35,14 @@ describe('req', function(){ assert(req('').range(120) === undefined); }) }) + + describe('.range(size, options)', function(){ + describe('with "combine: true" option', function(){ + it('should return combined ranges', function(){ + var ranges = [{ start: 0, end: 100 }] + ranges.type = 'bytes' + assert.deepEqual(req('bytes=0-50,51-100').range(120, { combine: true }), ranges) + }) + }) + }) }) From c762b16f62e2c9f5de33481c250ef6f94a99eb7f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 3 Jun 2016 00:07:34 -0400 Subject: [PATCH 115/889] Improve error with invalid arguments to req.get() fixes #2993 --- History.md | 1 + lib/request.js | 8 ++++++++ test/req.get.js | 26 +++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index a184efbf8a9..46e99a265eb 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ unreleased * Add `options` argument to `req.range` - Includes the `combine` option * Fix Windows absolute path check using forward slashes + * Improve error with invalid arguments to `req.get()` * Improve performance for `res.json`/`res.jsonp` in most cases * deps: accepts@~1.3.3 - Fix including type extensions in parameters in `Accept` parsing diff --git a/lib/request.js b/lib/request.js index ef0e101a001..557d050ffb5 100644 --- a/lib/request.js +++ b/lib/request.js @@ -57,6 +57,14 @@ var req = exports = module.exports = { req.get = req.header = function header(name) { + if (!name) { + throw new TypeError('name argument is required to req.get'); + } + + if (typeof name !== 'string') { + throw new TypeError('name must be a string to req.get'); + } + var lc = name.toLowerCase(); switch (lc) { diff --git a/test/req.get.js b/test/req.get.js index 144a256848d..109a2d90ce7 100644 --- a/test/req.get.js +++ b/test/req.get.js @@ -31,5 +31,29 @@ describe('req', function(){ .set('Referrer', 'http://foobar.com/') .expect('http://foobar.com/', done); }) + + it('should throw missing header name', function (done) { + var app = express() + + app.use(function (req, res) { + res.end(req.get()) + }) + + request(app) + .get('/') + .expect(500, /TypeError: name argument is required to req.get/, done) + }) + + it('should throw for non-string header name', function (done) { + var app = express() + + app.use(function (req, res) { + res.end(req.get(42)) + }) + + request(app) + .get('/') + .expect(500, /TypeError: name must be a string to req.get/, done) + }) }) -}) \ No newline at end of file +}) From fc40702cb70e39565263d64d962d3b8164fb3621 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 12 Jun 2016 22:33:44 -0400 Subject: [PATCH 116/889] deps: send@0.14.1 --- History.md | 18 ++++++++++++++++++ package.json | 2 +- test/res.sendFile.js | 22 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 46e99a265eb..12bafeff42d 100644 --- a/History.md +++ b/History.md @@ -1,11 +1,15 @@ unreleased ========== + * Add `acceptRanges` option to `res.sendFile`/`res.sendfile` + * Add `cacheControl` option to `res.sendFile`/`res.sendfile` * Add `options` argument to `req.range` - Includes the `combine` option + * Fix some redirect handling in `res.sendFile`/`res.sendfile` * Fix Windows absolute path check using forward slashes * Improve error with invalid arguments to `req.get()` * Improve performance for `res.json`/`res.jsonp` in most cases + * Improve `Range` header handling in `res.sendFile`/`res.sendfile` * deps: accepts@~1.3.3 - Fix including type extensions in parameters in `Accept` parsing - Fix parsing `Accept` parameters with quoted equals @@ -38,6 +42,20 @@ unreleased - Add `combine` option to combine overlapping ranges - Fix incorrectly returning -1 when there is at least one valid range - perf: remove internal function + * deps: send@0.14.1 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Correctly inherit from `Stream` class + - Fix `Content-Range` header in 416 responses when using `start`/`end` options + - Fix `Content-Range` header missing from default 416 responses + - Fix redirect error when `path` contains raw non-URL characters + - Fix redirect when `path` starts with multiple forward slashes + - Ignore non-byte `Range` headers + - deps: http-errors@~1.5.0 + - deps: range-parser@~1.2.0 + - deps: statuses@~1.3.0 + - perf: remove argument reassignment * deps: type-is@~1.6.13 - Fix type error when given invalid type to match against - deps: mime-types@~2.1.11 diff --git a/package.json b/package.json index 303524a3e5c..6d9a9f39c37 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "proxy-addr": "~1.1.2", "qs": "6.2.0", "range-parser": "~1.2.0", - "send": "0.13.1", + "send": "0.14.1", "serve-static": "~1.10.2", "type-is": "~1.6.13", "utils-merge": "1.0.0", diff --git a/test/res.sendFile.js b/test/res.sendFile.js index 78013a50ebd..705c15a8b7e 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -286,6 +286,14 @@ describe('res', function(){ }) }) + describe('.sendFile(path, options)', function () { + it('should pass options to send module', function (done) { + request(createApp(path.resolve(fixtures, 'name.txt'), { start: 0, end: 1 })) + .get('/') + .expect(200, 'to', done) + }) + }) + describe('.sendfile(path, fn)', function(){ it('should invoke the callback when complete', function(done){ var app = express(); @@ -702,6 +710,20 @@ describe('res', function(){ }) }) + describe('.sendfile(path, options)', function () { + it('should pass options to send module', function (done) { + var app = express() + + app.use(function (req, res) { + res.sendfile(path.resolve(fixtures, 'name.txt'), { start: 0, end: 1 }) + }) + + request(app) + .get('/') + .expect(200, 'to', done) + }) + }) + function createApp(path, options, fn) { var app = express(); From 791cabf9390a029c5ad9b63eae8145c3c73f204e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 12 Jun 2016 22:38:20 -0400 Subject: [PATCH 117/889] deps: serve-static@~1.11.1 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 12bafeff42d..0c2a99873db 100644 --- a/History.md +++ b/History.md @@ -56,6 +56,14 @@ unreleased - deps: range-parser@~1.2.0 - deps: statuses@~1.3.0 - perf: remove argument reassignment + * deps: serve-static@~1.11.1 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Fix redirect error when `req.url` contains raw non-URL characters + - Ignore non-byte `Range` headers + - Use status code 301 for redirects + - deps: send@0.14.1 * deps: type-is@~1.6.13 - Fix type error when given invalid type to match against - deps: mime-types@~2.1.11 diff --git a/package.json b/package.json index 6d9a9f39c37..ede72a7eb16 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "qs": "6.2.0", "range-parser": "~1.2.0", "send": "0.14.1", - "serve-static": "~1.10.2", + "serve-static": "~1.11.1", "type-is": "~1.6.13", "utils-merge": "1.0.0", "vary": "~1.1.0" From 23c22ce3fe2c298add7c06ac881ce0f17f73a6be Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Jun 2016 22:50:18 -0400 Subject: [PATCH 118/889] build: support Node.js 5.x --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 38998527547..79f4360e9ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ node_js: - "2.5" - "3.3" - "4.4" + - "5.11" sudo: false cache: directories: diff --git a/appveyor.yml b/appveyor.yml index ce5e52ff1b9..8ed246ec5cc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,7 @@ environment: - nodejs_version: "2.5" - nodejs_version: "3.3" - nodejs_version: "4.4" + - nodejs_version: "5.11" cache: - node_modules install: From c12cc8839277dcb3956558865f0cd241e8d08883 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Jun 2016 22:51:07 -0400 Subject: [PATCH 119/889] build: support Node.js 6.x --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 79f4360e9ee..95034721e75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ node_js: - "3.3" - "4.4" - "5.11" + - "6.2" sudo: false cache: directories: diff --git a/appveyor.yml b/appveyor.yml index 8ed246ec5cc..f1061373510 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,6 +7,7 @@ environment: - nodejs_version: "3.3" - nodejs_version: "4.4" - nodejs_version: "5.11" + - nodejs_version: "6.2" cache: - node_modules install: From 76eaa326ee8c4dda05568c6452286a16adb84c0b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Jun 2016 23:23:29 -0400 Subject: [PATCH 120/889] Encode URL in res.location/res.redirect if not already encoded fixes #2897 fixes #3003 --- History.md | 1 + lib/response.js | 9 ++++----- package.json | 1 + test/res.location.js | 26 ++++++++++++++++++++++++++ test/res.redirect.js | 36 +++++++++++++++++++++++++++++++----- 5 files changed, 63 insertions(+), 10 deletions(-) diff --git a/History.md b/History.md index 0c2a99873db..5fc6dd253a6 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ unreleased * Add `cacheControl` option to `res.sendFile`/`res.sendfile` * Add `options` argument to `req.range` - Includes the `combine` option + * Encode URL in `res.location`/`res.redirect` if not already encoded * Fix some redirect handling in `res.sendFile`/`res.sendfile` * Fix Windows absolute path check using forward slashes * Improve error with invalid arguments to `req.get()` diff --git a/lib/response.js b/lib/response.js index ad502ad8b58..6128f450a94 100644 --- a/lib/response.js +++ b/lib/response.js @@ -14,6 +14,7 @@ var contentDisposition = require('content-disposition'); var deprecate = require('depd')('express'); +var encodeUrl = require('encodeurl'); var escapeHtml = require('escape-html'); var http = require('http'); var isAbsolute = require('./utils').isAbsolute; @@ -832,8 +833,7 @@ res.location = function location(url) { } // set location - this.set('Location', loc); - return this; + return this.set('Location', encodeUrl(loc)); }; /** @@ -871,13 +871,12 @@ res.redirect = function redirect(url) { } // Set location header - this.location(address); - address = this.get('Location'); + address = this.location(address).get('Location'); // Support text/{plain,html} by default this.format({ text: function(){ - body = statusCodes[status] + '. Redirecting to ' + encodeURI(address); + body = statusCodes[status] + '. Redirecting to ' + address; }, html: function(){ diff --git a/package.json b/package.json index ede72a7eb16..8ed7783ab0a 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "cookie-signature": "1.0.6", "debug": "~2.2.0", "depd": "~1.1.0", + "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.7.0", "finalhandler": "0.4.1", diff --git a/test/res.location.js b/test/res.location.js index 2b42bf358d4..bb9eb6f92e3 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -16,5 +16,31 @@ describe('res', function(){ .expect('Location', 'http://google.com/') .expect(200, done) }) + + it('should encode "url"', function (done) { + var app = express() + + app.use(function (req, res) { + res.location('https://google.com/?q=\u2603%20%C2%A710').end() + }) + + request(app) + .get('/') + .expect('Location', 'https://google.com/?q=%E2%98%83%20%C2%A710') + .expect(200, done) + }) + + it('should not touch already-encoded sequences in "url"', function (done) { + var app = express() + + app.use(function (req, res) { + res.location('https://google.com/?q=%A710').end() + }) + + request(app) + .get('/') + .expect('Location', 'https://google.com/?q=%A710') + .expect(200, done) + }) }) }) diff --git a/test/res.redirect.js b/test/res.redirect.js index 8511c40f2ab..9f3bd436763 100644 --- a/test/res.redirect.js +++ b/test/res.redirect.js @@ -18,6 +18,32 @@ describe('res', function(){ .expect('location', 'http://google.com/') .expect(302, done) }) + + it('should encode "url"', function (done) { + var app = express() + + app.use(function (req, res) { + res.redirect('https://google.com/?q=\u2603%20%C2%A710') + }) + + request(app) + .get('/') + .expect('Location', 'https://google.com/?q=%E2%98%83%20%C2%A710') + .expect(302, done) + }) + + it('should not touch already-encoded sequences in "url"', function (done) { + var app = express() + + app.use(function (req, res) { + res.redirect('https://google.com/?q=%A710') + }) + + request(app) + .get('/') + .expect('Location', 'https://google.com/?q=%A710') + .expect(302, done) + }) }) describe('.redirect(status, url)', function(){ @@ -85,7 +111,7 @@ describe('res', function(){ var app = express(); app.use(function(req, res){ - res.redirect(''); + res.redirect(''); }); request(app) @@ -93,8 +119,8 @@ describe('res', function(){ .set('Host', 'http://example.com/') .set('Accept', 'text/html') .expect('Content-Type', /html/) - .expect('Location', '') - .expect(302, '

' + http.STATUS_CODES[302] + '. Redirecting to <lame>

', done); + .expect('Location', '%3Cla\'me%3E') + .expect(302, '

' + http.STATUS_CODES[302] + '. Redirecting to %3Cla'me%3E

', done) }) it('should include the redirect type', function(done){ @@ -141,8 +167,8 @@ describe('res', function(){ .set('Host', 'http://example.com/') .set('Accept', 'text/plain, */*') .expect('Content-Type', /plain/) - .expect('Location', 'http://example.com/?param=%3Cscript%3Ealert("hax");') - .expect(302, http.STATUS_CODES[302] + '. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E', done); + .expect('Location', 'http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E') + .expect(302, http.STATUS_CODES[302] + '. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E', done) }) it('should include the redirect type', function(done){ From e06766c573ba3784798fc9b8775cea1304e34427 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 15 Jun 2016 18:12:19 -0400 Subject: [PATCH 121/889] deps: finalhandler@0.5.0 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5fc6dd253a6..6c3811a4577 100644 --- a/History.md +++ b/History.md @@ -31,6 +31,12 @@ unreleased - perf: hoist regular expression - perf: use for loop in parse - perf: use string concatination for serialization + * deps: finalhandler@0.5.0 + - Change invalid or non-numeric status code to 500 + - Overwrite status message to match set status code + - Prefer `err.statusCode` if `err.status` is invalid + - Set response headers from `err.headers` object + - Use `statuses` instead of `http` module for status messages * deps: proxy-addr@~1.1.2 - Fix accepting various invalid netmasks - Fix IPv6-mapped IPv4 validation edge cases diff --git a/package.json b/package.json index 8ed7783ab0a..2c8e5cb9741 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.7.0", - "finalhandler": "0.4.1", + "finalhandler": "0.5.0", "fresh": "0.3.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", From 605983fd0e838f9ddb9d85f4e1950f0ce5bed83d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 15 Jun 2016 18:13:30 -0400 Subject: [PATCH 122/889] build: should@9.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2c8e5cb9741..3e491e78126 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "istanbul": "0.4.3", "marked": "0.3.5", "mocha": "2.5.3", - "should": "9.0.0", + "should": "9.0.2", "supertest": "1.2.0", "body-parser": "~1.14.2", "connect-redis": "~2.4.1", From 14cf9c563679566bef9a396bfa9702776bfc1b48 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 15 Jun 2016 18:16:08 -0400 Subject: [PATCH 123/889] deps: update example dependencies --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3e491e78126..6b3b11b1e60 100644 --- a/package.json +++ b/package.json @@ -56,22 +56,22 @@ }, "devDependencies": { "after": "0.8.1", + "body-parser": "~1.15.1", + "cookie-parser": "~1.4.3", "ejs": "2.4.2", "istanbul": "0.4.3", "marked": "0.3.5", + "method-override": "~2.3.6", "mocha": "2.5.3", + "morgan": "~1.7.0", "should": "9.0.2", "supertest": "1.2.0", - "body-parser": "~1.14.2", "connect-redis": "~2.4.1", - "cookie-parser": "~1.4.1", "cookie-session": "~1.2.0", "express-session": "~1.13.0", "jade": "~1.11.0", - "method-override": "~2.3.5", - "morgan": "~1.6.1", "multiparty": "~4.1.2", - "vhost": "~3.0.1" + "vhost": "~3.0.2" }, "engines": { "node": ">= 0.10.0" From 9375a9afa9d7baa814b454c7a6818a7471aaef00 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 16 Jun 2016 11:03:44 -0400 Subject: [PATCH 124/889] 4.14.0 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 6c3811a4577..40a5ed7e4be 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.14.0 / 2016-06-16 +=================== * Add `acceptRanges` option to `res.sendFile`/`res.sendfile` * Add `cacheControl` option to `res.sendFile`/`res.sendfile` diff --git a/package.json b/package.json index 6b3b11b1e60..57dd1602884 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.13.4", + "version": "4.14.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 305f982bd734da5ee74abba9c270905a8f4aa484 Mon Sep 17 00:00:00 2001 From: Hamza Date: Sun, 31 Jul 2016 13:14:05 +0100 Subject: [PATCH 125/889] exapmples: use path.join to concat paths closes #3046 --- examples/static-files/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/static-files/index.js b/examples/static-files/index.js index c3b1659d861..0e44313d15d 100644 --- a/examples/static-files/index.js +++ b/examples/static-files/index.js @@ -4,6 +4,7 @@ var express = require('../..'); var logger = require('morgan'); +var path = require('path'); var app = express(); // log requests @@ -16,7 +17,7 @@ app.use(logger('dev')); // that you pass it. In this case "GET /js/app.js" // will look for "./public/js/app.js". -app.use(express.static(__dirname + '/public')); +app.use(express.static(path.join(__dirname, 'public'))); // if you wanted to "prefix" you may use // the mounting feature of Connect, for example @@ -24,13 +25,13 @@ app.use(express.static(__dirname + '/public')); // The mount-path "/static" is simply removed before // passing control to the express.static() middleware, // thus it serves the file correctly by ignoring "/static" -app.use('/static', express.static(__dirname + '/public')); +app.use('/static', express.static(path.join(__dirname, 'public'))); // if for some reason you want to serve files from // several directories, you can use express.static() // multiple times! Here we're passing "./public/css", // this will allow "GET /style.css" instead of "GET /css/style.css": -app.use(express.static(__dirname + '/public/css')); +app.use(express.static(path.join(__dirname, 'public', 'css'))); app.listen(3000); console.log('listening on port 3000'); From bd47aeb88d28c6cff6e2d8e5378ec73c262e039f Mon Sep 17 00:00:00 2001 From: Vishvajit Pathak Date: Thu, 17 Nov 2016 12:43:14 +0530 Subject: [PATCH 126/889] tests: fix typos in test descriptions closes #3129 closes #3130 --- test/app.options.js | 2 +- test/app.router.js | 2 +- test/req.acceptsEncoding.js | 4 ++-- test/req.acceptsEncodings.js | 4 ++-- test/req.acceptsLanguage.js | 4 ++-- test/req.acceptsLanguages.js | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/app.options.js b/test/app.options.js index 20234723a57..9c88abafe5e 100644 --- a/test/app.options.js +++ b/test/app.options.js @@ -72,7 +72,7 @@ describe('OPTIONS', function(){ .expect(200, 'GET,HEAD', done); }) - describe('when error occurs in respone handler', function () { + describe('when error occurs in response handler', function () { it('should pass error to callback', function (done) { var app = express(); var router = express.Router(); diff --git a/test/app.router.js b/test/app.router.js index 03b43eb081a..11e492cbfae 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -757,7 +757,7 @@ describe('app.router', function(){ .expect('editing tj (old)', cb); }) - it('should work inside literal paranthesis', function(done){ + it('should work inside literal parenthesis', function(done){ var app = express(); app.get('/:user\\(:op\\)', function(req, res){ diff --git a/test/req.acceptsEncoding.js b/test/req.acceptsEncoding.js index 930b4ea76c1..12708fc0144 100644 --- a/test/req.acceptsEncoding.js +++ b/test/req.acceptsEncoding.js @@ -4,7 +4,7 @@ var express = require('../') describe('req', function(){ describe('.acceptsEncoding', function(){ - it('should be true if encoding accpeted', function(done){ + it('should be true if encoding accepted', function(done){ var app = express(); app.use(function(req, res){ @@ -19,7 +19,7 @@ describe('req', function(){ .expect(200, done); }) - it('should be false if encoding not accpeted', function(done){ + it('should be false if encoding not accepted', function(done){ var app = express(); app.use(function(req, res){ diff --git a/test/req.acceptsEncodings.js b/test/req.acceptsEncodings.js index c4c68e1e8ed..c036c297691 100644 --- a/test/req.acceptsEncodings.js +++ b/test/req.acceptsEncodings.js @@ -4,7 +4,7 @@ var express = require('../') describe('req', function(){ describe('.acceptsEncodingss', function(){ - it('should be true if encoding accpeted', function(done){ + it('should be true if encoding accepted', function(done){ var app = express(); app.use(function(req, res){ @@ -19,7 +19,7 @@ describe('req', function(){ .expect(200, done); }) - it('should be false if encoding not accpeted', function(done){ + it('should be false if encoding not accepted', function(done){ var app = express(); app.use(function(req, res){ diff --git a/test/req.acceptsLanguage.js b/test/req.acceptsLanguage.js index 36afc47f929..b14d920bd69 100644 --- a/test/req.acceptsLanguage.js +++ b/test/req.acceptsLanguage.js @@ -4,7 +4,7 @@ var express = require('../') describe('req', function(){ describe('.acceptsLanguage', function(){ - it('should be true if language accpeted', function(done){ + it('should be true if language accepted', function(done){ var app = express(); app.use(function(req, res){ @@ -19,7 +19,7 @@ describe('req', function(){ .expect(200, done); }) - it('should be false if language not accpeted', function(done){ + it('should be false if language not accepted', function(done){ var app = express(); app.use(function(req, res){ diff --git a/test/req.acceptsLanguages.js b/test/req.acceptsLanguages.js index 8d11eb81e83..6a9cb3366bc 100644 --- a/test/req.acceptsLanguages.js +++ b/test/req.acceptsLanguages.js @@ -4,7 +4,7 @@ var express = require('../') describe('req', function(){ describe('.acceptsLanguages', function(){ - it('should be true if language accpeted', function(done){ + it('should be true if language accepted', function(done){ var app = express(); app.use(function(req, res){ @@ -19,7 +19,7 @@ describe('req', function(){ .expect(200, done); }) - it('should be false if language not accpeted', function(done){ + it('should be false if language not accepted', function(done){ var app = express(); app.use(function(req, res){ From 505f8482f2a2d41be856662db41265a7b190ca65 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 2 Dec 2016 22:09:46 -0500 Subject: [PATCH 127/889] build: Node.js@4.6 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 95034721e75..f147c8a6f5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ node_js: - "1.8" - "2.5" - "3.3" - - "4.4" + - "4.6" - "5.11" - "6.2" sudo: false diff --git a/appveyor.yml b/appveyor.yml index f1061373510..7f53b61c289 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ environment: - nodejs_version: "1.8" - nodejs_version: "2.5" - nodejs_version: "3.3" - - nodejs_version: "4.4" + - nodejs_version: "4.6" - nodejs_version: "5.11" - nodejs_version: "6.2" cache: From 421ad5aaaa46ca5b2654bd75d9ec2bd62eed68b5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 2 Dec 2016 22:12:33 -0500 Subject: [PATCH 128/889] build: Node.js@5.12 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f147c8a6f5d..15fea9926e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ node_js: - "2.5" - "3.3" - "4.6" - - "5.11" + - "5.12" - "6.2" sudo: false cache: diff --git a/appveyor.yml b/appveyor.yml index 7f53b61c289..62a82ef709a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ environment: - nodejs_version: "2.5" - nodejs_version: "3.3" - nodejs_version: "4.6" - - nodejs_version: "5.11" + - nodejs_version: "5.12" - nodejs_version: "6.2" cache: - node_modules From 1bcc9b1236197ac78f64e6cc1a7baf2c97d36395 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 2 Dec 2016 22:19:04 -0500 Subject: [PATCH 129/889] build: Node.js@6.9 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 15fea9926e4..3bd122f5d81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ node_js: - "3.3" - "4.6" - "5.12" - - "6.2" + - "6.9" sudo: false cache: directories: diff --git a/appveyor.yml b/appveyor.yml index 62a82ef709a..18d5c4abe02 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ environment: - nodejs_version: "3.3" - nodejs_version: "4.6" - nodejs_version: "5.12" - - nodejs_version: "6.2" + - nodejs_version: "6.9" cache: - node_modules install: From 6210e47cb664714efac017b9e1987f867ae5f804 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 3 Dec 2016 00:04:47 -0500 Subject: [PATCH 130/889] build: after@0.8.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 57dd1602884..76e93218b9e 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "vary": "~1.1.0" }, "devDependencies": { - "after": "0.8.1", + "after": "0.8.2", "body-parser": "~1.15.1", "cookie-parser": "~1.4.3", "ejs": "2.4.2", From f6dca56e72bc8df794bb98fec14a0875323c0569 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 3 Dec 2016 00:08:46 -0500 Subject: [PATCH 131/889] build: istanbul@0.4.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 76e93218b9e..bb0a0e67d22 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "body-parser": "~1.15.1", "cookie-parser": "~1.4.3", "ejs": "2.4.2", - "istanbul": "0.4.3", + "istanbul": "0.4.5", "marked": "0.3.5", "method-override": "~2.3.6", "mocha": "2.5.3", From 1a17888073790f5567fdb9f9e270fab6904abf97 Mon Sep 17 00:00:00 2001 From: Deniz Tetik Date: Wed, 18 Jan 2017 01:32:25 -0500 Subject: [PATCH 132/889] docs: fix minor grammatical error closes #3178 --- Contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index 3fb2b7c25f1..2ddfa7a62a4 100644 --- a/Contributing.md +++ b/Contributing.md @@ -31,7 +31,7 @@ exception is security dislosures which should be sent privately. Committers may direct you to another repository, ask for additional clarifications, and add appropriate metadata before the issue is addressed. -Please be courteous, respectful, and every participant is expected to follow the +Please be courteous and respectful. Every participant is expected to follow the project's Code of Conduct. # Contributions From d1d9631b97b64c7f98f4ad2d0ba61014865b1d49 Mon Sep 17 00:00:00 2001 From: SeongHeon Kim Date: Fri, 20 Jan 2017 23:05:53 +0900 Subject: [PATCH 133/889] docs: remove link to missing section closes #3179 --- Security.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Security.md b/Security.md index d965a87bb0a..cbc5f16cde5 100644 --- a/Security.md +++ b/Security.md @@ -5,7 +5,6 @@ project. * [Reporting a Bug](#reporting-a-bug) * [Disclosure Policy](#disclosure-policy) - * [Receiving Security Updates](#receiving-security-updates) * [Comments on this Policy](#comments-on-this-policy) ## Reporting a Bug From 6723b4419abacba00b73c466edb338e331e9ffe8 Mon Sep 17 00:00:00 2001 From: Zachary Lester Date: Tue, 23 Aug 2016 13:36:52 -0700 Subject: [PATCH 134/889] tests: add test for res.sendFile "cacheContol" option closes #3061 --- test/res.sendFile.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/res.sendFile.js b/test/res.sendFile.js index 705c15a8b7e..ece09ee0731 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -116,6 +116,26 @@ describe('res', function(){ test.expect(200, cb); }) + describe('with "cacheControl" option', function () { + it('should enable cacheControl by default', function (done) { + var app = createApp(path.resolve(__dirname, 'fixtures/name.txt')) + + request(app) + .get('/') + .expect('Cache-Control', 'public, max-age=0') + .expect(200, done) + }) + + it('should accept cacheControl option', function (done) { + var app = createApp(path.resolve(__dirname, 'fixtures/name.txt'), { cacheControl: false }) + + request(app) + .get('/') + .expect(utils.shouldNotHaveHeader('Cache-Control')) + .expect(200, done) + }) + }) + describe('with "dotfiles" option', function () { it('should not serve dotfiles by default', function (done) { var app = createApp(path.resolve(__dirname, 'fixtures/.name')); From ddc93aa0e20e1a802dccc80dd4a84c5763306531 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 21 Jan 2017 00:39:46 -0500 Subject: [PATCH 135/889] deps: content-disposition@0.5.2 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 40a5ed7e4be..ac5203ca815 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * deps: content-disposition@0.5.2 + 4.14.0 / 2016-06-16 =================== diff --git a/package.json b/package.json index bb0a0e67d22..3a56a3de785 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "dependencies": { "accepts": "~1.3.3", "array-flatten": "1.1.1", - "content-disposition": "0.5.1", + "content-disposition": "0.5.2", "content-type": "~1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", From e73913b5837f615eaedde6a7005ffae5d09a3bff Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 21 Jan 2017 00:46:28 -0500 Subject: [PATCH 136/889] build: mocha@3.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a56a3de785..b4ec8b0d559 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "istanbul": "0.4.5", "marked": "0.3.5", "method-override": "~2.3.6", - "mocha": "2.5.3", + "mocha": "3.2.0", "morgan": "~1.7.0", "should": "9.0.2", "supertest": "1.2.0", From a2e323a012de8415df58bd23ccb235bb0e0094c2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 21 Jan 2017 00:59:29 -0500 Subject: [PATCH 137/889] build: should@11.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b4ec8b0d559..9a9b6ce63b1 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "method-override": "~2.3.6", "mocha": "3.2.0", "morgan": "~1.7.0", - "should": "9.0.2", + "should": "11.1.2", "supertest": "1.2.0", "connect-redis": "~2.4.1", "cookie-session": "~1.2.0", From a3d635309cab51fc04730be06efcb31f83d0c444 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 21 Jan 2017 01:00:52 -0500 Subject: [PATCH 138/889] deps: proxy-addr@~1.1.3 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ac5203ca815..63b5a6c2df3 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,8 @@ unreleased ========== * deps: content-disposition@0.5.2 + * deps: proxy-addr@~1.1.3 + - deps: ipaddr.js@1.2.0 4.14.0 / 2016-06-16 =================== diff --git a/package.json b/package.json index 9a9b6ce63b1..eaea535b0a7 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", - "proxy-addr": "~1.1.2", + "proxy-addr": "~1.1.3", "qs": "6.2.0", "range-parser": "~1.2.0", "send": "0.14.1", From cfae537d3b37c73090634dd1dec7b10d6e9b920d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 21 Jan 2017 01:05:17 -0500 Subject: [PATCH 139/889] deps: finalhandler@0.5.1 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 63b5a6c2df3..39e64c441a6 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,11 @@ unreleased ========== * deps: content-disposition@0.5.2 + * deps: finalhandler@0.5.1 + - Fix exception when `err.headers` is not an object + - deps: statuses@~1.3.1 + - perf: hoist regular expressions + - perf: remove duplicate validation path * deps: proxy-addr@~1.1.3 - deps: ipaddr.js@1.2.0 diff --git a/package.json b/package.json index eaea535b0a7..6b334fd59fd 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.7.0", - "finalhandler": "0.5.0", + "finalhandler": "0.5.1", "fresh": "0.3.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", From 572657ee4a63b95d7522232dcc74a5012eb4239e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 23 Jan 2017 10:43:11 -0500 Subject: [PATCH 140/889] deps: send@0.14.2 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 39e64c441a6..922bee8576c 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,10 @@ unreleased - perf: remove duplicate validation path * deps: proxy-addr@~1.1.3 - deps: ipaddr.js@1.2.0 + * deps: send@0.14.2 + - deps: http-errors@~1.5.1 + - deps: ms@0.7.2 + - deps: statuses@~1.3.1 4.14.0 / 2016-06-16 =================== diff --git a/package.json b/package.json index 6b334fd59fd..ebe7757b39a 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "proxy-addr": "~1.1.3", "qs": "6.2.0", "range-parser": "~1.2.0", - "send": "0.14.1", + "send": "0.14.2", "serve-static": "~1.11.1", "type-is": "~1.6.13", "utils-merge": "1.0.0", From 8e14e06ebf45bd88b92ce9e84d4ffed3634c5097 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 24 Jan 2017 07:40:20 -0800 Subject: [PATCH 141/889] deps: serve-static@~1.11.2 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 922bee8576c..ec0568ddf20 100644 --- a/History.md +++ b/History.md @@ -13,6 +13,8 @@ unreleased - deps: http-errors@~1.5.1 - deps: ms@0.7.2 - deps: statuses@~1.3.1 + * deps: serve-static@~1.11.2 + - deps: send@0.14.2 4.14.0 / 2016-06-16 =================== diff --git a/package.json b/package.json index ebe7757b39a..550bda78cec 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "qs": "6.2.0", "range-parser": "~1.2.0", "send": "0.14.2", - "serve-static": "~1.11.1", + "serve-static": "~1.11.2", "type-is": "~1.6.13", "utils-merge": "1.0.0", "vary": "~1.1.0" From dc48f27f607f59b187bd21ab3a84a82d2638f1eb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 26 Jan 2017 22:25:39 -0500 Subject: [PATCH 142/889] deps: update example dependencies --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 550bda78cec..017ef91ac6e 100644 --- a/package.json +++ b/package.json @@ -56,21 +56,21 @@ }, "devDependencies": { "after": "0.8.2", - "body-parser": "~1.15.1", + "body-parser": "1.16.0", "cookie-parser": "~1.4.3", - "ejs": "2.4.2", + "ejs": "2.5.5", + "express-session": "1.15.0", "istanbul": "0.4.5", - "marked": "0.3.5", + "marked": "0.3.6", "method-override": "~2.3.6", "mocha": "3.2.0", "morgan": "~1.7.0", + "multiparty": "4.1.3", "should": "11.1.2", "supertest": "1.2.0", "connect-redis": "~2.4.1", "cookie-session": "~1.2.0", - "express-session": "~1.13.0", "jade": "~1.11.0", - "multiparty": "~4.1.2", "vhost": "~3.0.2" }, "engines": { From 6b506d801a731eb079fc0f442d25a7398b5f1a5b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 26 Jan 2017 22:33:52 -0500 Subject: [PATCH 143/889] examples: fix mvc example to ignore files in controllers dir fixes #3182 --- examples/mvc/lib/boot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/mvc/lib/boot.js b/examples/mvc/lib/boot.js index 78e82db1bfb..a0ca6ec37b1 100644 --- a/examples/mvc/lib/boot.js +++ b/examples/mvc/lib/boot.js @@ -8,6 +8,7 @@ var fs = require('fs'); module.exports = function(parent, options){ var verbose = options.verbose; fs.readdirSync(__dirname + '/../controllers').forEach(function(name){ + if (!fs.statSync(__dirname + '/../controllers/' + name).isDirectory()) return; verbose && console.log('\n %s:', name); var obj = require('./../controllers/' + name); var name = obj.name || name; From c238aca43875fe804df1e7e076dd3f63211f2e02 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 26 Jan 2017 22:48:08 -0500 Subject: [PATCH 144/889] examples: remove big-view example --- examples/big-view/index.js | 31 ------------------------------- examples/big-view/pets.jade | 12 ------------ 2 files changed, 43 deletions(-) delete mode 100644 examples/big-view/index.js delete mode 100644 examples/big-view/pets.jade diff --git a/examples/big-view/index.js b/examples/big-view/index.js deleted file mode 100644 index 0814cbb6e01..00000000000 --- a/examples/big-view/index.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Module dependencies. - */ - -var express = require('../..'); -var logger = require('morgan'); -var app = express(); - -app.set('views', __dirname); -app.set('view engine', 'jade'); - -var pets = []; - -var n = 1000; -while (n--) { - pets.push({ name: 'Tobi', age: 2, species: 'ferret' }); - pets.push({ name: 'Loki', age: 1, species: 'ferret' }); - pets.push({ name: 'Jane', age: 6, species: 'ferret' }); -} - -app.use(logger('dev')); - -app.get('/', function(req, res){ - res.render('pets', { pets: pets }); -}); - -/* istanbul ignore next */ -if (!module.parent) { - app.listen(3000); - console.log('Express started on port 3000'); -} diff --git a/examples/big-view/pets.jade b/examples/big-view/pets.jade deleted file mode 100644 index afb086819c2..00000000000 --- a/examples/big-view/pets.jade +++ /dev/null @@ -1,12 +0,0 @@ -style. - body { - padding: 50px; - font: 16px "Helvetica Neue", Helvetica; - } - -table - for pet in pets - tr - td= pet.name - td= pet.age - td= pet.species \ No newline at end of file From 0d6c64fdfd0bd6031dc23df2c5f9abdf6e4bbb11 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 26 Jan 2017 22:54:05 -0500 Subject: [PATCH 145/889] deps: type-is@~1.6.14 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ec0568ddf20..5d69820a80f 100644 --- a/History.md +++ b/History.md @@ -15,6 +15,8 @@ unreleased - deps: statuses@~1.3.1 * deps: serve-static@~1.11.2 - deps: send@0.14.2 + * deps: type-is@~1.6.14 + - deps: mime-types@~2.1.13 4.14.0 / 2016-06-16 =================== diff --git a/package.json b/package.json index 017ef91ac6e..c8ff63519e1 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "range-parser": "~1.2.0", "send": "0.14.2", "serve-static": "~1.11.2", - "type-is": "~1.6.13", + "type-is": "~1.6.14", "utils-merge": "1.0.0", "vary": "~1.1.0" }, From a856456a956f294d24b37710d0e6971897c97b5b Mon Sep 17 00:00:00 2001 From: Mike Tunnicliffe Date: Mon, 14 Mar 2016 13:11:00 +0000 Subject: [PATCH 146/889] Remove res.vary() (no arguments) signature closes #2943 --- History.md | 3 +++ lib/response.js | 6 ------ test/res.vary.js | 5 ++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/History.md b/History.md index bfd7e58afa8..d1186168610 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,9 @@ This incorporates all changes after 4.13.1 up to 4.14.0. + * remove: + - `res.vary()` (no arguments) -- provide a field name as an argument + 5.0.0-alpha.2 / 2015-07-06 ========================== diff --git a/lib/response.js b/lib/response.js index 6ab51223310..a2c672f5bd9 100644 --- a/lib/response.js +++ b/lib/response.js @@ -808,12 +808,6 @@ res.redirect = function redirect(url) { */ res.vary = function(field){ - // checks for back-compat - if (!field || (Array.isArray(field) && !field.length)) { - deprecate('res.vary(): Provide a field name'); - return this; - } - vary(this, field); return this; diff --git a/test/res.vary.js b/test/res.vary.js index 9a2edd24c09..dbf942ec918 100644 --- a/test/res.vary.js +++ b/test/res.vary.js @@ -6,7 +6,7 @@ var utils = require('./support/utils'); describe('res.vary()', function(){ describe('with no arguments', function(){ - it('should not set Vary', function (done) { + it('should throw error', function (done) { var app = express(); app.use(function (req, res) { @@ -16,8 +16,7 @@ describe('res.vary()', function(){ request(app) .get('/') - .expect(utils.shouldNotHaveHeader('Vary')) - .expect(200, done); + .expect(500, /field.*required/, done) }) }) From 25fdefac45f0569a19fbd0e1baf07737ef232766 Mon Sep 17 00:00:00 2001 From: Mike Tunnicliffe Date: Mon, 14 Mar 2016 11:47:38 +0000 Subject: [PATCH 147/889] Remove res.json(status, obj) signature closes #2939 --- History.md | 1 + lib/response.js | 11 +---------- test/res.json.js | 15 --------------- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/History.md b/History.md index d1186168610..bf28c579a85 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ This incorporates all changes after 4.13.1 up to 4.14.0. * remove: + - `res.json(status, obj)` signature - use `res.status(status).json(obj)` - `res.vary()` (no arguments) -- provide a field name as an argument 5.0.0-alpha.2 / 2015-07-06 diff --git a/lib/response.js b/lib/response.js index a2c672f5bd9..5a3bbbdf924 100644 --- a/lib/response.js +++ b/lib/response.js @@ -203,20 +203,11 @@ res.send = function send(body) { */ res.json = function json(obj) { - var val = obj; - - // support res.json(status, obj) - if (arguments.length === 2) { - deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); - this.statusCode = arguments[0]; - val = arguments[1]; - } - // settings var app = this.app; var replacer = app.get('json replacer'); var spaces = app.get('json spaces'); - var body = stringify(val, replacer, spaces); + var body = stringify(obj, replacer, spaces); // content-type if (!this.get('Content-Type')) { diff --git a/test/res.json.js b/test/res.json.js index 9aab76e5ad4..d8a32a06a5a 100644 --- a/test/res.json.js +++ b/test/res.json.js @@ -145,19 +145,4 @@ describe('res', function(){ }) }) }) - - describe('.json(status, object)', function(){ - it('should respond with json and set the .statusCode', function(done){ - var app = express(); - - app.use(function(req, res){ - res.json(201, { id: 1 }); - }); - - request(app) - .get('/') - .expect('Content-Type', 'application/json; charset=utf-8') - .expect(201, '{"id":1}', done) - }) - }) }) From ab1c9e924e3e0def80224d8ed6cb995978c88ed8 Mon Sep 17 00:00:00 2001 From: Mike Tunnicliffe Date: Mon, 14 Mar 2016 12:01:21 +0000 Subject: [PATCH 148/889] Remove res.jsonp(status, obj) signature closes #2940 --- History.md | 1 + lib/response.js | 11 +---------- test/res.jsonp.js | 15 --------------- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/History.md b/History.md index bf28c579a85..890265c8854 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ This incorporates all changes after 4.13.1 up to 4.14.0. * remove: - `res.json(status, obj)` signature - use `res.status(status).json(obj)` + - `res.jsonp(status, obj)` signature - use `res.status(status).jsonp(obj)` - `res.vary()` (no arguments) -- provide a field name as an argument 5.0.0-alpha.2 / 2015-07-06 diff --git a/lib/response.js b/lib/response.js index 5a3bbbdf924..03c45276f9b 100644 --- a/lib/response.js +++ b/lib/response.js @@ -230,20 +230,11 @@ res.json = function json(obj) { */ res.jsonp = function jsonp(obj) { - var val = obj; - - // support res.jsonp(status, obj) - if (arguments.length === 2) { - deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead'); - this.statusCode = arguments[0]; - val = arguments[1]; - } - // settings var app = this.app; var replacer = app.get('json replacer'); var spaces = app.get('json spaces'); - var body = stringify(val, replacer, spaces); + var body = stringify(obj, replacer, spaces); var callback = this.req.query[app.get('jsonp callback name')]; // content-type diff --git a/test/res.jsonp.js b/test/res.jsonp.js index 6bf49d94aa2..d38932631b7 100644 --- a/test/res.jsonp.js +++ b/test/res.jsonp.js @@ -286,21 +286,6 @@ describe('res', function(){ }) }) - describe('.jsonp(status, object)', function(){ - it('should respond with json and set the .statusCode', function(done){ - var app = express(); - - app.use(function(req, res){ - res.jsonp(201, { id: 1 }); - }); - - request(app) - .get('/') - .expect('Content-Type', 'application/json; charset=utf-8') - .expect(201, '{"id":1}', done) - }) - }) - it('should not override previous Content-Types', function(done){ var app = express(); From 0b39fa2f7c5a68c956019eff01c002968e8966db Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 28 Jan 2017 16:40:40 -0500 Subject: [PATCH 149/889] build: should@11.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c8ff63519e1..d39ac73503b 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "mocha": "3.2.0", "morgan": "~1.7.0", "multiparty": "4.1.3", - "should": "11.1.2", + "should": "11.2.0", "supertest": "1.2.0", "connect-redis": "~2.4.1", "cookie-session": "~1.2.0", From 1f70b76c453e9550545e9a5a91a97d5d0dba3e32 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 28 Jan 2017 16:56:34 -0500 Subject: [PATCH 150/889] build: Node.js@4.7 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3bd122f5d81..924fd00a2aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ node_js: - "1.8" - "2.5" - "3.3" - - "4.6" + - "4.7" - "5.12" - "6.9" sudo: false diff --git a/appveyor.yml b/appveyor.yml index 18d5c4abe02..72f86987907 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ environment: - nodejs_version: "1.8" - nodejs_version: "2.5" - nodejs_version: "3.3" - - nodejs_version: "4.6" + - nodejs_version: "4.7" - nodejs_version: "5.12" - nodejs_version: "6.9" cache: From 0437c513f2dbc8d1dfc5a3e35fe35182bd3a671e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 28 Jan 2017 17:21:24 -0500 Subject: [PATCH 151/889] 4.14.1 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 5d69820a80f..4a706a4d104 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.14.1 / 2017-01-28 +=================== * deps: content-disposition@0.5.2 * deps: finalhandler@0.5.1 diff --git a/package.json b/package.json index d39ac73503b..d499a6df13e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.14.0", + "version": "4.14.1", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 07077c44570b4f4faf27b9c92e6d22e81c0d11fb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 28 Jan 2017 21:54:42 -0500 Subject: [PATCH 152/889] deps: router@~1.1.5 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 63f9321214c..0f3d6ad6823 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,11 @@ This incorporates all changes after 4.13.1 up to 4.14.1. - `res.json(status, obj)` signature - use `res.status(status).json(obj)` - `res.jsonp(status, obj)` signature - use `res.status(status).jsonp(obj)` - `res.vary()` (no arguments) -- provide a field name as an argument + * deps: router@~1.1.5 + - deps: array-flatten@2.0.1 + - deps: methods@~1.1.2 + - deps: parseurl@~1.3.1 + - deps: setprototypeof@1.0.2 5.0.0-alpha.2 / 2015-07-06 ========================== diff --git a/package.json b/package.json index 967a55d5c6d..8a2a70a7f7a 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "proxy-addr": "~1.1.3", "qs": "6.2.0", "range-parser": "~1.2.0", - "router": "~1.1.3", + "router": "~1.1.5", "send": "0.14.2", "serve-static": "~1.11.2", "type-is": "~1.6.14", From ad4d52de29e0bca3ed74ec721773a9e0ac72b420 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 28 Jan 2017 21:55:32 -0500 Subject: [PATCH 153/889] deps: array-flatten@2.1.1 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0f3d6ad6823..380d587354b 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,7 @@ This incorporates all changes after 4.13.1 up to 4.14.1. - `res.json(status, obj)` signature - use `res.status(status).json(obj)` - `res.jsonp(status, obj)` signature - use `res.status(status).jsonp(obj)` - `res.vary()` (no arguments) -- provide a field name as an argument + * deps: array-flatten@2.1.1 * deps: router@~1.1.5 - deps: array-flatten@2.0.1 - deps: methods@~1.1.2 diff --git a/package.json b/package.json index 8a2a70a7f7a..e9d3adaf3a7 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ ], "dependencies": { "accepts": "~1.3.3", - "array-flatten": "2.0.0", + "array-flatten": "2.1.1", "content-disposition": "0.5.2", "content-type": "~1.0.2", "cookie": "0.3.1", From 4b39a01e6ad736bfa4c80ce2a80c787dd1bd41e1 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 28 Jan 2017 21:56:53 -0500 Subject: [PATCH 154/889] deps: path-is-absolute@1.0.1 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 380d587354b..17826794ba4 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,7 @@ This incorporates all changes after 4.13.1 up to 4.14.1. - `res.jsonp(status, obj)` signature - use `res.status(status).jsonp(obj)` - `res.vary()` (no arguments) -- provide a field name as an argument * deps: array-flatten@2.1.1 + * deps: path-is-absolute@1.0.1 * deps: router@~1.1.5 - deps: array-flatten@2.0.1 - deps: methods@~1.1.2 diff --git a/package.json b/package.json index e9d3adaf3a7..7acf0f2475d 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "methods": "~1.1.2", "on-finished": "~2.3.0", "parseurl": "~1.3.1", - "path-is-absolute": "1.0.0", + "path-is-absolute": "1.0.1", "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.3", "qs": "6.2.0", From c8d9223e93ee0c08490e4840f3278314ccb221a5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 28 Jan 2017 22:21:29 -0500 Subject: [PATCH 155/889] 5.0.0-alpha.3 --- History.md | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 17826794ba4..977abaf97fe 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,8 @@ -5.x -=== +5.0.0-alpha.3 / 2017-01-28 +========================== -This incorporates all changes after 4.13.1 up to 4.14.1. +This is the third Express 5.0 alpha release, based off 4.14.1 and includes +changes from 5.0.0-alpha.2. * remove: - `res.json(status, obj)` signature - use `res.status(status).json(obj)` diff --git a/package.json b/package.json index 7acf0f2475d..7063bbc06c1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-alpha.2", + "version": "5.0.0-alpha.3", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 94377f681d66efff100aa2a9086398b0df5688f8 Mon Sep 17 00:00:00 2001 From: Takuma Hanatani Date: Wed, 1 Feb 2017 18:26:16 +0900 Subject: [PATCH 156/889] lint: remove unnecessary semicolon closes #3191 --- lib/request.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/request.js b/lib/request.js index 557d050ffb5..513c9bf3d46 100644 --- a/lib/request.js +++ b/lib/request.js @@ -499,4 +499,4 @@ function defineGetter(obj, name, getter) { enumerable: true, get: getter }); -}; +} From 4f291e7d55d6093ecc4a99d88c785dee22d6d125 Mon Sep 17 00:00:00 2001 From: Tom Hosford Date: Wed, 1 Feb 2017 18:28:26 -0500 Subject: [PATCH 157/889] examples: use res.format in error-pages closes #3195 --- examples/error-pages/index.js | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/examples/error-pages/index.js b/examples/error-pages/index.js index aff985bd674..d1219689f2c 100644 --- a/examples/error-pages/index.js +++ b/examples/error-pages/index.js @@ -60,20 +60,17 @@ app.get('/500', function(req, res, next){ app.use(function(req, res, next){ res.status(404); - // respond with html page - if (req.accepts('html')) { - res.render('404', { url: req.url }); - return; - } - - // respond with json - if (req.accepts('json')) { - res.send({ error: 'Not found' }); - return; - } - - // default to plain-text. send() - res.type('txt').send('Not found'); + res.format({ + html: function () { + res.render('404', { url: req.url }) + }, + json: function () { + res.json({ error: 'Not found' }) + }, + default: function () { + res.type('txt').send('Not found') + } + }) }); // error-handling middleware, take the same form From fb3946f4549395b2f0d3a166ef74eb407d11549b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 4 Feb 2017 20:54:47 -0500 Subject: [PATCH 158/889] lint: fix broken indentation in tests --- test/req.ip.js | 4 ++-- test/res.sendFile.js | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/req.ip.js b/test/req.ip.js index 3ca575e11bd..1cd255216b9 100644 --- a/test/req.ip.js +++ b/test/req.ip.js @@ -79,8 +79,8 @@ describe('req', function(){ res.send(req.ip); }); - var test = request(app).get('/') - test.expect(200, getExpectedClientAddress(test._server), done); + var test = request(app).get('/') + test.expect(200, getExpectedClientAddress(test._server), done) }) }) }) diff --git a/test/res.sendFile.js b/test/res.sendFile.js index ece09ee0731..927d31991f0 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -157,8 +157,8 @@ describe('res', function(){ describe('with "headers" option', function () { it('should accept headers option', function (done) { var headers = { - 'x-success': 'sent', - 'x-other': 'done' + 'x-success': 'sent', + 'x-other': 'done' }; var app = createApp(path.resolve(__dirname, 'fixtures/name.txt'), { headers: headers }); @@ -510,8 +510,8 @@ describe('res', function(){ it('should accept headers option', function(done){ var app = express(); var headers = { - 'x-success': 'sent', - 'x-other': 'done' + 'x-success': 'sent', + 'x-other': 'done' }; app.use(function(req, res){ @@ -730,19 +730,19 @@ describe('res', function(){ }) }) - describe('.sendfile(path, options)', function () { - it('should pass options to send module', function (done) { - var app = express() +describe('.sendfile(path, options)', function () { + it('should pass options to send module', function (done) { + var app = express() - app.use(function (req, res) { - res.sendfile(path.resolve(fixtures, 'name.txt'), { start: 0, end: 1 }) - }) + app.use(function (req, res) { + res.sendfile(path.resolve(fixtures, 'name.txt'), { start: 0, end: 1 }) + }) - request(app) + request(app) .get('/') .expect(200, 'to', done) - }) }) +}) function createApp(path, options, fn) { var app = express(); From abd1de73c14985c884d11fb35aff5f4b17381e23 Mon Sep 17 00:00:00 2001 From: Sebastian Van Sande Date: Mon, 6 Feb 2017 13:09:59 +0100 Subject: [PATCH 159/889] tests: fix misnamed app.router test section fixes #3194 closes #3199 --- test/app.router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/app.router.js b/test/app.router.js index 11e492cbfae..6d41778c038 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -90,7 +90,7 @@ describe('app.router', function(){ }); }) - describe('decode querystring', function(){ + describe('decode params', function () { it('should decode correct params', function(done){ var app = express(); From 034f261fea1eed22d79706ef3c29666acc5fce4a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 15 Feb 2017 23:36:17 -0500 Subject: [PATCH 160/889] examples: use pbkdf2-password module in auth example closes #3207 --- examples/auth/index.js | 6 +++--- examples/auth/pass.js | 48 ------------------------------------------ package.json | 1 + 3 files changed, 4 insertions(+), 51 deletions(-) delete mode 100644 examples/auth/pass.js diff --git a/examples/auth/index.js b/examples/auth/index.js index d110fe28d42..1c3ca217512 100644 --- a/examples/auth/index.js +++ b/examples/auth/index.js @@ -3,8 +3,8 @@ */ var express = require('../..'); -var hash = require('./pass').hash; var bodyParser = require('body-parser'); +var hash = require('pbkdf2-password')() var session = require('express-session'); var app = module.exports = express(); @@ -45,7 +45,7 @@ var users = { // when you create a user, generate a salt // and hash the password ('foobar' is the pass here) -hash('foobar', function(err, salt, hash){ +hash({ password: 'foobar' }, function (err, pass, salt, hash) { if (err) throw err; // store the salt & hash in the "db" users.tj.salt = salt; @@ -63,7 +63,7 @@ function authenticate(name, pass, fn) { // apply the same algorithm to the POSTed password, applying // the hash against the pass / salt, if there is a match we // found the user - hash(pass, user.salt, function(err, hash){ + hash({ password: pass, salt: user.salt }, function (err, pass, salt, hash) { if (err) return fn(err); if (hash == user.hash) return fn(null, user); fn(new Error('invalid password')); diff --git a/examples/auth/pass.js b/examples/auth/pass.js deleted file mode 100644 index fefb25b66a5..00000000000 --- a/examples/auth/pass.js +++ /dev/null @@ -1,48 +0,0 @@ - -// check out https://github.com/tj/node-pwd - -/** - * Module dependencies. - */ - -var crypto = require('crypto'); - -/** - * Bytesize. - */ - -var len = 128; - -/** - * Iterations. ~300ms - */ - -var iterations = 12000; - -/** - * Hashes a password with optional `salt`, otherwise - * generate a salt for `pass` and invoke `fn(err, salt, hash)`. - * - * @param {String} password to hash - * @param {String} optional salt - * @param {Function} callback - * @api public - */ - -exports.hash = function (pwd, salt, fn) { - if (3 == arguments.length) { - crypto.pbkdf2(pwd, salt, iterations, len, function(err, hash){ - fn(err, hash.toString('base64')); - }); - } else { - fn = salt; - crypto.randomBytes(len, function(err, salt){ - if (err) return fn(err); - salt = salt.toString('base64'); - crypto.pbkdf2(pwd, salt, iterations, len, function(err, hash){ - if (err) return fn(err); - fn(null, salt, hash.toString('base64')); - }); - }); - } -}; diff --git a/package.json b/package.json index d499a6df13e..72b266a3afb 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "mocha": "3.2.0", "morgan": "~1.7.0", "multiparty": "4.1.3", + "pbkdf2-password": "1.2.1", "should": "11.2.0", "supertest": "1.2.0", "connect-redis": "~2.4.1", From c48014fde8682f59c2fff8f0ae4655daf8de3b0d Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Wed, 15 Feb 2017 17:14:06 -0800 Subject: [PATCH 161/889] docs: minor fixes to contributing guide --- Contributing.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Contributing.md b/Contributing.md index 2ddfa7a62a4..214e9070126 100644 --- a/Contributing.md +++ b/Contributing.md @@ -1,20 +1,13 @@ -# Node.js Community Contributing Guide 1.0 - -This document describes a very simple process suitable for most projects -in the Node.js ecosystem. Projects are encouraged to adopt this whether they -are hosted in the Node.js Foundation or not. +# Express.js Community Contributing Guide 1.0 The goal of this document is to create a contribution process that: * Encourages new contributions. * Encourages contributors to remain involved. * Avoids unnecessary processes and bureaucracy whenever possible. -* Creates a transparent decision making process which makes it clear how +* Creates a transparent decision making process that makes it clear how contributors can be involved in decision making. -This document is based on much prior art in the Node.js community, io.js, -and the Node.js project. - ## Vocabulary * A **Contributor** is any individual creating or commenting on an issue or pull request. @@ -24,7 +17,7 @@ expertise to resolve rare disputes. # Logging Issues -Log an issue for any question or problem you might have. When in doubt, log an issue, +Log an issue for any question or problem you might have. When in doubt, log an issue, and any additional policies about what to include will be provided in the responses. The only exception is security dislosures which should be sent privately. From 7ef92f8a171aeb7c90260a0ba92015862da1a0eb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 16 Feb 2017 00:42:57 -0500 Subject: [PATCH 162/889] examples: remove semi-broken expose-data-to-client example --- examples/expose-data-to-client/index.js | 64 ------------------- .../expose-data-to-client/views/page.jade | 14 ---- 2 files changed, 78 deletions(-) delete mode 100644 examples/expose-data-to-client/index.js delete mode 100644 examples/expose-data-to-client/views/page.jade diff --git a/examples/expose-data-to-client/index.js b/examples/expose-data-to-client/index.js deleted file mode 100644 index 5dd99df682a..00000000000 --- a/examples/expose-data-to-client/index.js +++ /dev/null @@ -1,64 +0,0 @@ - -var express = require('../..'); -var logger = require('morgan'); -var app = express(); - -app.set('view engine', 'jade'); -app.set('views', __dirname + '/views'); - -function User(name) { - this.private = 'heyyyy'; - this.secret = 'something'; - this.name = name; - this.id = 123; -} - -// You'll probably want to do -// something like this so you -// dont expose "secret" data. - -User.prototype.toJSON = function(){ - return { - id: this.id, - name: this.name - }; -}; - -app.use(logger('dev')); - -// earlier on expose an object -// that we can tack properties on. -// all res.locals props are exposed -// to the templates, so "expose" will -// be present. - -app.use(function(req, res, next){ - res.locals.expose = {}; - // you could alias this as req or res.expose - // to make it shorter and less annoying - next(); -}); - -// pretend we loaded a user - -app.use(function(req, res, next){ - req.user = new User('Tobi'); - next(); -}); - -app.get('/', function(req, res){ - res.redirect('/user'); -}); - -app.get('/user', function(req, res){ - // we only want to expose the user - // to the client for this route: - res.locals.expose.user = req.user; - res.render('page'); -}); - -/* istanbul ignore next */ -if (!module.parent) { - app.listen(3000); - console.log('Express started on port 3000'); -} diff --git a/examples/expose-data-to-client/views/page.jade b/examples/expose-data-to-client/views/page.jade deleted file mode 100644 index 6e58a18afbc..00000000000 --- a/examples/expose-data-to-client/views/page.jade +++ /dev/null @@ -1,14 +0,0 @@ -html - head - title Express - script. - // call this whatever you like, - // or dump them into individual - // props like "var user =" - var data = !{JSON.stringify(expose)} - body - h1 Expose client data - p The following was exposed to the client: - pre - script. - document.write(JSON.stringify(data, null, 2)) \ No newline at end of file From eb326d7ecb52a555f08aba4ebf8744512db1240b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 20 Feb 2017 16:55:15 -0500 Subject: [PATCH 163/889] tests: update req.is tests to run through express --- test/req.is.js | 213 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 139 insertions(+), 74 deletions(-) diff --git a/test/req.is.js b/test/req.is.js index e5adb19de90..a2fce178673 100644 --- a/test/req.is.js +++ b/test/req.is.js @@ -1,103 +1,168 @@ -var express = require('../') - , request = require('supertest'); - -function req(ct) { - var req = { - headers: { - 'content-type': ct, - 'transfer-encoding': 'chunked' - }, - __proto__: express.request - }; - - return req; -} - -describe('req.is()', function(){ - it('should ignore charset', function(){ - req('application/json') - .is('json') - .should.equal('json'); +var express = require('..') +var request = require('supertest') + +describe('req.is()', function () { + describe('when given a mime type', function () { + it('should return the type when matching', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.is('application/json')) + }) + + request(app) + .post('/') + .type('application/json') + .send('{}') + .expect(200, '"application/json"', done) + }) + + it('should return false when not matching', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.is('image/jpeg')) + }) + + request(app) + .post('/') + .type('application/json') + .send('{}') + .expect(200, 'false', done) + }) + + it('should ignore charset', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.is('application/json')) + }) + + request(app) + .post('/') + .type('application/json; charset=UTF-8') + .send('{}') + .expect(200, '"application/json"', done) + }) }) describe('when content-type is not present', function(){ - it('should return false', function(){ - req('') - .is('json') - .should.be.false; + it('should return false', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.is('application/json')) + }) + + request(app) + .post('/') + .send('{}') + .expect(200, 'false', done) }) }) describe('when given an extension', function(){ - it('should lookup the mime type', function(){ - req('application/json') - .is('json') - .should.equal('json'); - - req('text/html') - .is('json') - .should.be.false; - }) - }) + it('should lookup the mime type', function (done) { + var app = express() - describe('when given a mime type', function(){ - it('should match', function(){ - req('application/json') - .is('application/json') - .should.equal('application/json'); + app.use(function (req, res) { + res.json(req.is('json')) + }) - req('image/jpeg') - .is('application/json') - .should.be.false; + request(app) + .post('/') + .type('application/json') + .send('{}') + .expect(200, '"json"', done) }) }) describe('when given */subtype', function(){ - it('should match', function(){ - req('application/json') - .is('*/json') - .should.equal('application/json'); - - req('image/jpeg') - .is('*/json') - .should.be.false; + it('should return the full type when matching', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.is('*/json')) + }) + + request(app) + .post('/') + .type('application/json') + .send('{}') + .expect(200, '"application/json"', done) + }) + + it('should return false when not matching', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.is('*/html')) + }) + + request(app) + .post('/') + .type('application/json') + .send('{}') + .expect(200, 'false', done) }) - describe('with a charset', function(){ - it('should match', function(){ - req('text/html; charset=utf-8') - .is('*/html') - .should.equal('text/html'); + it('should ignore charset', function (done) { + var app = express() - req('text/plain; charset=utf-8') - .is('*/html') - .should.be.false; + app.use(function (req, res) { + res.json(req.is('*/json')) }) + + request(app) + .post('/') + .type('application/json; charset=UTF-8') + .send('{}') + .expect(200, '"application/json"', done) }) }) describe('when given type/*', function(){ - it('should match', function(){ - req('image/png') - .is('image/*') - .should.equal('image/png'); - - req('text/html') - .is('image/*') - .should.be.false; + it('should return the full type when matching', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.is('application/*')) + }) + + request(app) + .post('/') + .type('application/json') + .send('{}') + .expect(200, '"application/json"', done) }) - describe('with a charset', function(){ - it('should match', function(){ - req('text/html; charset=utf-8') - .is('text/*') - .should.equal('text/html'); + it('should return false when not matching', function (done) { + var app = express() - req('something/html; charset=utf-8') - .is('text/*') - .should.be.false; + app.use(function (req, res) { + res.json(req.is('text/*')) }) + + request(app) + .post('/') + .type('application/json') + .send('{}') + .expect(200, 'false', done) + }) + + it('should ignore charset', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.is('application/*')) + }) + + request(app) + .post('/') + .type('application/json; charset=UTF-8') + .send('{}') + .expect(200, '"application/json"', done) }) }) }) From 3e3d35777d3e3081b33ce7d50c8a5c855b450534 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 20 Feb 2017 17:09:21 -0500 Subject: [PATCH 164/889] tests: update req.range tests to run through express --- test/req.range.js | 110 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 27 deletions(-) diff --git a/test/req.range.js b/test/req.range.js index d530d85a645..09459d1e127 100644 --- a/test/req.range.js +++ b/test/req.range.js @@ -1,47 +1,103 @@ var assert = require('assert'); var express = require('..'); - -function req(ret) { - return { - get: function(){ return ret } - , __proto__: express.request - }; -} +var request = require('supertest') describe('req', function(){ describe('.range(size)', function(){ - it('should return parsed ranges', function(){ - var ranges = [{ start: 0, end: 50 }, { start: 51, end: 100 }] - ranges.type = 'bytes' - assert.deepEqual(req('bytes=0-50,51-100').range(120), ranges) + it('should return parsed ranges', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.range(120)) + }) + + request(app) + .get('/') + .set('Range', 'bytes=0-50,51-100') + .expect(200, '[{"start":0,"end":50},{"start":51,"end":100}]', done) }) - it('should cap to the given size', function(){ - var ret = [{ start: 0, end: 74 }]; - ret.type = 'bytes'; - req('bytes=0-100').range(75).should.eql(ret); + it('should cap to the given size', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.range(75)) + }) + + request(app) + .get('/') + .set('Range', 'bytes=0-100') + .expect(200, '[{"start":0,"end":74}]', done) }) - it('should have a .type', function(){ - var ret = [{ start: 0, end: Infinity }]; - ret.type = 'users'; - req('users=0-').range(Infinity).should.eql(ret); + it('should cap to the given size when open-ended', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.range(75)) + }) + + request(app) + .get('/') + .set('Range', 'bytes=0-') + .expect(200, '[{"start":0,"end":74}]', done) }) - it('should return undefined if no range', function(){ - var ret = [{ start: 0, end: 50 }, { start: 60, end: 100 }]; - ret.type = 'bytes'; - assert(req('').range(120) === undefined); + it('should have a .type', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.range(120).type) + }) + + request(app) + .get('/') + .set('Range', 'bytes=0-100') + .expect(200, '"bytes"', done) + }) + + it('should accept any type', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.range(120).type) + }) + + request(app) + .get('/') + .set('Range', 'users=0-2') + .expect(200, '"users"', done) + }) + + it('should return undefined if no range', function (done) { + var app = express() + + app.use(function (req, res) { + res.send(String(req.range(120))) + }) + + request(app) + .get('/') + .expect(200, 'undefined', done) }) }) describe('.range(size, options)', function(){ describe('with "combine: true" option', function(){ - it('should return combined ranges', function(){ - var ranges = [{ start: 0, end: 100 }] - ranges.type = 'bytes' - assert.deepEqual(req('bytes=0-50,51-100').range(120, { combine: true }), ranges) + it('should return combined ranges', function (done) { + var app = express() + + app.use(function (req, res) { + res.json(req.range(120, { + combine: true + })) + }) + + request(app) + .get('/') + .set('Range', 'bytes=0-50,51-100') + .expect(200, '[{"start":0,"end":100}]', done) }) }) }) From f3a47e39a4aeaba36c4881ccafbe12262278e9f4 Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Wed, 15 Feb 2017 17:18:57 -0800 Subject: [PATCH 165/889] docs: update collaborator guide --- Collaborator-Guide.md | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Collaborator-Guide.md b/Collaborator-Guide.md index abbfc109429..7c0d265dd0a 100644 --- a/Collaborator-Guide.md +++ b/Collaborator-Guide.md @@ -6,25 +6,36 @@ Open issues for the expressjs.com website in https://github.com/expressjs/expres ## PRs and Code contributions * Tests must pass. -* Follow existing coding style. +* Follow the [JavaScript Standard Style](http://standardjs.com/). * If you fix a bug, add a test. ## Branches -* Use the `master` branch for bug fixes or minor work that is intended for the current release stream -* Use the correspondingly named branch, e.g. `5.0`, for anything intended for a future release of Express +Use the `master` branch for bug fixes or minor work that is intended for the +current release stream. + +Use the correspondingly named branch, e.g. `5.0`, for anything intended for +a future release of Express. ## Steps for contributing -* [Create an issue](https://github.com/expressjs/express/issues/new) for the bug you want to fix or the feature that you want to add. -* Create your own [fork](https://github.com/expressjs/express) on github, then checkout your fork. -* Write your code in your local copy. It's good practice to create a branch for each new issue you work on, although not compulsory. -* To run the test suite, first install the dependencies by running `npm install`, then run `npm test`. -* If the tests pass, you can commit your changes to your fork and then create a pull request from there. Make sure to reference your issue from the pull request comments by including the issue number e.g. #123. +1. [Create an issue](https://github.com/expressjs/express/issues/new) for the + bug you want to fix or the feature that you want to add. +2. Create your own [fork](https://github.com/expressjs/express) on github, then + checkout your fork. +3. Write your code in your local copy. It's good practice to create a branch for + each new issue you work on, although not compulsory. +4. To run the test suite, first install the dependencies by running `npm install`, + then run `npm test`. +5. If the tests pass, you can commit your changes to your fork and then create + a pull request from there. Make sure to reference your issue from the pull + request comments by including the issue number e.g. `#123`. ## Issues which are questions -We will typically close any vague issues or questions that are specific to some app you are writing. Please double check the docs and other references before being trigger happy with posting a question issue. +We will typically close any vague issues or questions that are specific to some +app you are writing. Please double check the docs and other references before +being trigger happy with posting a question issue. Things that will help get your question issue looked at: @@ -33,4 +44,5 @@ Things that will help get your question issue looked at: * Clear description of the expected result. * Steps you have taken to debug it yourself. -If you post a question and do not outline the above items or make it easy for us to understand and reproduce your issue, it will be closed. +If you post a question and do not outline the above items or make it easy for +us to understand and reproduce your issue, it will be closed. From 1678613db165126306bd79ca6bda310c5cf9bb62 Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Wed, 15 Feb 2017 17:02:13 -0800 Subject: [PATCH 166/889] docs: add guide for writing readmes closes #3209 --- Readme-Guide.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 Readme-Guide.md diff --git a/Readme-Guide.md b/Readme-Guide.md new file mode 100644 index 00000000000..34d4648b9c2 --- /dev/null +++ b/Readme-Guide.md @@ -0,0 +1,125 @@ +# README guidelines + +Every module in the expressjs, pillarjs, and jshttp organizations should have +a README file named `README.md`. The purpose of the README is to: + +- Explain the purpose of the module and how to use it. +- Act as a landing page (both on GitHub and npmjs.com) for the module to help + people find it via search. Middleware module READMEs are also incorporated + into https://expressjs.com/en/resources/middleware.html. +- Encourage community contributions and participation. + +Use the [README template](https://github.com/expressjs/express/wiki/README-template) +to quickly create a new README file. + +## Top-level items + +**Badges** (optional): At the very top (with no subheading), include any +applicable badges, such as npm version/downloads, build status, test coverage, +and so on. Badges should resolve properly (not display a broken image). + +Possible badges include: +- npm version: `[![NPM Version][npm-image]][npm-url]` +- npm downloads: `[![NPM Downloads][downloads-image]][downloads-url]` +- Build status: `[![Build Status][travis-image]][travis-url]` +- Test coverage: `[![Test Coverage][coveralls-image]][coveralls-url]` +- Tips: `[![Gratipay][gratipay-image]][gratipay-url]` + +**Summary**: Following badges, provide a one- or two-sentence description of +what the module does. This should be the same as the npmjs.org blurb (which +comes from the description property of `package.json`). Since npm doesn't +handle markdown for the blurb, avoid using markdown in the summary sentence. + +**TOC** (Optional): For longer READMEs, provide a table of contents that has +a relative link to each section. A tool such as +[doctoc](https://www.npmjs.com/package/doctoc) makes it very easy to generate +a TOC. + +## Overview + +Optionally, include a section of one or two paragraphs with more high-level +information on what the module does, what problems it solves, why one would +use it and how. Don't just repeat what's in the summary. + +## Installation + +Required. This section is typically just: + +```sh +$ npm install module-name +``` + +But include any other steps or requirements. + +NOTE: Use the `sh` code block to make the shell command display properly on +the website. + +## Basic use + +- Provide a general description of how to use the module with code sample. + Include any important caveats or restrictions. +- Explain the most common use cases. +- Optional: a simple "hello world" type example (where applicable). This + example is in addition to the more comprehensive [example section](#examples) + later. + +## API + +Provide complete API documentation. + +Formatting conventions: Each function is listed in a 3rd-level heading (`###`), +like this: + +``` +### Function_name(arg, options [, optional_arg] ... ) +``` + +**Options objects** + +For arguments that are objects (for example, options object), describe the +properties in a table, as follows. This matches the formatting used in the +[Express API docs](https://expressjs.com/en/4x/api.html). + +|Property | Description | Type | Default| +|----------|-----------|------------|-------------| +|Name of the property in `monospace`. | Brief description | String, Number, Boolean, etc. | If applicable.| + +If all the properties are required (i.e. there are no defaults), then you +can omit the default column. + +Instead of very lengthy descriptions, link out to subsequent paragraphs for +more detailed explanation of specific cases (e.g. "When this property is set +to 'foobar', xyz happens; see <link to following section >.) + +If there are options properties that are themselves options, use additional +tables. See [`trust proxy` and `etag` properties](https://expressjs.com/en/4x/api.html#app.settings.table). + +## Examples + +Every README should have at least one example; ideally more. For code samples, +be sure to use the `js` code block, for proper display in the website, e.g.: + +```js +var csurf = require('csurf') +... +``` + +## Tests + +What tests are included. + +How to run them. + +The convention for running tests is `npm test`. All our projects should follow +this convention. + +## Contributors + +Names of module "owners" (lead developers) and other developers who have +contributed. + +## License + +Link to the license, with a short description of what it is, e.g. "MIT" or +whatever. Ideally, avoid putting the license text directly in the README; link +to it instead. From 4420a7bd94f811e4e40caa5fcf5b67ecae779d2f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 20 Feb 2017 18:25:42 -0500 Subject: [PATCH 167/889] docs: update link to expressjs.com website repo --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index e9bfaeba20d..0ddc68fdc9a 100644 --- a/Readme.md +++ b/Readme.md @@ -37,7 +37,7 @@ $ npm install express ## Docs & Community - * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/strongloop/expressjs.com)] + * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)] * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC * [Github Organization](https://github.com/expressjs) for Official Middleware & Modules * Visit the [Wiki](https://github.com/expressjs/express/wiki) From 1a99bb051947fbf06b6b415bba06f8c83247c0d1 Mon Sep 17 00:00:00 2001 From: Mike Tunnicliffe Date: Mon, 15 Feb 2016 17:25:35 +0000 Subject: [PATCH 168/889] docs: add release guide closes #2857 closes #2890 --- Release-Process.md | 186 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 Release-Process.md diff --git a/Release-Process.md b/Release-Process.md new file mode 100644 index 00000000000..ae740972f77 --- /dev/null +++ b/Release-Process.md @@ -0,0 +1,186 @@ +# Express Release Process + +This document contains the technical aspects of the Express release process. The +intended audience is those who have been authorized by the Express Technical +Committee (TC) to create, promote and sign official release builds for Express, +as npm packages hosted on https://npmjs.com/package/express. + +## Who can make releases? + +Release authorization is given by the Express TC. Once authorized, an individual +must have the following access permissions: + +### 1. Github release access + +The individual making the release will need to be a member of the +expressjs/express team with Write permission level so they are able to tag the +release commit and push changes to the expressjs/express repository +(see Steps 4 and 5). + +### 2. npmjs.com release access + +The individual making the release will need to be made an owner on the +`express` package on npmjs.com so they are able to publish the release +(see Step 6). + +## How to publish a release + +Before publishing, the following preconditions should be met: + +- A release proposal issue or tracking pull request (see "Proposal branch" + below) will exist documenting: + - the proposed changes + - the type of release: patch, minor or major + - the version number (according to semantic versioning - http://semver.org) +- The proposed changes should be complete. + +There are two main release flows: patch and non-patch. + +The patch flow is for making **patch releases**. As per semantic versioning, +patch releases are for simple changes, eg: typo fixes, patch dependency updates, +and simple/low-risk bug fixes. Every other type of change is made via the +non-patch flow. + +### Branch terminology + +"Master branch" + +- There is a branch in git used for the current major version of Express, named + `master`. +- This branch contains the completed commits for the next patch release of the + current major version. +- Releases for the current major version are published from this branch. + +"Version branch" + +- For any given major version of Express (current, previous or next) there is + a branch in git for that release named `.x` (eg: `4.x`). +- This branch points to the commit of the latest tag for the given major version. + +"Release branch" + +- For any given major version of Express, there is a branch used for publishing + releases. +- For the current major version of Express, the release branch is the + "Master branch" named `master`. +- For all other major versions of Express, the release branch is the + "Version branch" named `.x`. + +"Proposal branch" + +- A branch in git representing a proposed new release of Express. This can be a + minor or major release, named `.0` for a major release, + `.` for a minor release. +- A tracking pull request should exist to document the proposed release, + targeted at the appropriate release branch. Prior to opening the tracking + pull request the content of the release may have be discussed in an issue. +- This branch contains the commits accepted so far that implement the proposal + in the tracking pull request. + +### Patch flow + +In the patch flow, simple changes are committed to the release branch which +acts as an ever-present branch for the next patch release of the associated +major version of Express. + +The release branch is usually kept in a state where it is ready to release. +Releases are made when sufficient time or change has been made to warrant it. +This is usually proposed and decided using a github issue. + +### Non-patch flow + +In the non-patch flow, changes are committed to a temporary proposal branch +created specifically for that release proposal. The branch is based on the +most recent release of the major version of Express that the release targets. + +Releases are made when all the changes on a proposal branch are complete and +approved. This is done by merging the proposal branch into the release branch +(using a fast-forward merge), tagging it with the new version number and +publishing the release package to npmjs.com. + +### Flow + +Below is a detailed description of the steps to publish a release. + +#### Step 1. Check the release is ready to publish + +Check any relevant information to ensure the release is ready, eg: any +milestone, label, issue or tracking pull request for the release. The release +is ready when all proposed code, tests and documentation updates are complete +(either merged, closed or re-targeted to another release). + +#### Step 2. (Non-patch flow only) Merge the proposal branch into the release branch + +In the patch flow: skip this step. + +In the non-patch flow: +```sh +$ git checkout +$ git merge --ff-only +``` + + - see "Release branch" of "Branches" above. + - see "Proposal branch" of "Non-patch flow" above. + +**NOTE:** You may need to rebase the proposal branch to allow a fast-forward + merge. Using a fast-forward merge keeps the history clean as it does + not introduce merge commits. + +### Step 3. Update the History.md and package.json to the new version number + +The changes so far for the release should already be documented under the +"unreleased" section at the top of the History.md file, as per the usual +development practice. Change "unreleased" to the new release version / date. +Example diff fragment: + +```diff +-unreleased +-========== ++4.13.3 / 2015-08-02 ++=================== +``` + +The version property in the package.json should already contain the version of +the previous release. Change it to the new release version. + +Commit these changes together under a single commit with the message set to +the new release version (eg: `4.13.3`): + +```sh +$ git checkout +<..edit files..> +$ git add History.md package.json +$ git commit -m '' +``` + +### Step 4. Identify and tag the release commit with the new release version + +Create a lightweight tag (rather than an annotated tag) named after the new +release version (eg: `4.13.3`). + +```sh +$ git tag +``` + +### Step 5. Push the release branch changes and tag to github + +The branch and tag should be pushed directly to the main repository +(https://github.com/expressjs/express). + +```sh +$ git push origin +$ git push origin +``` + +### Step 6. Publish to npmjs.com + +Ensure your local working copy is completely clean (no extra or changed files). +You can use `git status` for this purpose. + +```sh +$ npm login +$ npm publish +``` + +**NOTE:** The version number to publish will be picked up automatically from + package.json. From fefd7290376ca865e348d747592543a119a2ff98 Mon Sep 17 00:00:00 2001 From: Pravdomil Date: Sun, 25 Dec 2016 19:28:15 +0100 Subject: [PATCH 169/889] Add debug message when loading view engine closes #3158 --- History.md | 5 +++++ lib/view.js | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 4a706a4d104..e78bd75083d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Add debug message when loading view engine + 4.14.1 / 2017-01-28 =================== diff --git a/lib/view.js b/lib/view.js index 52415d4c28b..1728725d291 100644 --- a/lib/view.js +++ b/lib/view.js @@ -75,7 +75,9 @@ function View(name, options) { if (!opts.engines[this.ext]) { // load engine - opts.engines[this.ext] = require(this.ext.substr(1)).__express; + var mod = this.ext.substr(1) + debug('require "%s"', mod) + opts.engines[this.ext] = require(mod).__express } // store loaded engine From bbed8021c6f634b5eeec52f0f70666f76c78e918 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 16 Feb 2017 00:58:46 -0500 Subject: [PATCH 170/889] build: support Node.js 7.x --- .travis.yml | 1 + appveyor.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 924fd00a2aa..c8220d9b83a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ node_js: - "4.7" - "5.12" - "6.9" + - "7.5" sudo: false cache: directories: diff --git a/appveyor.yml b/appveyor.yml index 72f86987907..4717f2735a8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,6 +8,7 @@ environment: - nodejs_version: "4.7" - nodejs_version: "5.12" - nodejs_version: "6.9" + - nodejs_version: "7.5" cache: - node_modules install: From c63424a0a11a29c067dd0e6ae284d6d821917f32 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 16 Feb 2017 01:22:17 -0500 Subject: [PATCH 171/889] deps: debug@2.6.1 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e78bd75083d..17a6027733e 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,12 @@ unreleased ========== * Add debug message when loading view engine + * deps: debug@2.6.1 + - Allow colors in workers + - Deprecated `DEBUG_FD` environment variable set to `3` or higher + - Fix error when running under React Native + - Use same color for same namespace + - deps: ms@0.7.2 4.14.1 / 2017-01-28 =================== diff --git a/package.json b/package.json index 72b266a3afb..28a07ea618b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "content-type": "~1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", - "debug": "~2.2.0", + "debug": "2.6.1", "depd": "~1.1.0", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", From 906164b204efa1e27af16468ad2cd2b1532212b0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 16 Feb 2017 01:23:51 -0500 Subject: [PATCH 172/889] deps: qs@6.3.1 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 17a6027733e..c46cda0d152 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,9 @@ unreleased - Fix error when running under React Native - Use same color for same namespace - deps: ms@0.7.2 + * deps: qs@6.3.1 + - Fix array parsing from skipping empty values + - Fix compacting nested arrays 4.14.1 / 2017-01-28 =================== diff --git a/package.json b/package.json index 28a07ea618b..dfe12046f7f 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.3", - "qs": "6.2.0", + "qs": "6.3.1", "range-parser": "~1.2.0", "send": "0.14.2", "serve-static": "~1.11.2", From 485b6f86ac43814c2b596f14648f8b6e1a373a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Sanz?= Date: Tue, 4 Aug 2015 00:28:54 +0200 Subject: [PATCH 173/889] perf: improve req.ips performance closes #2723 --- History.md | 1 + lib/request.js | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c46cda0d152..c7410703e72 100644 --- a/History.md +++ b/History.md @@ -11,6 +11,7 @@ unreleased * deps: qs@6.3.1 - Fix array parsing from skipping empty values - Fix compacting nested arrays + * perf: improve `req.ips` performance 4.14.1 / 2017-01-28 =================== diff --git a/lib/request.js b/lib/request.js index 513c9bf3d46..78945e5da7a 100644 --- a/lib/request.js +++ b/lib/request.js @@ -356,7 +356,12 @@ defineGetter(req, 'ip', function ip(){ defineGetter(req, 'ips', function ips() { var trust = this.app.get('trust proxy fn'); var addrs = proxyaddr.all(this, trust); - return addrs.slice(1).reverse(); + + // reverse the order (to farthest -> closest) + // and remove socket address + addrs.reverse().pop() + + return addrs }); /** From 92c859dd055646077607619a2df79243bc8a431f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 18 Feb 2017 22:14:58 -0500 Subject: [PATCH 174/889] deps: finalhandler@~1.0.0 --- History.md | 7 +++++++ package.json | 2 +- test/app.router.js | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index c7410703e72..acad7d288e0 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,13 @@ unreleased - Fix error when running under React Native - Use same color for same namespace - deps: ms@0.7.2 + * deps: finalhandler@~1.0.0 + - Fix exception when `err` cannot be converted to a string + - Fully URL-encode the pathname in the 404 + - Only include the pathname in the 404 message + - Send complete HTML document + - Set `Content-Security-Policy: default-src 'self'` header + - deps: debug@2.6.1 * deps: qs@6.3.1 - Fix array parsing from skipping empty values - Fix compacting nested arrays diff --git a/package.json b/package.json index dfe12046f7f..08aea3e25fb 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.7.0", - "finalhandler": "0.5.1", + "finalhandler": "~1.0.0", "fresh": "0.3.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", diff --git a/test/app.router.js b/test/app.router.js index 6d41778c038..301f9b86af0 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -77,7 +77,7 @@ describe('app.router', function(){ request(app) .get('/') - .expect(404, 'Cannot GET /\n', cb); + .expect(404, cb) request(app) .delete('/') From f2bbd10ae7abadae174b3cf9beb5d944dea4a90b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 18 Feb 2017 22:17:52 -0500 Subject: [PATCH 175/889] deps: update example dependencies --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 08aea3e25fb..10cabda8ceb 100644 --- a/package.json +++ b/package.json @@ -56,15 +56,15 @@ }, "devDependencies": { "after": "0.8.2", - "body-parser": "1.16.0", + "body-parser": "1.16.1", "cookie-parser": "~1.4.3", - "ejs": "2.5.5", - "express-session": "1.15.0", + "ejs": "2.5.6", + "express-session": "1.15.1", "istanbul": "0.4.5", "marked": "0.3.6", - "method-override": "~2.3.6", + "method-override": "2.3.7", "mocha": "3.2.0", - "morgan": "~1.7.0", + "morgan": "1.8.1", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", "should": "11.2.0", From 9f4dbae083264898a65ee2d187b1ae0302814148 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 18 Feb 2017 22:49:04 -0500 Subject: [PATCH 176/889] deps: etag@~1.8.0 --- History.md | 3 +++ package.json | 2 +- test/res.send.js | 16 ++++++++-------- test/utils.js | 16 ++++++++-------- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/History.md b/History.md index acad7d288e0..c63b9a45b60 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,9 @@ unreleased - Fix error when running under React Native - Use same color for same namespace - deps: ms@0.7.2 + * deps: etag@~1.8.0 + - Use SHA1 instead of MD5 for ETag hashing + - Works with FIPS 140-2 OpenSSL configuration * deps: finalhandler@~1.0.0 - Fix exception when `err` cannot be converted to a string - Fully URL-encode the pathname in the 404 diff --git a/package.json b/package.json index 10cabda8ceb..b313d14d67d 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "depd": "~1.1.0", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", - "etag": "~1.7.0", + "etag": "~1.8.0", "finalhandler": "~1.0.0", "fresh": "0.3.0", "merge-descriptors": "1.0.1", diff --git a/test/res.send.js b/test/res.send.js index 719424657c4..f2e7d759c15 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -133,7 +133,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"3e7-VYgCBglFKiDVAcpzPNt4Sg"') + .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"') .expect(200, done); }) @@ -201,7 +201,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"3e7-VYgCBglFKiDVAcpzPNt4Sg"') + .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"') .expect(200, done); }) @@ -355,7 +355,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"c-ZUfd0NJ26qwjlKF4r8qb2g"') + .expect('ETag', 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"') .expect(200, done); }); @@ -371,7 +371,7 @@ describe('res', function(){ request(app) [method]('/') - .expect('ETag', 'W/"c-ZUfd0NJ26qwjlKF4r8qb2g"') + .expect('ETag', 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"') .expect(200, done); }) }); @@ -387,7 +387,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"0-1B2M2Y8AsgTpgAmY7PhCfg"') + .expect('ETag', 'W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"') .expect(200, done); }) @@ -403,7 +403,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"3e7-VYgCBglFKiDVAcpzPNt4Sg"') + .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"') .expect(200, done); }); @@ -485,7 +485,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', '"d-Otu60XkfuuPskIiUxJY4cA"') + .expect('ETag', '"d-HwnTDHB9U/PRbFMN1z1wps51lqk"') .expect(200, done); }) }) @@ -502,7 +502,7 @@ describe('res', function(){ request(app) .get('/') - .expect('ETag', 'W/"d-Otu60XkfuuPskIiUxJY4cA"') + .expect('ETag', 'W/"d-HwnTDHB9U/PRbFMN1z1wps51lqk"') .expect(200, done) }) }) diff --git a/test/utils.js b/test/utils.js index b6731962601..c49019fe126 100644 --- a/test/utils.js +++ b/test/utils.js @@ -5,23 +5,23 @@ var utils = require('../lib/utils'); describe('utils.etag(body, encoding)', function(){ it('should support strings', function(){ utils.etag('express!') - .should.eql('"8-zZdv4imtWD49AHEviejT6A"') + .should.eql('"8-O2uVAFaQ1rZvlKLT14RnuvjPIdg"') }) it('should support utf8 strings', function(){ utils.etag('express❤', 'utf8') - .should.eql('"a-fsFba4IxwQS6h6Umb+FNxw"') + .should.eql('"a-JBiXf7GyzxwcrxY4hVXUwa7tmks"') }) it('should support buffer', function(){ var buf = new Buffer('express!') utils.etag(buf) - .should.eql('"8-zZdv4imtWD49AHEviejT6A"'); + .should.eql('"8-O2uVAFaQ1rZvlKLT14RnuvjPIdg"') }) it('should support empty string', function(){ utils.etag('') - .should.eql('"0-1B2M2Y8AsgTpgAmY7PhCfg"'); + .should.eql('"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"') }) }) @@ -50,23 +50,23 @@ describe('utils.setCharset(type, charset)', function () { describe('utils.wetag(body, encoding)', function(){ it('should support strings', function(){ utils.wetag('express!') - .should.eql('W/"8-zZdv4imtWD49AHEviejT6A"') + .should.eql('W/"8-O2uVAFaQ1rZvlKLT14RnuvjPIdg"') }) it('should support utf8 strings', function(){ utils.wetag('express❤', 'utf8') - .should.eql('W/"a-fsFba4IxwQS6h6Umb+FNxw"') + .should.eql('W/"a-JBiXf7GyzxwcrxY4hVXUwa7tmks"') }) it('should support buffer', function(){ var buf = new Buffer('express!') utils.wetag(buf) - .should.eql('W/"8-zZdv4imtWD49AHEviejT6A"'); + .should.eql('W/"8-O2uVAFaQ1rZvlKLT14RnuvjPIdg"') }) it('should support empty string', function(){ utils.wetag('') - .should.eql('W/"0-1B2M2Y8AsgTpgAmY7PhCfg"'); + .should.eql('W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"') }) }) From cd7d241a5d07eb8fa3df025e96759ee15800e661 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 20 Feb 2017 21:29:19 -0500 Subject: [PATCH 177/889] build: test against Node.js 8.x nightly --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index c8220d9b83a..e6139739cc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,13 @@ node_js: - "5.12" - "6.9" - "7.5" +matrix: + include: + - node_js: "8.0" + env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly" + allow_failures: + # Allow the nightly installs to fail + - env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly" sudo: false cache: directories: From f87abb34934c21926f0315162159e4acf7d7dae8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 20 Feb 2017 21:39:22 -0500 Subject: [PATCH 178/889] Remove usage of res._headers private field closes #3174 --- History.md | 2 ++ lib/request.js | 10 +++++++--- test/req.fresh.js | 2 +- test/req.stale.js | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index c63b9a45b60..755ba7456c4 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,8 @@ unreleased ========== * Add debug message when loading view engine + * Remove usage of `res._headers` private field + - Improves compatibility with Node.js 8 nightly * deps: debug@2.6.1 - Allow colors in workers - Deprecated `DEBUG_FD` environment variable set to `3` or higher diff --git a/lib/request.js b/lib/request.js index 78945e5da7a..fdebbcdbe18 100644 --- a/lib/request.js +++ b/lib/request.js @@ -452,14 +452,18 @@ defineGetter(req, 'host', deprecate.function(function host(){ defineGetter(req, 'fresh', function(){ var method = this.method; - var s = this.res.statusCode; + var res = this.res + var status = res.statusCode // GET or HEAD for weak freshness validation only if ('GET' !== method && 'HEAD' !== method) return false; // 2xx or 304 as per rfc2616 14.26 - if ((s >= 200 && s < 300) || 304 === s) { - return fresh(this.headers, (this.res._headers || {})); + if ((status >= 200 && status < 300) || 304 === status) { + return fresh(this.headers, { + 'etag': res.get('ETag'), + 'last-modified': res.get('Last-Modified') + }) } return false; diff --git a/test/req.fresh.js b/test/req.fresh.js index 0f1aa982ad2..1aa8fa5b217 100644 --- a/test/req.fresh.js +++ b/test/req.fresh.js @@ -36,8 +36,8 @@ describe('req', function(){ it('should return false without response headers', function(done){ var app = express(); + app.disable('x-powered-by') app.use(function(req, res){ - res._headers = null; res.send(req.fresh); }); diff --git a/test/req.stale.js b/test/req.stale.js index c92c5a9fb8d..30c9d05d51c 100644 --- a/test/req.stale.js +++ b/test/req.stale.js @@ -36,8 +36,8 @@ describe('req', function(){ it('should return true without response headers', function(done){ var app = express(); + app.disable('x-powered-by') app.use(function(req, res){ - res._headers = null; res.send(req.stale); }); From a9f15aaefc396b487f18d583b1a3c39ee53e1db6 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Feb 2017 02:11:06 -0500 Subject: [PATCH 179/889] deps: fresh@0.5.0 --- History.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 755ba7456c4..7e90ca96f93 100644 --- a/History.md +++ b/History.md @@ -20,6 +20,18 @@ unreleased - Send complete HTML document - Set `Content-Security-Policy: default-src 'self'` header - deps: debug@2.6.1 + * deps: fresh@0.5.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - perf: delay reading header values until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove duplicate conditional + - perf: remove unnecessary boolean coercions + - perf: skip checking modified time if ETag check failed + - perf: skip parsing `If-None-Match` when no `ETag` header + - perf: use `Date.parse` instead of `new Date` * deps: qs@6.3.1 - Fix array parsing from skipping empty values - Fix compacting nested arrays diff --git a/package.json b/package.json index b313d14d67d..417df65d53a 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "escape-html": "~1.0.3", "etag": "~1.8.0", "finalhandler": "~1.0.0", - "fresh": "0.3.0", + "fresh": "0.5.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", From 034165caeb558560c19a0b3105d913c11999cdd0 Mon Sep 17 00:00:00 2001 From: Wes Date: Mon, 20 Feb 2017 15:32:33 -0600 Subject: [PATCH 180/889] Use statuses instead of http module for status messages closes #3215 --- History.md | 1 + lib/response.js | 10 +++++----- package.json | 1 + test/res.redirect.js | 9 ++++----- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/History.md b/History.md index 7e90ca96f93..a74b4c058b7 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ unreleased * Add debug message when loading view engine * Remove usage of `res._headers` private field - Improves compatibility with Node.js 8 nightly + * Use `statuses` instead of `http` module for status messages * deps: debug@2.6.1 - Allow colors in workers - Deprecated `DEBUG_FD` environment variable set to `3` or higher diff --git a/lib/response.js b/lib/response.js index 6128f450a94..42bc196dfae 100644 --- a/lib/response.js +++ b/lib/response.js @@ -20,12 +20,12 @@ var http = require('http'); var isAbsolute = require('./utils').isAbsolute; var onFinished = require('on-finished'); var path = require('path'); +var statuses = require('statuses') var merge = require('utils-merge'); var sign = require('cookie-signature').sign; var normalizeType = require('./utils').normalizeType; var normalizeTypes = require('./utils').normalizeTypes; var setCharset = require('./utils').setCharset; -var statusCodes = http.STATUS_CODES; var cookie = require('cookie'); var send = require('send'); var extname = path.extname; @@ -129,7 +129,7 @@ res.send = function send(body) { deprecate('res.send(status): Use res.sendStatus(status) instead'); this.statusCode = chunk; - chunk = statusCodes[chunk]; + chunk = statuses[chunk] } switch (typeof chunk) { @@ -334,7 +334,7 @@ res.jsonp = function jsonp(obj) { */ res.sendStatus = function sendStatus(statusCode) { - var body = statusCodes[statusCode] || String(statusCode); + var body = statuses[statusCode] || String(statusCode) this.statusCode = statusCode; this.type('txt'); @@ -876,12 +876,12 @@ res.redirect = function redirect(url) { // Support text/{plain,html} by default this.format({ text: function(){ - body = statusCodes[status] + '. Redirecting to ' + address; + body = statuses[status] + '. Redirecting to ' + address }, html: function(){ var u = escapeHtml(address); - body = '

' + statusCodes[status] + '. Redirecting to ' + u + '

'; + body = '

' + statuses[status] + '. Redirecting to ' + u + '

' }, default: function(){ diff --git a/package.json b/package.json index 417df65d53a..36d83cb9660 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "range-parser": "~1.2.0", "send": "0.14.2", "serve-static": "~1.11.2", + "statuses": "~1.3.1", "type-is": "~1.6.14", "utils-merge": "1.0.0", "vary": "~1.1.0" diff --git a/test/res.redirect.js b/test/res.redirect.js index 9f3bd436763..755bb1c1c6c 100644 --- a/test/res.redirect.js +++ b/test/res.redirect.js @@ -1,5 +1,4 @@ -var http = require('http'); var express = require('..'); var request = require('supertest'); var utils = require('./support/utils'); @@ -104,7 +103,7 @@ describe('res', function(){ .set('Accept', 'text/html') .expect('Content-Type', /html/) .expect('Location', 'http://google.com/') - .expect(302, '

' + http.STATUS_CODES[302] + '. Redirecting to http://google.com

', done); + .expect(302, '

Found. Redirecting to http://google.com

', done) }) it('should escape the url', function(done){ @@ -120,7 +119,7 @@ describe('res', function(){ .set('Accept', 'text/html') .expect('Content-Type', /html/) .expect('Location', '%3Cla\'me%3E') - .expect(302, '

' + http.STATUS_CODES[302] + '. Redirecting to %3Cla'me%3E

', done) + .expect(302, '

Found. Redirecting to %3Cla'me%3E

', done) }) it('should include the redirect type', function(done){ @@ -152,7 +151,7 @@ describe('res', function(){ .set('Accept', 'text/plain, */*') .expect('Content-Type', /plain/) .expect('Location', 'http://google.com/') - .expect(302, http.STATUS_CODES[302] + '. Redirecting to http://google.com', done); + .expect(302, 'Found. Redirecting to http://google.com', done) }) it('should encode the url', function(done){ @@ -168,7 +167,7 @@ describe('res', function(){ .set('Accept', 'text/plain, */*') .expect('Content-Type', /plain/) .expect('Location', 'http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E') - .expect(302, http.STATUS_CODES[302] + '. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E', done) + .expect(302, 'Found. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E', done) }) it('should include the redirect type', function(done){ From 8de1230d039f4391a8c7227e8ce702f280b72e33 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Feb 2017 23:03:20 -0500 Subject: [PATCH 181/889] lint: remove unreachable code --- lib/router/index.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/router/index.js b/lib/router/index.js index dac2514815b..29183d561e1 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -351,11 +351,6 @@ proto.process_params = function process_params(layer, called, req, res, done) { paramIndex = 0; key = keys[i++]; - - if (!key) { - return done(); - } - name = key.name; paramVal = req.params[name]; paramCallbacks = params[name]; From 7bc5f1af968175ddb492cc436a37fc53a8026175 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Feb 2017 23:09:36 -0500 Subject: [PATCH 182/889] lint: consolidate layer match failure path --- lib/router/layer.js | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/router/layer.js b/lib/router/layer.js index fe9210cb9de..e2afb9723db 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -108,23 +108,21 @@ Layer.prototype.handle_request = function handle(req, res, next) { */ Layer.prototype.match = function match(path) { - if (path == null) { - // no path, nothing matches - this.params = undefined; - this.path = undefined; - return false; - } + var match + + if (path != null) { + if (this.regexp.fast_slash) { + // fast path non-ending match for / (everything matches) + this.params = {} + this.path = '' + return true + } - if (this.regexp.fast_slash) { - // fast path non-ending match for / (everything matches) - this.params = {}; - this.path = ''; - return true; + // match the path + match = this.regexp.exec(path) } - var m = this.regexp.exec(path); - - if (!m) { + if (!match) { this.params = undefined; this.path = undefined; return false; @@ -132,15 +130,15 @@ Layer.prototype.match = function match(path) { // store values this.params = {}; - this.path = m[0]; + this.path = match[0] var keys = this.keys; var params = this.params; - for (var i = 1; i < m.length; i++) { + for (var i = 1; i < match.length; i++) { var key = keys[i - 1]; var prop = key.name; - var val = decode_param(m[i]); + var val = decode_param(match[i]) if (val !== undefined || !(hasOwnProperty.call(params, prop))) { params[prop] = val; From 668f545fd4f69cb27dccc6c2d7a21c1637e84933 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Feb 2017 23:42:57 -0500 Subject: [PATCH 183/889] Skip routing when req.url is not set --- History.md | 1 + lib/router/index.js | 24 +++++++++++++++++++----- test/Router.js | 10 ++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index a74b4c058b7..f218fb578b3 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ unreleased * Add debug message when loading view engine * Remove usage of `res._headers` private field - Improves compatibility with Node.js 8 nightly + * Skip routing when `req.url` is not set * Use `statuses` instead of `http` module for status messages * deps: debug@2.6.1 - Allow colors in workers diff --git a/lib/router/index.js b/lib/router/index.js index 29183d561e1..83ad8b500f4 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -137,11 +137,8 @@ proto.handle = function handle(req, res, out) { debug('dispatching %s %s', req.method, req.url); - var search = 1 + req.url.indexOf('?'); - var pathlength = search ? search - 1 : req.url.length; - var fqdn = req.url[0] !== '/' && 1 + req.url.substr(0, pathlength).indexOf('://'); - var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : ''; var idx = 0; + var protohost = getProtohost(req.url) || '' var removed = ''; var slashAdded = false; var paramcalled = {}; @@ -293,7 +290,7 @@ proto.handle = function handle(req, res, out) { req.url = protohost + req.url.substr(protohost.length + removed.length); // Ensure leading slash - if (!fqdn && req.url[0] !== '/') { + if (!protohost && req.url[0] !== '/') { req.url = '/' + req.url; slashAdded = true; } @@ -526,6 +523,23 @@ function getPathname(req) { } } +// Get get protocol + host for a URL +function getProtohost(url) { + if (typeof url !== 'string' || url.length === 0 || url[0] === '/') { + return undefined + } + + var searchIndex = url.indexOf('?') + var pathLength = searchIndex !== -1 + ? searchIndex + : url.length + var fqdnIndex = url.substr(0, pathLength).indexOf('://') + + return fqdnIndex !== -1 + ? url.substr(0, url.indexOf('/', 3 + fqdnIndex)) + : undefined +} + // get type for error message function gettype(obj) { var type = typeof obj; diff --git a/test/Router.js b/test/Router.js index 21cdff2c6c0..41cd149e8eb 100644 --- a/test/Router.js +++ b/test/Router.js @@ -53,6 +53,16 @@ describe('Router', function(){ router.handle({ url: '', method: 'GET' }, {}, done); }); + it('should handle missing URL', function (done) { + var router = new Router() + + router.use(function (req, res) { + throw new Error('should not be called') + }) + + router.handle({ method: 'GET' }, {}, done) + }) + it('should not stack overflow with many registered routes', function(done){ var handler = function(req, res){ res.end(new Error('wrong handler')) }; var router = new Router(); From 12ff56e1e44eb0126d777205b53c31c247ee9293 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 23 Feb 2017 01:52:49 -0500 Subject: [PATCH 184/889] Use Object.create to setup request & response prototypes --- History.md | 1 + lib/express.js | 12 ++++++++++-- lib/request.js | 12 +++++++++--- lib/response.js | 12 +++++++++--- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/History.md b/History.md index f218fb578b3..be606575bef 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ unreleased * Remove usage of `res._headers` private field - Improves compatibility with Node.js 8 nightly * Skip routing when `req.url` is not set + * Use `Object.create` to setup request & response prototypes * Use `statuses` instead of `http` module for status messages * deps: debug@2.6.1 - Allow colors in workers diff --git a/lib/express.js b/lib/express.js index 540c8be6f41..187e4e2d7ca 100644 --- a/lib/express.js +++ b/lib/express.js @@ -41,8 +41,16 @@ function createApplication() { mixin(app, EventEmitter.prototype, false); mixin(app, proto, false); - app.request = { __proto__: req, app: app }; - app.response = { __proto__: res, app: app }; + // expose the prototype that will get set on requests + app.request = Object.create(req, { + app: { configurable: true, enumerable: true, writable: true, value: app } + }) + + // expose the prototype that will get set on responses + app.response = Object.create(res, { + app: { configurable: true, enumerable: true, writable: true, value: app } + }) + app.init(); return app; } diff --git a/lib/request.js b/lib/request.js index fdebbcdbe18..3432e6776fe 100644 --- a/lib/request.js +++ b/lib/request.js @@ -25,11 +25,17 @@ var proxyaddr = require('proxy-addr'); /** * Request prototype. + * @public */ -var req = exports = module.exports = { - __proto__: http.IncomingMessage.prototype -}; +var req = Object.create(http.IncomingMessage.prototype) + +/** + * Module exports. + * @public + */ + +module.exports = req /** * Return request header. diff --git a/lib/response.js b/lib/response.js index 42bc196dfae..6aefe1b1782 100644 --- a/lib/response.js +++ b/lib/response.js @@ -35,11 +35,17 @@ var vary = require('vary'); /** * Response prototype. + * @public */ -var res = module.exports = { - __proto__: http.ServerResponse.prototype -}; +var res = Object.create(http.ServerResponse.prototype) + +/** + * Module exports. + * @public + */ + +module.exports = res /** * Module variables. From 6022567c754a8f1d0b117168b67324da7200fa3c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 23 Feb 2017 01:56:58 -0500 Subject: [PATCH 185/889] Use setprototypeof module to replace __proto__ setting closes #1967 closes #2613 closes #3103 closes #3164 --- History.md | 1 + lib/application.js | 13 +++++++------ lib/middleware/init.js | 11 +++++++++-- lib/router/index.js | 3 ++- package.json | 1 + 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/History.md b/History.md index be606575bef..5e12afa9957 100644 --- a/History.md +++ b/History.md @@ -6,6 +6,7 @@ unreleased - Improves compatibility with Node.js 8 nightly * Skip routing when `req.url` is not set * Use `Object.create` to setup request & response prototypes + * Use `setprototypeof` module to replace `__proto__` setting * Use `statuses` instead of `http` module for status messages * deps: debug@2.6.1 - Allow colors in workers diff --git a/lib/application.js b/lib/application.js index 0ee4def3890..0fe0eb44023 100644 --- a/lib/application.js +++ b/lib/application.js @@ -28,6 +28,7 @@ var deprecate = require('depd')('express'); var flatten = require('array-flatten'); var merge = require('utils-merge'); var resolve = require('path').resolve; +var setPrototyeOf = require('setprototypeof') var slice = Array.prototype.slice; /** @@ -94,10 +95,10 @@ app.defaultConfiguration = function defaultConfiguration() { } // inherit protos - this.request.__proto__ = parent.request; - this.response.__proto__ = parent.response; - this.engines.__proto__ = parent.engines; - this.settings.__proto__ = parent.settings; + setPrototyeOf(this.request, parent.request) + setPrototyeOf(this.response, parent.response) + setPrototyeOf(this.engines, parent.engines) + setPrototyeOf(this.settings, parent.settings) }); // setup locals @@ -227,8 +228,8 @@ app.use = function use(fn) { router.use(path, function mounted_app(req, res, next) { var orig = req.app; fn.handle(req, res, function (err) { - req.__proto__ = orig.request; - res.__proto__ = orig.response; + setPrototyeOf(req, orig.request) + setPrototyeOf(res, orig.response) next(err); }); }); diff --git a/lib/middleware/init.js b/lib/middleware/init.js index f3119ed3a15..328c4a863d9 100644 --- a/lib/middleware/init.js +++ b/lib/middleware/init.js @@ -8,6 +8,13 @@ 'use strict'; +/** + * Module dependencies. + * @private + */ + +var setPrototyeOf = require('setprototypeof') + /** * Initialization middleware, exposing the * request and response to each other, as well @@ -25,8 +32,8 @@ exports.init = function(app){ res.req = req; req.next = next; - req.__proto__ = app.request; - res.__proto__ = app.response; + setPrototyeOf(req, app.request) + setPrototyeOf(res, app.response) res.locals = res.locals || Object.create(null); diff --git a/lib/router/index.js b/lib/router/index.js index 83ad8b500f4..2c4239eba18 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -21,6 +21,7 @@ var debug = require('debug')('express:router'); var deprecate = require('depd')('express'); var flatten = require('array-flatten'); var parseUrl = require('parseurl'); +var setPrototypeOf = require('setprototypeof') /** * Module variables. @@ -47,7 +48,7 @@ var proto = module.exports = function(options) { } // mixin Router class functions - router.__proto__ = proto; + setPrototypeOf(router, proto) router.params = {}; router._params = []; diff --git a/package.json b/package.json index 36d83cb9660..daa1580b2ff 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "range-parser": "~1.2.0", "send": "0.14.2", "serve-static": "~1.11.2", + "setprototypeof": "1.0.3", "statuses": "~1.3.1", "type-is": "~1.6.14", "utils-merge": "1.0.0", From 1b43166fcafceedf50d588abf09224d33cc93507 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 25 Feb 2017 17:53:34 -0500 Subject: [PATCH 186/889] deps: send@0.15.0 --- History.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5e12afa9957..67f353843f2 100644 --- a/History.md +++ b/History.md @@ -39,6 +39,18 @@ unreleased * deps: qs@6.3.1 - Fix array parsing from skipping empty values - Fix compacting nested arrays + * deps: send@0.15.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - Remove usage of `res._headers` private field + - Support `If-Match` and `If-Unmodified-Since` headers + - Use `res.getHeaderNames()` when available + - Use `res.headersSent` when available + - deps: debug@2.6.1 + - deps: etag@~1.8.0 + - deps: fresh@0.5.0 + - deps: http-errors@~1.6.1 * perf: improve `req.ips` performance 4.14.1 / 2017-01-28 diff --git a/package.json b/package.json index daa1580b2ff..9bc995e3205 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "proxy-addr": "~1.1.3", "qs": "6.3.1", "range-parser": "~1.2.0", - "send": "0.14.2", + "send": "0.15.0", "serve-static": "~1.11.2", "setprototypeof": "1.0.3", "statuses": "~1.3.1", From acc4a619d93c86b526af9d850407464f8e404b8f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 25 Feb 2017 19:31:39 -0500 Subject: [PATCH 187/889] deps: serve-static@1.12.0 --- History.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 67f353843f2..14103f267f8 100644 --- a/History.md +++ b/History.md @@ -51,6 +51,17 @@ unreleased - deps: etag@~1.8.0 - deps: fresh@0.5.0 - deps: http-errors@~1.6.1 + * deps: serve-static@1.12.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - Remove usage of `res._headers` private field + - Send complete HTML document in redirect response + - Set default CSP header in redirect response + - Support `If-Match` and `If-Unmodified-Since` headers + - Use `res.getHeaderNames()` when available + - Use `res.headersSent` when available + - deps: send@0.15.0 * perf: improve `req.ips` performance 4.14.1 / 2017-01-28 diff --git a/package.json b/package.json index 9bc995e3205..79b3b0e31c5 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "qs": "6.3.1", "range-parser": "~1.2.0", "send": "0.15.0", - "serve-static": "~1.11.2", + "serve-static": "1.12.0", "setprototypeof": "1.0.3", "statuses": "~1.3.1", "type-is": "~1.6.14", From 1f71fae23be00f44bdfef212cc16868dd8cd5954 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 26 Feb 2017 13:21:18 -0500 Subject: [PATCH 188/889] tests: add lone "*" route tests --- test/app.router.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/app.router.js b/test/app.router.js index 301f9b86af0..1bba62e270f 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -563,6 +563,30 @@ describe('app.router', function(){ }) describe('*', function(){ + it('should capture everything', function (done) { + var app = express() + + app.get('*', function (req, res) { + res.end(req.params[0]) + }) + + request(app) + .get('/user/tobi.json') + .expect('/user/tobi.json', done) + }) + + it('should decore the capture', function (done) { + var app = express() + + app.get('*', function (req, res) { + res.end(req.params[0]) + }) + + request(app) + .get('/user/tobi%20and%20loki.json') + .expect('/user/tobi and loki.json', done) + }) + it('should denote a greedy capture group', function(done){ var app = express(); From 081b811b100a54e26e46aec64e0effd12cdd5053 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 26 Feb 2017 13:32:21 -0500 Subject: [PATCH 189/889] perf: add fast match path for "*" route --- History.md | 1 + lib/router/layer.js | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 14103f267f8..2b20beb7177 100644 --- a/History.md +++ b/History.md @@ -62,6 +62,7 @@ unreleased - Use `res.getHeaderNames()` when available - Use `res.headersSent` when available - deps: send@0.15.0 + * perf: add fast match path for `*` route * perf: improve `req.ips` performance 4.14.1 / 2017-01-28 diff --git a/lib/router/layer.js b/lib/router/layer.js index e2afb9723db..6325df8aff9 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -44,9 +44,9 @@ function Layer(path, options, fn) { this.path = undefined; this.regexp = pathRegexp(path, this.keys = [], opts); - if (path === '/' && opts.end === false) { - this.regexp.fast_slash = true; - } + // set fast path flags + this.regexp.fast_star = path === '*' + this.regexp.fast_slash = path === '/' && opts.end === false } /** @@ -111,13 +111,20 @@ Layer.prototype.match = function match(path) { var match if (path != null) { + // fast path non-ending match for / (any path matches) if (this.regexp.fast_slash) { - // fast path non-ending match for / (everything matches) this.params = {} this.path = '' return true } + // fast path for * (everything matched in a param) + if (this.regexp.fast_star) { + this.params = {'0': decode_param(path)} + this.path = path + return true + } + // match the path match = this.regexp.exec(path) } From 8b6dc6ceec1b36e74ee9c6d362aa04e46237c227 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 26 Feb 2017 13:45:35 -0500 Subject: [PATCH 190/889] Use "%o" in path debug to tell types apart --- History.md | 1 + lib/router/index.js | 2 +- lib/router/layer.js | 2 +- lib/router/route.js | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 2b20beb7177..ed51a7e5b0a 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ unreleased * Remove usage of `res._headers` private field - Improves compatibility with Node.js 8 nightly * Skip routing when `req.url` is not set + * Use `%o` in path debug to tell types apart * Use `Object.create` to setup request & response prototypes * Use `setprototypeof` module to replace `__proto__` setting * Use `statuses` instead of `http` module for status messages diff --git a/lib/router/index.js b/lib/router/index.js index 2c4239eba18..d2ed86e0bc8 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -452,7 +452,7 @@ proto.use = function use(fn) { } // add the middleware - debug('use %s %s', path, fn.name || ''); + debug('use %o %s', path, fn.name || '') var layer = new Layer(path, { sensitive: this.caseSensitive, diff --git a/lib/router/layer.js b/lib/router/layer.js index 6325df8aff9..4dc8e86d4f7 100644 --- a/lib/router/layer.js +++ b/lib/router/layer.js @@ -35,7 +35,7 @@ function Layer(path, options, fn) { return new Layer(path, options, fn); } - debug('new %s', path); + debug('new %o', path) var opts = options || {}; this.handle = fn; diff --git a/lib/router/route.js b/lib/router/route.js index 2788d7b7353..1ec9d50ea0e 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -44,7 +44,7 @@ function Route(path) { this.path = path; this.stack = []; - debug('new %s', path); + debug('new %o', path) // route handlers for various http methods this.methods = {}; @@ -196,7 +196,7 @@ methods.forEach(function(method){ throw new Error(msg); } - debug('%s %s', method, this.path); + debug('%s %o', method, this.path) var layer = Layer('/', {}, handle); layer.method = method; From 51f52901eb1f00571e18d404e10b27310215234c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 26 Feb 2017 13:59:47 -0500 Subject: [PATCH 191/889] Fix case where router.use skipped requests routes did not fixes #3037 --- History.md | 1 + lib/router/index.js | 11 ++++++----- test/Router.js | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index ed51a7e5b0a..bf7764011ba 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ unreleased ========== * Add debug message when loading view engine + * Fix case where `router.use` skipped requests routes did not * Remove usage of `res._headers` private field - Improves compatibility with Node.js 8 nightly * Skip routing when `req.url` is not set diff --git a/lib/router/index.js b/lib/router/index.js index d2ed86e0bc8..917c6002c8b 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -280,12 +280,13 @@ proto.handle = function handle(req, res, out) { } function trim_prefix(layer, layerError, layerPath, path) { - var c = path[layerPath.length]; - if (c && '/' !== c && '.' !== c) return next(layerError); - - // Trim off the part of the url that matches the route - // middleware (.use stuff) needs to have the path stripped if (layerPath.length !== 0) { + // Validate path breaks on a path separator + var c = path[layerPath.length] + if (c && c !== '/' && c !== '.') return next(layerError) + + // Trim off the part of the url that matches the route + // middleware (.use stuff) needs to have the path stripped debug('trim prefix (%s) from url %s', layerPath, req.url); removed = layerPath; req.url = protohost + req.url.substr(protohost.length + removed.length); diff --git a/test/Router.js b/test/Router.js index 41cd149e8eb..01a6e2c472b 100644 --- a/test/Router.js +++ b/test/Router.js @@ -347,6 +347,24 @@ describe('Router', function(){ assert.equal(count, methods.length); done(); }) + + it('should be called for any URL when "*"', function (done) { + var cb = after(4, done) + var router = new Router() + + function no () { + throw new Error('should not be called') + } + + router.all('*', function (req, res) { + res.end() + }) + + router.handle({ url: '/', method: 'GET' }, { end: cb }, no) + router.handle({ url: '/foo', method: 'GET' }, { end: cb }, no) + router.handle({ url: 'foo', method: 'GET' }, { end: cb }, no) + router.handle({ url: '*', method: 'GET' }, { end: cb }, no) + }) }) describe('.use', function() { @@ -363,6 +381,24 @@ describe('Router', function(){ router.use.bind(router, '/', new Date()).should.throw(/requires middleware function.*Date/) }) + it('should be called for any URL', function (done) { + var cb = after(4, done) + var router = new Router() + + function no () { + throw new Error('should not be called') + } + + router.use(function (req, res) { + res.end() + }) + + router.handle({ url: '/', method: 'GET' }, { end: cb }, no) + router.handle({ url: '/foo', method: 'GET' }, { end: cb }, no) + router.handle({ url: 'foo', method: 'GET' }, { end: cb }, no) + router.handle({ url: '*', method: 'GET' }, { end: cb }, no) + }) + it('should accept array of middleware', function(done){ var count = 0; var router = new Router(); From 9722202df964bfbfc0f579e4baeb5a4e1b43b344 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Thu, 12 Nov 2015 16:17:47 -0800 Subject: [PATCH 192/889] Add next("router") to exit from router closes #2241 closes #2371 --- History.md | 1 + lib/router/index.js | 6 ++++++ lib/router/route.js | 6 ++++++ test/app.router.js | 31 +++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+) diff --git a/History.md b/History.md index bf7764011ba..824f2443d3e 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ unreleased ========== * Add debug message when loading view engine + * Add `next("router")` to exit from router * Fix case where `router.use` skipped requests routes did not * Remove usage of `res._headers` private field - Improves compatibility with Node.js 8 nightly diff --git a/lib/router/index.js b/lib/router/index.js index 917c6002c8b..1f426068d7e 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -191,6 +191,12 @@ proto.handle = function handle(req, res, out) { removed = ''; } + // signal to exit router + if (layerError === 'router') { + setImmediate(done, null) + return + } + // no more matching layers if (idx >= stack.length) { setImmediate(done, layerError); diff --git a/lib/router/route.js b/lib/router/route.js index 1ec9d50ea0e..ea82ed29df5 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -112,10 +112,16 @@ Route.prototype.dispatch = function dispatch(req, res, done) { next(); function next(err) { + // signal to exit route if (err && err === 'route') { return done(); } + // signal to exit router + if (err && err === 'router') { + return done(err) + } + var layer = stack[idx++]; if (!layer) { return done(err); diff --git a/test/app.router.js b/test/app.router.js index 1bba62e270f..e838b2e33fc 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -932,6 +932,37 @@ describe('app.router', function(){ }) }) + describe('when next("router") is called', function () { + it('should jump out of router', function (done) { + var app = express() + var router = express.Router() + + function fn (req, res, next) { + res.set('X-Hit', '1') + next('router') + } + + router.get('/foo', fn, function (req, res, next) { + res.end('failure') + }) + + router.get('/foo', function (req, res, next) { + res.end('failure') + }) + + app.use(router) + + app.get('/foo', function (req, res) { + res.end('success') + }) + + request(app) + .get('/foo') + .expect('X-Hit', '1') + .expect(200, 'success', done) + }) + }) + describe('when next(err) is called', function(){ it('should break out of app.router', function(done){ var app = express() From 146a13ede7c81d0131468e99b29d06940727bfea Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Mar 2017 17:15:57 -0500 Subject: [PATCH 193/889] build: Node.js@4.8 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e6139739cc4..bb466557163 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ node_js: - "1.8" - "2.5" - "3.3" - - "4.7" + - "4.8" - "5.12" - "6.9" - "7.5" diff --git a/appveyor.yml b/appveyor.yml index 4717f2735a8..659dbd1d3f7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ environment: - nodejs_version: "1.8" - nodejs_version: "2.5" - nodejs_version: "3.3" - - nodejs_version: "4.7" + - nodejs_version: "4.8" - nodejs_version: "5.12" - nodejs_version: "6.9" - nodejs_version: "7.5" From 72475543bcf61868e32ba2f4053cf42707a4b55d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Mar 2017 17:16:09 -0500 Subject: [PATCH 194/889] build: Node.js@6.10 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bb466557163..0c4df4972da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ node_js: - "3.3" - "4.8" - "5.12" - - "6.9" + - "6.10" - "7.5" matrix: include: diff --git a/appveyor.yml b/appveyor.yml index 659dbd1d3f7..4645573fcd7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ environment: - nodejs_version: "3.3" - nodejs_version: "4.8" - nodejs_version: "5.12" - - nodejs_version: "6.9" + - nodejs_version: "6.10" - nodejs_version: "7.5" cache: - node_modules From f59de6ae3d0c142a95e4f47dedf9770efe198ae6 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Mar 2017 17:16:21 -0500 Subject: [PATCH 195/889] build: Node.js@7.7 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0c4df4972da..824e6b2a17a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ node_js: - "4.8" - "5.12" - "6.10" - - "7.5" + - "7.7" matrix: include: - node_js: "8.0" diff --git a/appveyor.yml b/appveyor.yml index 4645573fcd7..1b399ce4ab0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ environment: - nodejs_version: "4.8" - nodejs_version: "5.12" - nodejs_version: "6.10" - - nodejs_version: "7.5" + - nodejs_version: "7.7" cache: - node_modules install: From 7f96896f67ba14e5a2f5be4fc5496584ce682b24 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Mar 2017 17:17:50 -0500 Subject: [PATCH 196/889] deps: update example dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 79b3b0e31c5..cca0f7f4533 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ }, "devDependencies": { "after": "0.8.2", - "body-parser": "1.16.1", + "body-parser": "1.17.0", "cookie-parser": "~1.4.3", "ejs": "2.5.6", "express-session": "1.15.1", From 504a51c040f22c80c7e52377c0ef00b1c8b2a76b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Mar 2017 17:22:18 -0500 Subject: [PATCH 197/889] 4.15.0 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 824f2443d3e..24f0c2e41f7 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.15.0 / 2017-03-01 +=================== * Add debug message when loading view engine * Add `next("router")` to exit from router diff --git a/package.json b/package.json index cca0f7f4533..cc6f36633fe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.14.1", + "version": "4.15.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 6d9b1279899cbc1fbaa2b98a2ab118a2c3081778 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Mar 2017 17:44:13 -0500 Subject: [PATCH 198/889] build: Node.js@7.6 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 824e6b2a17a..1230c7e2f95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ node_js: - "4.8" - "5.12" - "6.10" - - "7.7" + - "7.6" matrix: include: - node_js: "8.0" diff --git a/appveyor.yml b/appveyor.yml index 1b399ce4ab0..b4bb184dd8f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ environment: - nodejs_version: "4.8" - nodejs_version: "5.12" - nodejs_version: "6.10" - - nodejs_version: "7.7" + - nodejs_version: "7.6" cache: - node_modules install: From 4012846d2534addd8de0b0c237cd63ada104109a Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Sun, 26 Feb 2017 13:38:26 +0000 Subject: [PATCH 199/889] examples: use static assets in search example closes #3224 --- examples/search/index.js | 11 +---------- examples/search/{ => public}/client.js | 0 examples/search/public/index.html | 20 ++++++++++++++++++++ examples/search/search.jade | 15 --------------- 4 files changed, 21 insertions(+), 25 deletions(-) rename examples/search/{ => public}/client.js (100%) create mode 100644 examples/search/public/index.html delete mode 100644 examples/search/search.jade diff --git a/examples/search/index.js b/examples/search/index.js index d614ac24076..8027635f19e 100644 --- a/examples/search/index.js +++ b/examples/search/index.js @@ -15,8 +15,7 @@ var db = redis.createClient(); var app = express(); -app.set('view engine', 'jade'); -app.set('views', __dirname); +app.use(express.static(__dirname + '/public')); // populate search @@ -26,14 +25,6 @@ db.sadd('ferret', 'jane'); db.sadd('cat', 'manny'); db.sadd('cat', 'luna'); -/** - * GET the search page. - */ - -app.get('/', function(req, res){ - res.render('search'); -}); - /** * GET search for :query. */ diff --git a/examples/search/client.js b/examples/search/public/client.js similarity index 100% rename from examples/search/client.js rename to examples/search/public/client.js diff --git a/examples/search/public/index.html b/examples/search/public/index.html new file mode 100644 index 00000000000..4a5540fdf3a --- /dev/null +++ b/examples/search/public/index.html @@ -0,0 +1,20 @@ + + + + + Search example + + + +

Search

+

Try searching for "ferret" or "cat".

+ +
+  
+
+
diff --git a/examples/search/search.jade b/examples/search/search.jade
deleted file mode 100644
index 37d77e434c6..00000000000
--- a/examples/search/search.jade
+++ /dev/null
@@ -1,15 +0,0 @@
-doctype
-html
-  head
-    title Search example
-    style.
-      body {
-        font: 14px "Helvetica Neue", Helvetica;
-        padding: 50px;
-      }
-  body
-    h2 Search
-    p Try searching for "ferret" or "cat".
-    input(type='search')
-    pre
-    script(src='http://github.com/client.js')

From 06f423d4f56bad350690ebf0f9fe7b79961dbc96 Mon Sep 17 00:00:00 2001
From: Wes 
Date: Mon, 20 Feb 2017 18:34:45 -0600
Subject: [PATCH 200/889] Remove Express 3.x middleware error stubs

closes #3217
---
 History.md      |  2 ++
 lib/express.js  | 34 ----------------------------------
 test/exports.js |  8 --------
 3 files changed, 2 insertions(+), 42 deletions(-)

diff --git a/History.md b/History.md
index 1bea61a705d..7f522d1a73a 100644
--- a/History.md
+++ b/History.md
@@ -3,6 +3,8 @@
 
 This incorporates all changes after 4.14.1 up to 4.15.0.
 
+  * remove:
+    - Remove Express 3.x middleware error stubs
   * deps: router@~1.3.0
     - Add `next("router")` to exit from router
     - Fix case where `router.use` skipped requests routes did not
diff --git a/lib/express.js b/lib/express.js
index 04dde09d56a..688f4295128 100644
--- a/lib/express.js
+++ b/lib/express.js
@@ -74,37 +74,3 @@ exports.Router = Router;
  */
 
 exports.static = require('serve-static');
-
-/**
- * Replace removed middleware with an appropriate error message.
- */
-
-[
-  'json',
-  'urlencoded',
-  'bodyParser',
-  'compress',
-  'cookieSession',
-  'session',
-  'logger',
-  'cookieParser',
-  'favicon',
-  'responseTime',
-  'errorHandler',
-  'timeout',
-  'methodOverride',
-  'vhost',
-  'csrf',
-  'directory',
-  'limit',
-  'multipart',
-  'staticCache',
-  'query',
-].forEach(function (name) {
-  Object.defineProperty(exports, name, {
-    get: function () {
-      throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.');
-    },
-    configurable: true
-  });
-});
diff --git a/test/exports.js b/test/exports.js
index d34a7b1cf3e..d2d4e07e194 100644
--- a/test/exports.js
+++ b/test/exports.js
@@ -50,12 +50,4 @@ describe('exports', function(){
     .get('/')
     .expect('bar', done);
   })
-
-  it('should throw on old middlewares', function(){
-    var error;
-    try { express.bodyParser; } catch (e) { error = e; }
-    should(error).have.property('message');
-    error.message.should.containEql('middleware');
-    error.message.should.containEql('bodyParser');
-  })
 })

From a3a9166c521008576da724e83221c05a1aa92245 Mon Sep 17 00:00:00 2001
From: Douglas Christopher Wilson 
Date: Wed, 1 Mar 2017 18:51:29 -0500
Subject: [PATCH 201/889] 5.0.0-alpha.4

---
 History.md   | 7 ++++---
 package.json | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/History.md b/History.md
index 7f522d1a73a..54dafd3b02a 100644
--- a/History.md
+++ b/History.md
@@ -1,7 +1,8 @@
-5.x
-===
+5.0.0-alpha.4 / 2017-03-01
+==========================
 
-This incorporates all changes after 4.14.1 up to 4.15.0.
+This is the fourth Express 5.0 alpha release, based off 4.15.0 and includes
+changes from 5.0.0-alpha.3.
 
   * remove:
     - Remove Express 3.x middleware error stubs
diff --git a/package.json b/package.json
index 56a58c8e8dc..60abd540cac 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "express",
   "description": "Fast, unopinionated, minimalist web framework",
-  "version": "5.0.0-alpha.3",
+  "version": "5.0.0-alpha.4",
   "author": "TJ Holowaychuk ",
   "contributors": [
     "Aaron Heckmann ",

From b4550fbe7a154d3fb9e935935e266a9eca9a4d69 Mon Sep 17 00:00:00 2001
From: Jamie Barton 
Date: Sun, 26 Feb 2017 13:12:35 +0000
Subject: [PATCH 202/889] Use ejs instead of jade within engine jsdoc

closes #3222
---
 lib/application.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/application.js b/lib/application.js
index 0fe0eb44023..21a81ee9efe 100644
--- a/lib/application.js
+++ b/lib/application.js
@@ -262,9 +262,9 @@ app.route = function route(path) {
  *
  * By default will `require()` the engine based on the
  * file extension. For example if you try to render
- * a "foo.jade" file Express will invoke the following internally:
+ * a "foo.ejs" file Express will invoke the following internally:
  *
- *     app.engine('jade', require('jade').__express);
+ *     app.engine('ejs', require('ejs').__express);
  *
  * For engines that do not provide `.__express` out of the box,
  * or if you wish to "map" a different extension to the template engine

From 7027b37764050c550366e808ea84fee1c58233ed Mon Sep 17 00:00:00 2001
From: Jianru Lin 
Date: Wed, 1 Mar 2017 10:38:13 +0800
Subject: [PATCH 203/889] lint: remove unused err argument

closes #3228
---
 lib/router/index.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/router/index.js b/lib/router/index.js
index 1f426068d7e..51db4c28ff9 100644
--- a/lib/router/index.js
+++ b/lib/router/index.js
@@ -626,7 +626,7 @@ function restore(fn, obj) {
     vals[i] = obj[props[i]];
   }
 
-  return function(err){
+  return function () {
     // restore vals
     for (var i = 0; i < props.length; i++) {
       obj[props[i]] = vals[i];

From dc8acc8676bed4aa4afa391ee312baa497d680e2 Mon Sep 17 00:00:00 2001
From: Douglas Christopher Wilson 
Date: Sun, 5 Mar 2017 00:04:47 -0500
Subject: [PATCH 204/889] tests: use supertest expect for simple assertions

---
 test/app.param.js         |  9 ++++-----
 test/app.router.js        |  4 ++--
 test/req.signedCookies.js |  6 +-----
 test/res.clearCookie.js   | 14 ++++----------
 test/res.cookie.js        | 28 ++++++++--------------------
 5 files changed, 19 insertions(+), 42 deletions(-)

diff --git a/test/app.param.js b/test/app.param.js
index 30885bcdc89..c7a375418cd 100644
--- a/test/app.param.js
+++ b/test/app.param.js
@@ -29,8 +29,8 @@ describe('app', function(){
 
       request(app)
       .get('/user/tj')
-      .end(function(err, res){
-        res.text.should.equal('tj');
+      .expect(200, 'tj', function (err) {
+        if (err) return done(err)
         request(app)
         .get('/user/123')
         .expect(404, done);
@@ -69,9 +69,8 @@ describe('app', function(){
 
       request(app)
       .get('/user/123')
-      .end(function(err, res){
-        res.text.should.equal('123');
-
+      .expect(200, '123', function (err) {
+        if (err) return done(err)
         request(app)
         .get('/post/123')
         .expect('123', done);
diff --git a/test/app.router.js b/test/app.router.js
index e838b2e33fc..95680f9139c 100644
--- a/test/app.router.js
+++ b/test/app.router.js
@@ -539,8 +539,8 @@ describe('app.router', function(){
 
     request(app)
     .get('/user/10')
-    .end(function(err, res){
-      res.statusCode.should.equal(200);
+    .expect(200, function (err) {
+      if (err) return done(err)
       request(app)
       .get('/user/tj')
       .expect(404, done);
diff --git a/test/req.signedCookies.js b/test/req.signedCookies.js
index 111a0f77df8..73880b01b4c 100644
--- a/test/req.signedCookies.js
+++ b/test/req.signedCookies.js
@@ -28,11 +28,7 @@ describe('req', function(){
         request(app)
         .get('/')
         .set('Cookie', cookie)
-        .end(function(err, res){
-          if (err) return done(err);
-          res.body.should.eql({ obj: { foo: 'bar' } });
-          done();
-        });
+        .expect(200, { obj: { foo: 'bar' } }, done)
       });
     })
   })
diff --git a/test/res.clearCookie.js b/test/res.clearCookie.js
index 92c9d049f0d..4822057e926 100644
--- a/test/res.clearCookie.js
+++ b/test/res.clearCookie.js
@@ -13,11 +13,8 @@ describe('res', function(){
 
       request(app)
       .get('/')
-      .end(function(err, res){
-        var val = 'sid=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT';
-        res.header['set-cookie'].should.eql([val]);
-        done();
-      })
+      .expect('Set-Cookie', 'sid=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT')
+      .expect(200, done)
     })
   })
 
@@ -31,11 +28,8 @@ describe('res', function(){
 
       request(app)
       .get('/')
-      .end(function(err, res){
-        var val = 'sid=; Path=/admin; Expires=Thu, 01 Jan 1970 00:00:00 GMT';
-        res.header['set-cookie'].should.eql([val]);
-        done();
-      })
+      .expect('Set-Cookie', 'sid=; Path=/admin; Expires=Thu, 01 Jan 1970 00:00:00 GMT')
+      .expect(200, done)
     })
   })
 })
diff --git a/test/res.cookie.js b/test/res.cookie.js
index 543af99dcdd..4eeaaf094ad 100644
--- a/test/res.cookie.js
+++ b/test/res.cookie.js
@@ -16,11 +16,8 @@ describe('res', function(){
 
       request(app)
       .get('/')
-      .end(function(err, res){
-        var val = ['user=' + encodeURIComponent('j:{"name":"tobi"}') + '; Path=/'];
-        res.headers['set-cookie'].should.eql(val);
-        done();
-      })
+      .expect('Set-Cookie', 'user=j%3A%7B%22name%22%3A%22tobi%22%7D; Path=/')
+      .expect(200, done)
     })
   })
 
@@ -34,11 +31,8 @@ describe('res', function(){
 
       request(app)
       .get('/')
-      .end(function(err, res){
-        var val = ['name=tobi; Path=/'];
-        res.headers['set-cookie'].should.eql(val);
-        done();
-      })
+      .expect('Set-Cookie', 'name=tobi; Path=/')
+      .expect(200, done)
     })
 
     it('should allow multiple calls', function(done){
@@ -72,11 +66,8 @@ describe('res', function(){
 
       request(app)
       .get('/')
-      .end(function(err, res){
-        var val = ['name=tobi; Path=/; HttpOnly; Secure'];
-        res.headers['set-cookie'].should.eql(val);
-        done();
-      })
+      .expect('Set-Cookie', 'name=tobi; Path=/; HttpOnly; Secure')
+      .expect(200, done)
     })
 
     describe('maxAge', function(){
@@ -178,11 +169,8 @@ describe('res', function(){
 
         request(app)
         .get('/')
-        .end(function(err, res){
-          var val = ['name=s%3Atobi.xJjV2iZ6EI7C8E5kzwbfA9PVLl1ZR07UTnuTgQQ4EnQ; Path=/'];
-          res.headers['set-cookie'].should.eql(val);
-          done();
-        })
+        .expect('Set-Cookie', 'name=s%3Atobi.xJjV2iZ6EI7C8E5kzwbfA9PVLl1ZR07UTnuTgQQ4EnQ; Path=/')
+        .expect(200, done)
       })
     })
   })

From c0089d971b9880b17c652bfde95cc4f36fd8aaf8 Mon Sep 17 00:00:00 2001
From: Douglas Christopher Wilson 
Date: Sun, 5 Mar 2017 00:06:59 -0500
Subject: [PATCH 205/889] deps: send@0.15.1

---
 History.md   | 7 +++++++
 package.json | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/History.md b/History.md
index 24f0c2e41f7..aadd7ece046 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,10 @@
+unreleased
+==========
+
+  * deps: send@0.15.1
+    - Fix issue when `Date.parse` does not return `NaN` on invalid date
+    - Fix strict violation in broken environments
+
 4.15.0 / 2017-03-01
 ===================
 
diff --git a/package.json b/package.json
index cc6f36633fe..aea1a83bc10 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,7 @@
     "proxy-addr": "~1.1.3",
     "qs": "6.3.1",
     "range-parser": "~1.2.0",
-    "send": "0.15.0",
+    "send": "0.15.1",
     "serve-static": "1.12.0",
     "setprototypeof": "1.0.3",
     "statuses": "~1.3.1",

From 67168fe231445a82dc1e8dde6a93ee9441be28c1 Mon Sep 17 00:00:00 2001
From: Douglas Christopher Wilson 
Date: Sun, 5 Mar 2017 00:08:16 -0500
Subject: [PATCH 206/889] deps: serve-static@1.12.1

fixes #3233
---
 History.md   | 3 +++
 package.json | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/History.md b/History.md
index aadd7ece046..e4de69bc488 100644
--- a/History.md
+++ b/History.md
@@ -4,6 +4,9 @@ unreleased
   * deps: send@0.15.1
     - Fix issue when `Date.parse` does not return `NaN` on invalid date
     - Fix strict violation in broken environments
+  * deps: serve-static@1.12.1
+    - Fix issue when `Date.parse` does not return `NaN` on invalid date
+    - deps: send@0.15.1
 
 4.15.0 / 2017-03-01
 ===================
diff --git a/package.json b/package.json
index aea1a83bc10..1b442295e03 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
     "qs": "6.3.1",
     "range-parser": "~1.2.0",
     "send": "0.15.1",
-    "serve-static": "1.12.0",
+    "serve-static": "1.12.1",
     "setprototypeof": "1.0.3",
     "statuses": "~1.3.1",
     "type-is": "~1.6.14",

From 8eb95ae57973b2cbe7778bc2e10450a380ca2efe Mon Sep 17 00:00:00 2001
From: chainhelen 
Date: Mon, 6 Mar 2017 02:44:22 +0800
Subject: [PATCH 207/889] examples: use path.join instead of concatenation

closes #3236
---
 examples/auth/index.js             |  3 ++-
 examples/downloads/index.js        |  6 ++---
 examples/ejs/index.js              |  3 ++-
 examples/error-pages/index.js      |  3 ++-
 examples/jade/index.js             |  5 +++--
 examples/markdown/index.js         |  3 ++-
 examples/mvc/index.js              |  5 +++--
 examples/mvc/lib/boot.js           | 35 ++++++++++++++++--------------
 examples/route-separation/index.js |  5 +++--
 examples/search/index.js           |  5 +++--
 10 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/examples/auth/index.js b/examples/auth/index.js
index 1c3ca217512..084fba79a97 100644
--- a/examples/auth/index.js
+++ b/examples/auth/index.js
@@ -5,6 +5,7 @@
 var express = require('../..');
 var bodyParser = require('body-parser');
 var hash = require('pbkdf2-password')()
+var path = require('path');
 var session = require('express-session');
 
 var app = module.exports = express();
@@ -12,7 +13,7 @@ var app = module.exports = express();
 // config
 
 app.set('view engine', 'ejs');
-app.set('views', __dirname + '/views');
+app.set('views', path.join(__dirname, 'views'));
 
 // middleware
 
diff --git a/examples/downloads/index.js b/examples/downloads/index.js
index 6ab6ba0213e..e6f3fa9db69 100644
--- a/examples/downloads/index.js
+++ b/examples/downloads/index.js
@@ -3,6 +3,7 @@
  */
 
 var express = require('../../');
+var path = require('path');
 var app = module.exports = express();
 
 app.get('/', function(req, res){
@@ -16,10 +17,9 @@ app.get('/', function(req, res){
 // /files/* is accessed via req.params[0]
 // but here we name it :file
 app.get('/files/:file(*)', function(req, res, next){
-  var file = req.params.file;
-  var path = __dirname + '/files/' + file;
+  var filePath = path.join(__dirname, 'files', req.params.file);
 
-  res.download(path, function(err){
+  res.download(filePath, function (err) {
     if (!err) return; // file sent
     if (err && err.status !== 404) return next(err); // non-404 error
     // file for download not found
diff --git a/examples/ejs/index.js b/examples/ejs/index.js
index bf78a9cc803..13a80efc193 100644
--- a/examples/ejs/index.js
+++ b/examples/ejs/index.js
@@ -3,6 +3,7 @@
  */
 
 var express = require('../../');
+var path = require('path');
 
 var app = module.exports = express();
 
@@ -21,7 +22,7 @@ app.engine('.html', require('ejs').__express);
 
 // Optional since express defaults to CWD/views
 
-app.set('views', __dirname + '/views');
+app.set('views', path.join(__dirname, 'views'));
 
 // Without this you would need to
 // supply the extension to res.render()
diff --git a/examples/error-pages/index.js b/examples/error-pages/index.js
index d1219689f2c..790f6e30dfd 100644
--- a/examples/error-pages/index.js
+++ b/examples/error-pages/index.js
@@ -3,12 +3,13 @@
  */
 
 var express = require('../../');
+var path = require('path');
 var app = module.exports = express();
 var logger = require('morgan');
 var silent = 'test' == process.env.NODE_ENV;
 
 // general config
-app.set('views', __dirname + '/views');
+app.set('views', path.join(__dirname, 'views'));
 app.set('view engine', 'ejs');
 
 // our custom "verbose errors" setting
diff --git a/examples/jade/index.js b/examples/jade/index.js
index 738b382d267..86ca14c426e 100644
--- a/examples/jade/index.js
+++ b/examples/jade/index.js
@@ -3,10 +3,11 @@
  */
 
 var express = require('../../lib/express');
+var path = require('path');
 
 // Path to our public directory
 
-var pub = __dirname + '/public';
+var pub = path.join(__dirname, 'public');
 
 // setup middleware
 
@@ -15,7 +16,7 @@ app.use(express.static(pub));
 
 // Optional since express defaults to CWD/views
 
-app.set('views', __dirname + '/views');
+app.set('views', path.join(__dirname, 'views'));
 
 // Set our default template engine to "jade"
 // which prevents the need for extensions
diff --git a/examples/markdown/index.js b/examples/markdown/index.js
index 430628701fd..df8c195fb4e 100644
--- a/examples/markdown/index.js
+++ b/examples/markdown/index.js
@@ -6,6 +6,7 @@ var escapeHtml = require('escape-html');
 var express = require('../..');
 var fs = require('fs');
 var marked = require('marked');
+var path = require('path');
 
 var app = module.exports = express();
 
@@ -21,7 +22,7 @@ app.engine('md', function(path, options, fn){
   });
 });
 
-app.set('views', __dirname + '/views');
+app.set('views', path.join(__dirname, 'views'));
 
 // make it the default so we dont need .md
 app.set('view engine', 'md');
diff --git a/examples/mvc/index.js b/examples/mvc/index.js
index bf7f726e30f..c5e2678697a 100644
--- a/examples/mvc/index.js
+++ b/examples/mvc/index.js
@@ -4,6 +4,7 @@
 
 var express = require('../..');
 var logger = require('morgan');
+var path = require('path');
 var session = require('express-session');
 var bodyParser = require('body-parser');
 var methodOverride = require('method-override');
@@ -17,7 +18,7 @@ var app = module.exports = express();
 app.set('view engine', 'jade');
 
 // set views for error and 404 pages
-app.set('views', __dirname + '/views');
+app.set('views', path.join(__dirname, 'views'));
 
 // define a custom res.message() method
 // which stores messages in the session
@@ -34,7 +35,7 @@ app.response.message = function(msg){
 if (!module.parent) app.use(logger('dev'));
 
 // serve static files
-app.use(express.static(__dirname + '/public'));
+app.use(express.static(path.join(__dirname, 'public')));
 
 // session support
 app.use(session({
diff --git a/examples/mvc/lib/boot.js b/examples/mvc/lib/boot.js
index a0ca6ec37b1..422330dc066 100644
--- a/examples/mvc/lib/boot.js
+++ b/examples/mvc/lib/boot.js
@@ -4,23 +4,26 @@
 
 var express = require('../../..');
 var fs = require('fs');
+var path = require('path');
 
 module.exports = function(parent, options){
+  var dir = path.join(__dirname, '..', 'controllers');
   var verbose = options.verbose;
-  fs.readdirSync(__dirname + '/../controllers').forEach(function(name){
-    if (!fs.statSync(__dirname + '/../controllers/' + name).isDirectory()) return;
+  fs.readdirSync(dir).forEach(function(name){
+    var file = path.join(dir, name)
+    if (!fs.statSync(file).isDirectory()) return;
     verbose && console.log('\n   %s:', name);
-    var obj = require('./../controllers/' + name);
+    var obj = require(file);
     var name = obj.name || name;
     var prefix = obj.prefix || '';
     var app = express();
     var handler;
     var method;
-    var path;
+    var url;
 
     // allow specifying the view engine
     if (obj.engine) app.set('view engine', obj.engine);
-    app.set('views', __dirname + '/../controllers/' + name + '/views');
+    app.set('views', path.join(__dirname, '..', 'controllers', name, 'views'));
 
     // generate routes based
     // on the exported methods
@@ -31,27 +34,27 @@ module.exports = function(parent, options){
       switch (key) {
         case 'show':
           method = 'get';
-          path = '/' + name + '/:' + name + '_id';
+          url = '/' + name + '/:' + name + '_id';
           break;
         case 'list':
           method = 'get';
-          path = '/' + name + 's';
+          url = '/' + name + 's';
           break;
         case 'edit':
           method = 'get';
-          path = '/' + name + '/:' + name + '_id/edit';
+          url = '/' + name + '/:' + name + '_id/edit';
           break;
         case 'update':
           method = 'put';
-          path = '/' + name + '/:' + name + '_id';
+          url = '/' + name + '/:' + name + '_id';
           break;
         case 'create':
           method = 'post';
-          path = '/' + name;
+          url = '/' + name;
           break;
         case 'index':
           method = 'get';
-          path = '/';
+          url = '/';
           break;
         default:
           /* istanbul ignore next */
@@ -60,15 +63,15 @@ module.exports = function(parent, options){
 
       // setup
       handler = obj[key];
-      path = prefix + path;
+      url = prefix + url;
 
       // before middleware support
       if (obj.before) {
-        app[method](path, obj.before, handler);
-        verbose && console.log('     %s %s -> before -> %s', method.toUpperCase(), path, key);
+        app[method](url, obj.before, handler);
+        verbose && console.log('     %s %s -> before -> %s', method.toUpperCase(), url, key);
       } else {
-        app[method](path, handler);
-        verbose && console.log('     %s %s -> %s', method.toUpperCase(), path, key);
+        app[method](url, handler);
+        verbose && console.log('     %s %s -> %s', method.toUpperCase(), url, key);
       }
     }
 
diff --git a/examples/route-separation/index.js b/examples/route-separation/index.js
index 3d93d5cfd9c..c6605ada6cb 100644
--- a/examples/route-separation/index.js
+++ b/examples/route-separation/index.js
@@ -3,6 +3,7 @@
  */
 
 var express = require('../..');
+var path = require('path');
 var app = express();
 var logger = require('morgan');
 var cookieParser = require('cookie-parser');
@@ -17,7 +18,7 @@ module.exports = app;
 // Config
 
 app.set('view engine', 'jade');
-app.set('views', __dirname + '/views');
+app.set('views', path.join(__dirname, 'views'));
 
 /* istanbul ignore next */
 if (!module.parent) {
@@ -27,7 +28,7 @@ if (!module.parent) {
 app.use(methodOverride('_method'));
 app.use(cookieParser());
 app.use(bodyParser.urlencoded({ extended: true }));
-app.use(express.static(__dirname + '/public'));
+app.use(express.static(path.join(__dirname, 'public')));
 
 // General
 
diff --git a/examples/search/index.js b/examples/search/index.js
index 8027635f19e..79f5d9f4d36 100644
--- a/examples/search/index.js
+++ b/examples/search/index.js
@@ -7,6 +7,7 @@
  */
 
 var express = require('../..');
+var path = require('path');
 var redis = require('redis');
 
 var db = redis.createClient();
@@ -15,7 +16,7 @@ var db = redis.createClient();
 
 var app = express();
 
-app.use(express.static(__dirname + '/public'));
+app.use(express.static(path.join(__dirname, 'public')));
 
 // populate search
 
@@ -45,7 +46,7 @@ app.get('/search/:query?', function(req, res){
  */
 
 app.get('/client.js', function(req, res){
-  res.sendFile(__dirname + '/client.js');
+  res.sendFile(path.join(__dirname, 'client.js'));
 });
 
 /* istanbul ignore next */

From eece3850bc5206c28bfac78c986fbe0c193b34b8 Mon Sep 17 00:00:00 2001
From: chainhelen 
Date: Mon, 6 Mar 2017 02:44:22 +0800
Subject: [PATCH 208/889] tests: use path.join instead of concatenation

closes #3236
---
 test/app.engine.js   |  9 +++++----
 test/app.render.js   | 47 ++++++++++++++++++++++++++++----------------
 test/res.render.js   | 47 +++++++++++++++++++++++++-------------------
 test/res.sendFile.js |  4 ++--
 4 files changed, 64 insertions(+), 43 deletions(-)

diff --git a/test/app.engine.js b/test/app.engine.js
index 88311b2f6d5..6d1ee1cacbf 100644
--- a/test/app.engine.js
+++ b/test/app.engine.js
@@ -1,6 +1,7 @@
 
 var express = require('../')
   , fs = require('fs');
+var path = require('path')
 
 function render(path, options, fn) {
   fs.readFile(path, 'utf8', function(err, str){
@@ -15,7 +16,7 @@ describe('app', function(){
     it('should map a template engine', function(done){
       var app = express();
 
-      app.set('views', __dirname + '/fixtures');
+      app.set('views', path.join(__dirname, 'fixtures'))
       app.engine('.html', render);
       app.locals.user = { name: 'tobi' };
 
@@ -36,7 +37,7 @@ describe('app', function(){
     it('should work without leading "."', function(done){
       var app = express();
 
-      app.set('views', __dirname + '/fixtures');
+      app.set('views', path.join(__dirname, 'fixtures'))
       app.engine('html', render);
       app.locals.user = { name: 'tobi' };
 
@@ -50,7 +51,7 @@ describe('app', function(){
     it('should work "view engine" setting', function(done){
       var app = express();
 
-      app.set('views', __dirname + '/fixtures');
+      app.set('views', path.join(__dirname, 'fixtures'))
       app.engine('html', render);
       app.set('view engine', 'html');
       app.locals.user = { name: 'tobi' };
@@ -65,7 +66,7 @@ describe('app', function(){
     it('should work "view engine" with leading "."', function(done){
       var app = express();
 
-      app.set('views', __dirname + '/fixtures');
+      app.set('views', path.join(__dirname, 'fixtures'))
       app.engine('.html', render);
       app.set('view engine', '.html');
       app.locals.user = { name: 'tobi' };
diff --git a/test/app.render.js b/test/app.render.js
index c9737b7a060..729b1c97cc8 100644
--- a/test/app.render.js
+++ b/test/app.render.js
@@ -1,5 +1,7 @@
 
+var assert = require('assert')
 var express = require('..');
+var path = require('path')
 var tmpl = require('./support/tmpl');
 
 describe('app', function(){
@@ -9,7 +11,7 @@ describe('app', function(){
 
       app.locals.user = { name: 'tobi' };
 
-      app.render(__dirname + '/fixtures/user.tmpl', function (err, str) {
+      app.render(path.join(__dirname, 'fixtures', 'user.tmpl'), function (err, str) {
         if (err) return done(err);
         str.should.equal('

tobi

'); done(); @@ -22,7 +24,7 @@ describe('app', function(){ app.set('view engine', 'tmpl'); app.locals.user = { name: 'tobi' }; - app.render(__dirname + '/fixtures/user', function(err, str){ + app.render(path.join(__dirname, 'fixtures', 'user'), function (err, str) { if (err) return done(err); str.should.equal('

tobi

'); done(); @@ -32,7 +34,7 @@ describe('app', function(){ it('should expose app.locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.locals.user = { name: 'tobi' }; app.render('user.tmpl', function (err, str) { @@ -45,7 +47,7 @@ describe('app', function(){ it('should support index.', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.set('view engine', 'tmpl'); app.render('blog/post', function (err, str) { @@ -80,9 +82,10 @@ describe('app', function(){ it('should provide a helpful error', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.render('rawr.tmpl', function (err) { - err.message.should.equal('Failed to lookup view "rawr.tmpl" in views directory "' + __dirname + '/fixtures"'); + assert.ok(err) + assert.equal(err.message, 'Failed to lookup view "rawr.tmpl" in views directory "' + path.join(__dirname, 'fixtures') + '"') done(); }); }) @@ -92,7 +95,7 @@ describe('app', function(){ it('should invoke the callback', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.render('user.tmpl', function (err, str) { // nextTick to prevent cyclic @@ -108,7 +111,7 @@ describe('app', function(){ it('should render the template', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.render('email.tmpl', function (err, str) { if (err) return done(err); @@ -123,7 +126,7 @@ describe('app', function(){ var app = createApp(); app.set('view engine', 'tmpl'); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.render('email', function(err, str){ if (err) return done(err); @@ -137,7 +140,7 @@ describe('app', function(){ it('should lookup the file in the path', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures/default_layout'); + app.set('views', path.join(__dirname, 'fixtures', 'default_layout')) app.locals.user = { name: 'tobi' }; app.render('user.tmpl', function (err, str) { @@ -150,7 +153,10 @@ describe('app', function(){ describe('when array of paths', function(){ it('should lookup the file in the path', function(done){ var app = createApp(); - var views = [__dirname + '/fixtures/local_layout', __dirname + '/fixtures/default_layout']; + var views = [ + path.join(__dirname, 'fixtures', 'local_layout'), + path.join(__dirname, 'fixtures', 'default_layout') + ] app.set('views', views); app.locals.user = { name: 'tobi' }; @@ -164,7 +170,10 @@ describe('app', function(){ it('should lookup in later paths until found', function(done){ var app = createApp(); - var views = [__dirname + '/fixtures/local_layout', __dirname + '/fixtures/default_layout']; + var views = [ + path.join(__dirname, 'fixtures', 'local_layout'), + path.join(__dirname, 'fixtures', 'default_layout') + ] app.set('views', views); app.locals.name = 'tobi'; @@ -178,13 +187,17 @@ describe('app', function(){ it('should error if file does not exist', function(done){ var app = createApp(); - var views = [__dirname + '/fixtures/local_layout', __dirname + '/fixtures/default_layout']; + var views = [ + path.join(__dirname, 'fixtures', 'local_layout'), + path.join(__dirname, 'fixtures', 'default_layout') + ] app.set('views', views); app.locals.name = 'tobi'; app.render('pet.tmpl', function (err, str) { - err.message.should.equal('Failed to lookup view "pet.tmpl" in views directories "' + __dirname + '/fixtures/local_layout" or "' + __dirname + '/fixtures/default_layout"'); + assert.ok(err) + assert.equal(err.message, 'Failed to lookup view "pet.tmpl" in views directories "' + views[0] + '" or "' + views[1] + '"') done(); }) }) @@ -281,7 +294,7 @@ describe('app', function(){ it('should render the template', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) var user = { name: 'tobi' }; @@ -295,7 +308,7 @@ describe('app', function(){ it('should expose app.locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.locals.user = { name: 'tobi' }; app.render('user.tmpl', {}, function (err, str) { @@ -308,7 +321,7 @@ describe('app', function(){ it('should give precedence to app.render() locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.locals.user = { name: 'tobi' }; var jane = { name: 'jane' }; diff --git a/test/res.render.js b/test/res.render.js index d4d2a7616d1..2e3a16f1370 100644 --- a/test/res.render.js +++ b/test/res.render.js @@ -1,5 +1,6 @@ var express = require('..'); +var path = require('path') var request = require('supertest'); var tmpl = require('./support/tmpl'); @@ -11,7 +12,7 @@ describe('res', function(){ app.locals.user = { name: 'tobi' }; app.use(function(req, res){ - res.render(__dirname + '/fixtures/user.tmpl'); + res.render(path.join(__dirname, 'fixtures', 'user.tmpl')) }); request(app) @@ -26,7 +27,7 @@ describe('res', function(){ app.set('view engine', 'tmpl'); app.use(function(req, res){ - res.render(__dirname + '/fixtures/user'); + res.render(path.join(__dirname, 'fixtures', 'user')) }); request(app) @@ -40,7 +41,7 @@ describe('res', function(){ app.locals.user = { name: 'tobi' }; app.use(function(req, res){ - res.render(__dirname + '/fixtures/user'); + res.render(path.join(__dirname, 'fixtures', 'user')) }); request(app) @@ -51,7 +52,7 @@ describe('res', function(){ it('should expose app.locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.locals.user = { name: 'tobi' }; app.use(function(req, res){ @@ -66,7 +67,7 @@ describe('res', function(){ it('should expose app.locals with `name` property', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.locals.name = 'tobi'; app.use(function(req, res){ @@ -81,7 +82,7 @@ describe('res', function(){ it('should support index.', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.set('view engine', 'tmpl'); app.use(function(req, res){ @@ -97,7 +98,7 @@ describe('res', function(){ it('should next(err)', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.use(function(req, res){ res.render('user.tmpl'); @@ -118,7 +119,7 @@ describe('res', function(){ var app = createApp(); app.set('view engine', 'tmpl'); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.use(function(req, res){ res.render('email'); @@ -134,7 +135,7 @@ describe('res', function(){ it('should lookup the file in the path', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures/default_layout'); + app.set('views', path.join(__dirname, 'fixtures', 'default_layout')) app.use(function(req, res){ res.render('user.tmpl', { user: { name: 'tobi' } }); @@ -148,7 +149,10 @@ describe('res', function(){ describe('when array of paths', function(){ it('should lookup the file in the path', function(done){ var app = createApp(); - var views = [__dirname + '/fixtures/local_layout', __dirname + '/fixtures/default_layout']; + var views = [ + path.join(__dirname, 'fixtures', 'local_layout'), + path.join(__dirname, 'fixtures', 'default_layout') + ] app.set('views', views); @@ -163,7 +167,10 @@ describe('res', function(){ it('should lookup in later paths until found', function(done){ var app = createApp(); - var views = [__dirname + '/fixtures/local_layout', __dirname + '/fixtures/default_layout']; + var views = [ + path.join(__dirname, 'fixtures', 'local_layout'), + path.join(__dirname, 'fixtures', 'default_layout') + ] app.set('views', views); @@ -183,7 +190,7 @@ describe('res', function(){ it('should render the template', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) var user = { name: 'tobi' }; @@ -199,7 +206,7 @@ describe('res', function(){ it('should expose app.locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.locals.user = { name: 'tobi' }; app.use(function(req, res){ @@ -214,7 +221,7 @@ describe('res', function(){ it('should expose res.locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.use(function(req, res){ res.locals.user = { name: 'tobi' }; @@ -229,7 +236,7 @@ describe('res', function(){ it('should give precedence to res.locals over app.locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.locals.user = { name: 'tobi' }; app.use(function(req, res){ @@ -245,7 +252,7 @@ describe('res', function(){ it('should give precedence to res.render() locals over res.locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) var jane = { name: 'jane' }; app.use(function(req, res){ @@ -261,7 +268,7 @@ describe('res', function(){ it('should give precedence to res.render() locals over app.locals', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.locals.user = { name: 'tobi' }; var jane = { name: 'jane' }; @@ -279,7 +286,7 @@ describe('res', function(){ it('should pass the resulting string', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.use(function(req, res){ var tobi = { name: 'tobi' }; @@ -299,7 +306,7 @@ describe('res', function(){ it('should pass the resulting string', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.use(function(req, res){ res.locals.user = { name: 'tobi' }; @@ -318,7 +325,7 @@ describe('res', function(){ it('should pass it to the callback', function(done){ var app = createApp(); - app.set('views', __dirname + '/fixtures'); + app.set('views', path.join(__dirname, 'fixtures')) app.use(function(req, res){ res.render('user.tmpl', function (err) { diff --git a/test/res.sendFile.js b/test/res.sendFile.js index 927d31991f0..be3a23ebc2c 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -613,7 +613,7 @@ describe('res', function(){ var app = express(); app.use(function(req, res){ - res.sendfile(__dirname + '/fixtures/user.html'); + res.sendfile(path.join(__dirname, '/fixtures/user.html')) }); request(app) @@ -718,7 +718,7 @@ describe('res', function(){ , calls = 0; app.use(function(req, res){ - res.sendfile(__dirname + '/fixtures/name.txt'); + res.sendfile(path.join(__dirname, '/fixtures/name.txt')) }); request(app) From 57d3dfd9f828c4529fa90dde4b3d216898181e99 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Sun, 26 Feb 2017 13:26:39 +0000 Subject: [PATCH 209/889] examples: merge the jade example into ejs closes #3223 --- examples/ejs/index.js | 4 ++ .../public/stylesheets/style.css | 0 examples/ejs/views/header.html | 9 +--- examples/jade/index.js | 52 ------------------- examples/jade/views/header.jade | 3 -- examples/jade/views/layout.jade | 5 -- examples/jade/views/users/index.jade | 8 --- examples/jade/views/users/user.jade | 3 -- 8 files changed, 6 insertions(+), 78 deletions(-) rename examples/{jade => ejs}/public/stylesheets/style.css (100%) delete mode 100644 examples/jade/index.js delete mode 100644 examples/jade/views/header.jade delete mode 100644 examples/jade/views/layout.jade delete mode 100644 examples/jade/views/users/index.jade delete mode 100644 examples/jade/views/users/user.jade diff --git a/examples/ejs/index.js b/examples/ejs/index.js index 13a80efc193..b868bdd7cb9 100644 --- a/examples/ejs/index.js +++ b/examples/ejs/index.js @@ -24,6 +24,10 @@ app.engine('.html', require('ejs').__express); app.set('views', path.join(__dirname, 'views')); +// Path to our public directory + +app.use(express.static(path.join(__dirname + 'public'))); + // Without this you would need to // supply the extension to res.render() // ex: res.render('users.html'). diff --git a/examples/jade/public/stylesheets/style.css b/examples/ejs/public/stylesheets/style.css similarity index 100% rename from examples/jade/public/stylesheets/style.css rename to examples/ejs/public/stylesheets/style.css diff --git a/examples/ejs/views/header.html b/examples/ejs/views/header.html index 8dbeb8d3c01..4396bc444fa 100644 --- a/examples/ejs/views/header.html +++ b/examples/ejs/views/header.html @@ -2,12 +2,7 @@ - <%= title %> - + <%= title %> + diff --git a/examples/jade/index.js b/examples/jade/index.js deleted file mode 100644 index 86ca14c426e..00000000000 --- a/examples/jade/index.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Module dependencies. - */ - -var express = require('../../lib/express'); -var path = require('path'); - -// Path to our public directory - -var pub = path.join(__dirname, 'public'); - -// setup middleware - -var app = express(); -app.use(express.static(pub)); - -// Optional since express defaults to CWD/views - -app.set('views', path.join(__dirname, 'views')); - -// Set our default template engine to "jade" -// which prevents the need for extensions -// (although you can still mix and match) -app.set('view engine', 'jade'); - -function User(name, email) { - this.name = name; - this.email = email; -} - -// Dummy users -var users = [ - new User('tj', 'tj@vision-media.ca') - , new User('ciaran', 'ciaranj@gmail.com') - , new User('aaron', 'aaron.heckmann+github@gmail.com') -]; - -app.get('/', function(req, res){ - res.render('users', { users: users }); -}); - -// change this to a better error handler in your code -// sending stacktrace to users in production is not good -app.use(function(err, req, res, next) { - res.send(err.stack); -}); - -/* istanbul ignore next */ -if (!module.parent) { - app.listen(3000); - console.log('Express started on port 3000'); -} diff --git a/examples/jade/views/header.jade b/examples/jade/views/header.jade deleted file mode 100644 index 6c42929d837..00000000000 --- a/examples/jade/views/header.jade +++ /dev/null @@ -1,3 +0,0 @@ -head - title Jade Example - link(rel="stylesheet", href="http://github.com/stylesheets/style.css") \ No newline at end of file diff --git a/examples/jade/views/layout.jade b/examples/jade/views/layout.jade deleted file mode 100644 index 300cdc78473..00000000000 --- a/examples/jade/views/layout.jade +++ /dev/null @@ -1,5 +0,0 @@ -doctype html -html - include header - body - block content diff --git a/examples/jade/views/users/index.jade b/examples/jade/views/users/index.jade deleted file mode 100644 index feb7623fa3d..00000000000 --- a/examples/jade/views/users/index.jade +++ /dev/null @@ -1,8 +0,0 @@ - -extends ../layout - -block content - h1 Users - #users - for user in users - include user \ No newline at end of file diff --git a/examples/jade/views/users/user.jade b/examples/jade/views/users/user.jade deleted file mode 100644 index 9e603298cbf..00000000000 --- a/examples/jade/views/users/user.jade +++ /dev/null @@ -1,3 +0,0 @@ -.user - h2= user.name - .email= user.email \ No newline at end of file From d32ed68b2995e0322100ace29d86e7a86b9c6378 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 5 Mar 2017 23:19:32 -0500 Subject: [PATCH 210/889] 4.15.1 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index e4de69bc488..82511c3f400 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.15.1 / 2017-03-05 +=================== * deps: send@0.15.1 - Fix issue when `Date.parse` does not return `NaN` on invalid date diff --git a/package.json b/package.json index 1b442295e03..727064b6652 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.15.0", + "version": "4.15.1", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 85c96fd64edad8ce076bb82c065ef0c9fea6c559 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Mar 2017 08:32:13 -0500 Subject: [PATCH 211/889] deps: qs@6.4.0 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 82511c3f400..dd529f16320 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +unreleased +========== + + * deps: qs@6.4.0 + - Fix regression parsing keys starting with `[` + 4.15.1 / 2017-03-05 =================== diff --git a/package.json b/package.json index 727064b6652..05a9ce56d90 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.3", - "qs": "6.3.1", + "qs": "6.4.0", "range-parser": "~1.2.0", "send": "0.15.1", "serve-static": "1.12.1", From 05fd1e444198954c1e275d485bccabafed052868 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Mar 2017 08:33:37 -0500 Subject: [PATCH 212/889] deps: update example dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 05a9ce56d90..7894722c4db 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ }, "devDependencies": { "after": "0.8.2", - "body-parser": "1.17.0", + "body-parser": "1.17.1", "cookie-parser": "~1.4.3", "ejs": "2.5.6", "express-session": "1.15.1", From d43b074f0b3b56a91f240e62798c932ba104b79a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Mar 2017 08:34:38 -0500 Subject: [PATCH 213/889] 4.15.2 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index dd529f16320..5bfd5690a53 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.15.2 / 2017-03-06 +=================== * deps: qs@6.4.0 - Fix regression parsing keys starting with `[` diff --git a/package.json b/package.json index 7894722c4db..ef49b40d425 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.15.1", + "version": "4.15.2", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 21f725e0ef9e1e9a8ea51e8486e9cadeae956774 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Mar 2017 08:43:58 -0500 Subject: [PATCH 214/889] 5.0.0-alpha.5 --- History.md | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index fe16da7a40e..9e41319f5a3 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,8 @@ -5.x -=== +5.0.0-alpha.5 / 2017-03-06 +========================== -This incorporates all changes after 4.15.0 up to 4.15.2. +This is the fifth Express 5.0 alpha release, based off 4.15.2 and includes +changes from 5.0.0-alpha.4. 5.0.0-alpha.4 / 2017-03-01 ========================== diff --git a/package.json b/package.json index ffd613debda..0efe312c6b4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-alpha.4", + "version": "5.0.0-alpha.5", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 64dd446aa85a3fc28bd4662626593f29a45689f6 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Wed, 8 Mar 2017 14:10:39 +0000 Subject: [PATCH 215/889] docs: remove dead link to translated readme closes #3239 --- Readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Readme.md b/Readme.md index 0ddc68fdc9a..7b261a3d94d 100644 --- a/Readme.md +++ b/Readme.md @@ -43,7 +43,6 @@ $ npm install express * Visit the [Wiki](https://github.com/expressjs/express/wiki) * [Google Group](https://groups.google.com/group/express-js) for discussion * [Gitter](https://gitter.im/expressjs/express) for support and discussion - * [Русскоязычная документация](http://jsman.ru/express/) **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x). From f44368f8bede4ffc56929b183d6d5508e222a949 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Wed, 8 Mar 2017 14:32:43 +0000 Subject: [PATCH 216/889] examples: replace jade with ejs in view-locals closes #3240 --- examples/view-locals/index.js | 11 ++++++----- examples/view-locals/layout.jade | 12 ------------ examples/view-locals/user.jade | 8 -------- examples/view-locals/views/index.ejs | 19 +++++++++++++++++++ 4 files changed, 25 insertions(+), 25 deletions(-) delete mode 100644 examples/view-locals/layout.jade delete mode 100644 examples/view-locals/user.jade create mode 100644 examples/view-locals/views/index.ejs diff --git a/examples/view-locals/index.js b/examples/view-locals/index.js index cf347ed38d6..3814e6e4962 100644 --- a/examples/view-locals/index.js +++ b/examples/view-locals/index.js @@ -3,11 +3,12 @@ */ var express = require('../..'); +var path = require('path'); var User = require('./user'); var app = express(); -app.set('views', __dirname); -app.set('view engine', 'jade'); +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'ejs'); // filter ferrets only @@ -25,7 +26,7 @@ app.get('/', function(req, res, next){ if (err) return next(err); User.all(function(err, users){ if (err) return next(err); - res.render('user', { + res.render('index', { title: 'Users', count: count, users: users.filter(ferrets) @@ -59,7 +60,7 @@ function users(req, res, next) { } app.get('/middleware', count, users, function(req, res, next){ - res.render('user', { + res.render('index', { title: 'Users', count: req.count, users: req.users.filter(ferrets) @@ -101,7 +102,7 @@ app.get('/middleware-locals', count2, users2, function(req, res, next){ // to pass to res.render(). If we have // several routes related to users this // can be a great productivity booster - res.render('user', { title: 'Users' }); + res.render('index', { title: 'Users' }); }); // keep in mind that middleware may be placed anywhere diff --git a/examples/view-locals/layout.jade b/examples/view-locals/layout.jade deleted file mode 100644 index 5616cfaf7c2..00000000000 --- a/examples/view-locals/layout.jade +++ /dev/null @@ -1,12 +0,0 @@ -doctype html -html - head - title= title - style. - body { - padding: 50px; - font: 16px Helvetica, Arial; - } - body - h2= title - block content \ No newline at end of file diff --git a/examples/view-locals/user.jade b/examples/view-locals/user.jade deleted file mode 100644 index b07d2b17563..00000000000 --- a/examples/view-locals/user.jade +++ /dev/null @@ -1,8 +0,0 @@ - -extends layout - -block content - for user in users - .user - h3= user.name - p #{user.name} is a #{user.age} year old #{user.species}. \ No newline at end of file diff --git a/examples/view-locals/views/index.ejs b/examples/view-locals/views/index.ejs new file mode 100644 index 00000000000..1cbfc40bc00 --- /dev/null +++ b/examples/view-locals/views/index.ejs @@ -0,0 +1,19 @@ + + + + + <%= title %> + + + +

<%= title %>

+ <% users.forEach(function(user) { %> +
  • <%= user.name %> is a <% user.age %> year old <%= user.species %>
  • + <% }); %> + + From a1fffda3f2c879dac1b2ba7a28c457957768e874 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 14 Mar 2017 23:46:29 -0400 Subject: [PATCH 217/889] build: should@11.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ef49b40d425..1ec44636566 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "morgan": "1.8.1", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", - "should": "11.2.0", + "should": "11.2.1", "supertest": "1.2.0", "connect-redis": "~2.4.1", "cookie-session": "~1.2.0", From 1b6ad080952f026fc7913beb84176519658ee07b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 14 Mar 2017 23:53:19 -0400 Subject: [PATCH 218/889] deps: debug@2.6.3 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5bfd5690a53..aa32ea6b893 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +unreleased +========== + + * deps: debug@2.6.3 + - Fix: `DEBUG_MAX_ARRAY_LENGTH` + 4.15.2 / 2017-03-06 =================== diff --git a/package.json b/package.json index 1ec44636566..dd03d7e9bc5 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "content-type": "~1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", - "debug": "2.6.1", + "debug": "2.6.3", "depd": "~1.1.0", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", From 245fa8942a4478862b7a620c6ce66f55311c556e Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Wed, 8 Mar 2017 14:52:43 +0000 Subject: [PATCH 219/889] examples: replace jade with ejs in route-separation closes #3241 --- examples/route-separation/index.js | 2 +- examples/route-separation/views/footer.ejs | 2 ++ examples/route-separation/views/header.ejs | 8 +++++++ examples/route-separation/views/index.ejs | 10 ++++++++ examples/route-separation/views/index.jade | 6 ----- examples/route-separation/views/layout.jade | 6 ----- .../route-separation/views/posts/index.ejs | 12 ++++++++++ .../route-separation/views/posts/index.jade | 8 ------- .../route-separation/views/users/edit.ejs | 23 +++++++++++++++++++ .../route-separation/views/users/edit.jade | 12 ---------- .../route-separation/views/users/index.ejs | 14 +++++++++++ .../route-separation/views/users/index.jade | 9 -------- .../route-separation/views/users/view.ejs | 9 ++++++++ .../route-separation/views/users/view.jade | 6 ----- 14 files changed, 79 insertions(+), 48 deletions(-) create mode 100644 examples/route-separation/views/footer.ejs create mode 100644 examples/route-separation/views/header.ejs create mode 100644 examples/route-separation/views/index.ejs delete mode 100644 examples/route-separation/views/index.jade delete mode 100644 examples/route-separation/views/layout.jade create mode 100644 examples/route-separation/views/posts/index.ejs delete mode 100644 examples/route-separation/views/posts/index.jade create mode 100644 examples/route-separation/views/users/edit.ejs delete mode 100644 examples/route-separation/views/users/edit.jade create mode 100644 examples/route-separation/views/users/index.ejs delete mode 100644 examples/route-separation/views/users/index.jade create mode 100644 examples/route-separation/views/users/view.ejs delete mode 100644 examples/route-separation/views/users/view.jade diff --git a/examples/route-separation/index.js b/examples/route-separation/index.js index c6605ada6cb..79e26497f45 100644 --- a/examples/route-separation/index.js +++ b/examples/route-separation/index.js @@ -17,7 +17,7 @@ module.exports = app; // Config -app.set('view engine', 'jade'); +app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views')); /* istanbul ignore next */ diff --git a/examples/route-separation/views/footer.ejs b/examples/route-separation/views/footer.ejs new file mode 100644 index 00000000000..308b1d01b6c --- /dev/null +++ b/examples/route-separation/views/footer.ejs @@ -0,0 +1,2 @@ + + diff --git a/examples/route-separation/views/header.ejs b/examples/route-separation/views/header.ejs new file mode 100644 index 00000000000..141f114ddba --- /dev/null +++ b/examples/route-separation/views/header.ejs @@ -0,0 +1,8 @@ + + + + + <%= title %> + + + diff --git a/examples/route-separation/views/index.ejs b/examples/route-separation/views/index.ejs new file mode 100644 index 00000000000..6d1afb4ac3d --- /dev/null +++ b/examples/route-separation/views/index.ejs @@ -0,0 +1,10 @@ +<% include header %> + +

    <%= title %>

    + +
      +
    • Visit the users page.
    • +
    • Visit the posts page.
    • +
    + +<% include footer %> diff --git a/examples/route-separation/views/index.jade b/examples/route-separation/views/index.jade deleted file mode 100644 index af9d499387a..00000000000 --- a/examples/route-separation/views/index.jade +++ /dev/null @@ -1,6 +0,0 @@ -extends layout - -block content - ul - li Visit the users page - li Visit the posts page diff --git a/examples/route-separation/views/layout.jade b/examples/route-separation/views/layout.jade deleted file mode 100644 index 6535c8cc89d..00000000000 --- a/examples/route-separation/views/layout.jade +++ /dev/null @@ -1,6 +0,0 @@ -html - head - title= title - link(href="http://github.com/style.css", rel="stylesheet") - body - block content diff --git a/examples/route-separation/views/posts/index.ejs b/examples/route-separation/views/posts/index.ejs new file mode 100644 index 00000000000..12303444858 --- /dev/null +++ b/examples/route-separation/views/posts/index.ejs @@ -0,0 +1,12 @@ +<% include ../header %> + +

    Posts

    + +
    + <% posts.forEach(function(post) { %> +
    <%= post.title %>
    +
    <%= post.body %>
    + <% }) %> +
    + +<% include ../footer %> diff --git a/examples/route-separation/views/posts/index.jade b/examples/route-separation/views/posts/index.jade deleted file mode 100644 index 46efb2ea222..00000000000 --- a/examples/route-separation/views/posts/index.jade +++ /dev/null @@ -1,8 +0,0 @@ -extends ../layout - -block content - h1 Posts - dl#posts - for post in posts - dt= post.title - dd= post.body diff --git a/examples/route-separation/views/users/edit.ejs b/examples/route-separation/views/users/edit.ejs new file mode 100644 index 00000000000..c64160e037f --- /dev/null +++ b/examples/route-separation/views/users/edit.ejs @@ -0,0 +1,23 @@ +<% include ../header %> + +

    Editing <%= user.name %>

    + +
    +
    +

    + Name: + +

    + +

    + Email: + +

    + +

    + +

    +
    +
    + +<% include ../footer %> diff --git a/examples/route-separation/views/users/edit.jade b/examples/route-separation/views/users/edit.jade deleted file mode 100644 index f9ef180d6db..00000000000 --- a/examples/route-separation/views/users/edit.jade +++ /dev/null @@ -1,12 +0,0 @@ -extends ../layout - -block content - h1 Editing #{user.name} - #user - form(action="http://github.com/?_method=put", method="post") - p Name: - input(type="text", value= user.name, name="user[name]") - p Email: - input(type="text", value= user.email, name="user[email]") - p - input(type="submit", value="Save") diff --git a/examples/route-separation/views/users/index.ejs b/examples/route-separation/views/users/index.ejs new file mode 100644 index 00000000000..0f97fc691c0 --- /dev/null +++ b/examples/route-separation/views/users/index.ejs @@ -0,0 +1,14 @@ +<% include ../header %> + +

    <%= title %>

    + +
    + <% users.forEach(function(user, index) { %> +
  • + <%= user.name %> + edit +
  • + <% }) %> +
    + +<% include ../footer %> diff --git a/examples/route-separation/views/users/index.jade b/examples/route-separation/views/users/index.jade deleted file mode 100644 index c4c54d0cf0d..00000000000 --- a/examples/route-separation/views/users/index.jade +++ /dev/null @@ -1,9 +0,0 @@ -extends ../layout - -block content - h1 Users - #users - for user, i in users - li - a(href="http://github.com/user/#{i}")= user.name - a.edit(href="http://github.com/user/#{i}/edit") edit diff --git a/examples/route-separation/views/users/view.ejs b/examples/route-separation/views/users/view.ejs new file mode 100644 index 00000000000..696abc04504 --- /dev/null +++ b/examples/route-separation/views/users/view.ejs @@ -0,0 +1,9 @@ +<% include ../header %> + +

    <%= user.name %>

    + +
    +

    Email: <%= user.email %>

    +
    + +<% include ../footer %> diff --git a/examples/route-separation/views/users/view.jade b/examples/route-separation/views/users/view.jade deleted file mode 100644 index f5af1ae8cc0..00000000000 --- a/examples/route-separation/views/users/view.jade +++ /dev/null @@ -1,6 +0,0 @@ -extends ../layout - -block content - h1= user.name - #user - p Email: #{user.email} From 2189ff14a9ba5ff2109412edd7009fcf5bc802f3 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 19 Mar 2017 16:45:58 -0400 Subject: [PATCH 220/889] lint: remove trailing new lines from docs --- Contributing.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Contributing.md b/Contributing.md index 214e9070126..41386568d64 100644 --- a/Contributing.md +++ b/Contributing.md @@ -12,7 +12,7 @@ contributors can be involved in decision making. * A **Contributor** is any individual creating or commenting on an issue or pull request. * A **Committer** is a subset of contributors who have been given write access to the repository. -* A **TC (Technical Committee)** is a group of committers representing the required technical +* A **TC (Technical Committee)** is a group of committers representing the required technical expertise to resolve rare disputes. # Logging Issues @@ -36,24 +36,24 @@ pull requests. No pull request can be merged without being reviewed. For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that -contributors in other timezones have time to review. Consideration should also be given to -weekends and other holiday periods to ensure active committers all have reasonable time to +contributors in other timezones have time to review. Consideration should also be given to +weekends and other holiday periods to ensure active committers all have reasonable time to become involved in the discussion and review process if they wish. The default for each contribution is that it is accepted once no committer has an objection. -During review committers may also request that a specific contributor who is most versed in a -particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off" -process for contributions to land. Once all issues brought by committers are addressed it can +During review committers may also request that a specific contributor who is most versed in a +particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off" +process for contributions to land. Once all issues brought by committers are addressed it can be landed by any committer. -In the case of an objection being raised in a pull request by another committer, all involved -committers should seek to arrive at a consensus by way of addressing concerns being expressed +In the case of an objection being raised in a pull request by another committer, all involved +committers should seek to arrive at a consensus by way of addressing concerns being expressed by discussion, compromise on the proposed change, or withdrawal of the proposed change. If a contribution is controversial and committers cannot agree about how to get it to land or if it should land then it should be escalated to the TC. TC members should regularly -discuss pending contributions in order to find a resolution. It is expected that only a -small minority of issues be brought to the TC for resolution and that discussion and +discuss pending contributions in order to find a resolution. It is expected that only a +small minority of issues be brought to the TC for resolution and that discussion and compromise among committers be the default resolution mechanism. # Becoming a Committer @@ -66,20 +66,20 @@ proper review, and have other committers merge their pull requests. # TC Process -The TC uses a "consensus seeking" process for issues that are escalated to the TC. +The TC uses a "consensus seeking" process for issues that are escalated to the TC. The group tries to find a resolution that has no open objections among TC members. If a consensus cannot be reached that has no objections then a majority wins vote -is called. It is also expected that the majority of decisions made by the TC are via +is called. It is also expected that the majority of decisions made by the TC are via a consensus seeking process and that voting is only used as a last-resort. -Resolution may involve returning the issue to committers with suggestions on how to -move forward towards a consensus. It is not expected that a meeting of the TC +Resolution may involve returning the issue to committers with suggestions on how to +move forward towards a consensus. It is not expected that a meeting of the TC will resolve all issues on its agenda during that meeting and may prefer to continue the discussion happening among the committers. Members can be added to the TC at any time. Any committer can nominate another committer to the TC and the TC uses its standard consensus seeking process to evaluate whether or -not to add this new member. Members who do not participate consistently at the level of +not to add this new member. Members who do not participate consistently at the level of a majority of the other members are expected to resign. From efd7032f71f3ef18060a100edc4aa11f4c912dde Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Fri, 24 Feb 2017 09:05:43 -0600 Subject: [PATCH 221/889] build: Add .editorconfig closes #3221 --- .editorconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..cdb36c1b466 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# http://editorconfig.org +root = true + +[*] +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +[{*.js,*.json,*.yml}] +indent_size = 2 +indent_style = space From dbf092d3ea5aefd65815ca022ab9e89246cd67b9 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Mar 2017 02:10:43 -0400 Subject: [PATCH 222/889] deps: vary@~1.1.1 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index aa32ea6b893..8ecd3970c70 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ unreleased * deps: debug@2.6.3 - Fix: `DEBUG_MAX_ARRAY_LENGTH` + * deps: vary@~1.1.1 + - perf: hoist regular expression 4.15.2 / 2017-03-06 =================== diff --git a/package.json b/package.json index dd03d7e9bc5..1bb93d378c1 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "statuses": "~1.3.1", "type-is": "~1.6.14", "utils-merge": "1.0.0", - "vary": "~1.1.0" + "vary": "~1.1.1" }, "devDependencies": { "after": "0.8.2", From 8acaa9a3ea209be604e73477445c991e842ffe9e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Mar 2017 02:12:06 -0400 Subject: [PATCH 223/889] deps: finalhandler@~1.0.1 fixes #3252 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 8ecd3970c70..a8647e2484a 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,9 @@ unreleased * deps: debug@2.6.3 - Fix: `DEBUG_MAX_ARRAY_LENGTH` + * deps: finalhandler@~1.0.1 + - Fix missing `` in HTML document + - deps: debug@2.6.3 * deps: vary@~1.1.1 - perf: hoist regular expression diff --git a/package.json b/package.json index 1bb93d378c1..42fd1ca46be 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.8.0", - "finalhandler": "~1.0.0", + "finalhandler": "~1.0.1", "fresh": "0.5.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", From 3763d73a1f6663460b32e600b8fc892075e069c5 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Wed, 8 Mar 2017 16:31:18 +0000 Subject: [PATCH 224/889] examples: replace jade with hbs in mvc example fixes #3181 closes #3185 closes #3243 closes #3245 closes #3249 --- examples/mvc/controllers/user/index.js | 2 ++ examples/mvc/controllers/user/views/edit.hbs | 25 ++++++++++++++++ examples/mvc/controllers/user/views/edit.jade | 11 ------- examples/mvc/controllers/user/views/list.hbs | 16 ++++++++++ examples/mvc/controllers/user/views/list.jade | 7 ----- examples/mvc/controllers/user/views/show.hbs | 29 +++++++++++++++++++ examples/mvc/controllers/user/views/show.jade | 17 ----------- examples/mvc/index.js | 8 ++--- examples/mvc/views/404.ejs | 12 ++++++++ examples/mvc/views/404.jade | 3 -- examples/mvc/views/5xx.ejs | 12 ++++++++ examples/mvc/views/5xx.jade | 3 -- package.json | 2 +- 13 files changed, 100 insertions(+), 47 deletions(-) create mode 100644 examples/mvc/controllers/user/views/edit.hbs delete mode 100644 examples/mvc/controllers/user/views/edit.jade create mode 100644 examples/mvc/controllers/user/views/list.hbs delete mode 100644 examples/mvc/controllers/user/views/list.jade create mode 100644 examples/mvc/controllers/user/views/show.hbs delete mode 100644 examples/mvc/controllers/user/views/show.jade create mode 100644 examples/mvc/views/404.ejs delete mode 100644 examples/mvc/views/404.jade create mode 100644 examples/mvc/views/5xx.ejs delete mode 100644 examples/mvc/views/5xx.jade diff --git a/examples/mvc/controllers/user/index.js b/examples/mvc/controllers/user/index.js index 9ccbcccb9ca..a7b0208c8e7 100644 --- a/examples/mvc/controllers/user/index.js +++ b/examples/mvc/controllers/user/index.js @@ -4,6 +4,8 @@ var db = require('../../db'); +exports.engine = 'hbs'; + exports.before = function(req, res, next){ var id = req.params.user_id; if (!id) return next(); diff --git a/examples/mvc/controllers/user/views/edit.hbs b/examples/mvc/controllers/user/views/edit.hbs new file mode 100644 index 00000000000..d356f5ee7f3 --- /dev/null +++ b/examples/mvc/controllers/user/views/edit.hbs @@ -0,0 +1,25 @@ + + + + + Edit {{user.name}} + + +

    {{user.name}}

    +
    + + + +
    + +
    + + + +
    + + diff --git a/examples/mvc/controllers/user/views/edit.jade b/examples/mvc/controllers/user/views/edit.jade deleted file mode 100644 index a2fde5d477e..00000000000 --- a/examples/mvc/controllers/user/views/edit.jade +++ /dev/null @@ -1,11 +0,0 @@ -link(rel='stylesheet', href='http://github.com/style.css') -h1= user.name -form(action='http://github.com/user/#{user.id}?_method=put', method='post') - label= 'Name: ' - input(type='text', name='user[name]', value='#{user.name}') - input(type='submit', value='Update') - -form(action='http://github.com/user/#{user.id}/pet', method='post') - label= 'Pet: ' - input(type='text', name='pet[name]', placeholder='Name') - input(type='submit', value='Add') diff --git a/examples/mvc/controllers/user/views/list.hbs b/examples/mvc/controllers/user/views/list.hbs new file mode 100644 index 00000000000..191867de3ff --- /dev/null +++ b/examples/mvc/controllers/user/views/list.hbs @@ -0,0 +1,16 @@ + + + + + Users + + +

    Users

    +

    Click a user below to view their pets.

    +
      + {{#each users}} +
    • {{name}}
    • + {{/each}} +
    + + diff --git a/examples/mvc/controllers/user/views/list.jade b/examples/mvc/controllers/user/views/list.jade deleted file mode 100644 index af8933cfe05..00000000000 --- a/examples/mvc/controllers/user/views/list.jade +++ /dev/null @@ -1,7 +0,0 @@ -link(rel='stylesheet', href='http://github.com/style.css') -h1 Users -p Click a user below to view their pets. -ul - each user in users - li - a(href='http://github.com/user/#{user.id}')= user.name diff --git a/examples/mvc/controllers/user/views/show.hbs b/examples/mvc/controllers/user/views/show.hbs new file mode 100644 index 00000000000..f064cf54f1f --- /dev/null +++ b/examples/mvc/controllers/user/views/show.hbs @@ -0,0 +1,29 @@ + + + + + {{user.name}} + + +

    {{user.name}} edit

    + +{{#if hasMessages}} +
      + {{#each messages}} +
    • {{this}}
    • + {{/each}} +
    +{{/if}} + +{{#if user.pets.length}} +

    View {{user.name}}'s pets:

    +
      + {{#each user.pets}} +
    • {{name}}
    • + {{/each}} +
    +{{else}} +

    No pets!

    +{{/if}} + + diff --git a/examples/mvc/controllers/user/views/show.jade b/examples/mvc/controllers/user/views/show.jade deleted file mode 100644 index 267d3ef7e40..00000000000 --- a/examples/mvc/controllers/user/views/show.jade +++ /dev/null @@ -1,17 +0,0 @@ -link(rel='stylesheet', href='http://github.com/style.css') -h1= user.name + ' ' - a(href='http://github.com/user/#{user.id}/edit') edit - -if (hasMessages) - ul#messages - each msg in messages - li= msg - -if (user.pets.length) - p View #{user.name}'s pets: - ul - each pet in user.pets - li - a(href='http://github.com/pet/#{pet.id}')= pet.name -else - p No pets! diff --git a/examples/mvc/index.js b/examples/mvc/index.js index c5e2678697a..0d5624b63d3 100644 --- a/examples/mvc/index.js +++ b/examples/mvc/index.js @@ -11,11 +11,9 @@ var methodOverride = require('method-override'); var app = module.exports = express(); -// settings - -// set our default template engine to "jade" -// which prevents the need for extensions -app.set('view engine', 'jade'); +// set our default template engine to "ejs" +// which prevents the need for using file extensions +app.set('view engine', 'ejs'); // set views for error and 404 pages app.set('views', path.join(__dirname, 'views')); diff --git a/examples/mvc/views/404.ejs b/examples/mvc/views/404.ejs new file mode 100644 index 00000000000..18d7e4afe3a --- /dev/null +++ b/examples/mvc/views/404.ejs @@ -0,0 +1,12 @@ + + + + + Not Found + + + +

    404: Not Found

    +

    Sorry we can't find <%= url %>

    + + diff --git a/examples/mvc/views/404.jade b/examples/mvc/views/404.jade deleted file mode 100644 index 110c471f1b9..00000000000 --- a/examples/mvc/views/404.jade +++ /dev/null @@ -1,3 +0,0 @@ -link(rel='stylesheet', href='http://github.com/style.css') -h1 404: Not Found -p Sorry we can't find #{url} diff --git a/examples/mvc/views/5xx.ejs b/examples/mvc/views/5xx.ejs new file mode 100644 index 00000000000..ea0f246ddfd --- /dev/null +++ b/examples/mvc/views/5xx.ejs @@ -0,0 +1,12 @@ + + + + + Internal Server Error + + + +

    500: Internal Server Error

    +

    Looks like something blew up!

    + + diff --git a/examples/mvc/views/5xx.jade b/examples/mvc/views/5xx.jade deleted file mode 100644 index 3508b7c0e2a..00000000000 --- a/examples/mvc/views/5xx.jade +++ /dev/null @@ -1,3 +0,0 @@ -link(rel='stylesheet', href='http://github.com/style.css') -h1 500: Internal Server Error -p Looks like something blew up! diff --git a/package.json b/package.json index 42fd1ca46be..8c1d415f212 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "cookie-parser": "~1.4.3", "ejs": "2.5.6", "express-session": "1.15.1", + "hbs": "4.0.1", "istanbul": "0.4.5", "marked": "0.3.6", "method-override": "2.3.7", @@ -73,7 +74,6 @@ "supertest": "1.2.0", "connect-redis": "~2.4.1", "cookie-session": "~1.2.0", - "jade": "~1.11.0", "vhost": "~3.0.2" }, "engines": { From aabf7802a979f44cf75ffac2978724935d064fec Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Fri, 24 Mar 2017 08:53:03 +0000 Subject: [PATCH 225/889] docs: fix the security issues heading format closes #3256 --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 7b261a3d94d..786756a1cd2 100644 --- a/Readme.md +++ b/Readme.md @@ -46,7 +46,7 @@ $ npm install express **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x). -###Security Issues +### Security Issues If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). From 347d4db3cac2979d639cb2be161ba01c9b2336d2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 28 Mar 2017 22:56:32 -0400 Subject: [PATCH 226/889] deps: proxy-addr@~1.1.4 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index a8647e2484a..8e80d0e5ee7 100644 --- a/History.md +++ b/History.md @@ -6,6 +6,8 @@ unreleased * deps: finalhandler@~1.0.1 - Fix missing `` in HTML document - deps: debug@2.6.3 + * deps: proxy-addr@~1.1.4 + - deps: ipaddr.js@1.3.0 * deps: vary@~1.1.1 - perf: hoist regular expression diff --git a/package.json b/package.json index 8c1d415f212..940c58d1bef 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", - "proxy-addr": "~1.1.3", + "proxy-addr": "~1.1.4", "qs": "6.4.0", "range-parser": "~1.2.0", "send": "0.15.1", From c087a45b9cc3eb69c777e260ee880758b6e03a40 Mon Sep 17 00:00:00 2001 From: asaf david Date: Fri, 31 Mar 2017 15:57:28 +0300 Subject: [PATCH 227/889] Fix typo in variable name setPrototypeOf closes #3266 --- lib/application.js | 14 +++++++------- lib/middleware/init.js | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/application.js b/lib/application.js index 21a81ee9efe..1abe8d08f58 100644 --- a/lib/application.js +++ b/lib/application.js @@ -28,7 +28,7 @@ var deprecate = require('depd')('express'); var flatten = require('array-flatten'); var merge = require('utils-merge'); var resolve = require('path').resolve; -var setPrototyeOf = require('setprototypeof') +var setPrototypeOf = require('setprototypeof') var slice = Array.prototype.slice; /** @@ -95,10 +95,10 @@ app.defaultConfiguration = function defaultConfiguration() { } // inherit protos - setPrototyeOf(this.request, parent.request) - setPrototyeOf(this.response, parent.response) - setPrototyeOf(this.engines, parent.engines) - setPrototyeOf(this.settings, parent.settings) + setPrototypeOf(this.request, parent.request) + setPrototypeOf(this.response, parent.response) + setPrototypeOf(this.engines, parent.engines) + setPrototypeOf(this.settings, parent.settings) }); // setup locals @@ -228,8 +228,8 @@ app.use = function use(fn) { router.use(path, function mounted_app(req, res, next) { var orig = req.app; fn.handle(req, res, function (err) { - setPrototyeOf(req, orig.request) - setPrototyeOf(res, orig.response) + setPrototypeOf(req, orig.request) + setPrototypeOf(res, orig.response) next(err); }); }); diff --git a/lib/middleware/init.js b/lib/middleware/init.js index 328c4a863d9..dfd042747bd 100644 --- a/lib/middleware/init.js +++ b/lib/middleware/init.js @@ -13,7 +13,7 @@ * @private */ -var setPrototyeOf = require('setprototypeof') +var setPrototypeOf = require('setprototypeof') /** * Initialization middleware, exposing the @@ -32,8 +32,8 @@ exports.init = function(app){ res.req = req; req.next = next; - setPrototyeOf(req, app.request) - setPrototyeOf(res, app.response) + setPrototypeOf(req, app.request) + setPrototypeOf(res, app.response) res.locals = res.locals || Object.create(null); From df4f2719db909ab333d8173f57a96bc213680c2a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 26 Apr 2017 23:49:41 -0400 Subject: [PATCH 228/889] deps: type-is@~1.6.15 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 8e80d0e5ee7..336e7428c91 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,8 @@ unreleased - deps: debug@2.6.3 * deps: proxy-addr@~1.1.4 - deps: ipaddr.js@1.3.0 + * deps: type-is@~1.6.15 + - deps: mime-types@~2.1.15 * deps: vary@~1.1.1 - perf: hoist regular expression diff --git a/package.json b/package.json index 940c58d1bef..3ce5dc3cbc2 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "serve-static": "1.12.1", "setprototypeof": "1.0.3", "statuses": "~1.3.1", - "type-is": "~1.6.14", + "type-is": "~1.6.15", "utils-merge": "1.0.0", "vary": "~1.1.1" }, From 2d1dade36a867dcd68a2169270d524d73a3b92eb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 27 Apr 2017 00:00:57 -0400 Subject: [PATCH 229/889] deps: serve-static@1.12.2 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 336e7428c91..f6bd295727a 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,8 @@ unreleased - deps: debug@2.6.3 * deps: proxy-addr@~1.1.4 - deps: ipaddr.js@1.3.0 + * deps: serve-static@1.12.2 + - deps: send@0.15.2 * deps: type-is@~1.6.15 - deps: mime-types@~2.1.15 * deps: vary@~1.1.1 diff --git a/package.json b/package.json index 3ce5dc3cbc2..9dcc7266c73 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "qs": "6.4.0", "range-parser": "~1.2.0", "send": "0.15.1", - "serve-static": "1.12.1", + "serve-static": "1.12.2", "setprototypeof": "1.0.3", "statuses": "~1.3.1", "type-is": "~1.6.15", From 1b6e7004b7e46a7c9fd3f53cd408debbcb689367 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 27 Apr 2017 01:11:58 -0400 Subject: [PATCH 230/889] deps: send@0.15.2 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index f6bd295727a..10b15b2b6a0 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,9 @@ unreleased - deps: debug@2.6.3 * deps: proxy-addr@~1.1.4 - deps: ipaddr.js@1.3.0 + * deps: send@0.15.2 + - deps: debug@2.6.4 + - deps: ms@1.0.0 * deps: serve-static@1.12.2 - deps: send@0.15.2 * deps: type-is@~1.6.15 diff --git a/package.json b/package.json index 9dcc7266c73..1fbff92544f 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "proxy-addr": "~1.1.4", "qs": "6.4.0", "range-parser": "~1.2.0", - "send": "0.15.1", + "send": "0.15.2", "serve-static": "1.12.2", "setprototypeof": "1.0.3", "statuses": "~1.3.1", From a13938eed7b67ce13b86a45c7b0f2ae766a3166d Mon Sep 17 00:00:00 2001 From: Colin Richardson Date: Thu, 27 Apr 2017 19:51:38 +0100 Subject: [PATCH 231/889] tests: add tests for res.location('back') closes #3292 closes #3293 --- test/res.location.js | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/res.location.js b/test/res.location.js index bb9eb6f92e3..c0bfbe8c8ec 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -42,5 +42,63 @@ describe('res', function(){ .expect('Location', 'https://google.com/?q=%A710') .expect(200, done) }) + + describe('when url is "back"', function () { + it('should set location from "Referer" header', function (done) { + var app = express() + + app.use(function (req, res) { + res.location('back').end() + }) + + request(app) + .get('/') + .set('Referer', '/some/page.html') + .expect('Location', '/some/page.html') + .expect(200, done) + }) + + it('should set location from "Referrer" header', function (done) { + var app = express() + + app.use(function (req, res) { + res.location('back').end() + }) + + request(app) + .get('/') + .set('Referrer', '/some/page.html') + .expect('Location', '/some/page.html') + .expect(200, done) + }) + + it('should prefer "Referrer" header', function (done) { + var app = express() + + app.use(function (req, res) { + res.location('back').end() + }) + + request(app) + .get('/') + .set('Referer', '/some/page1.html') + .set('Referrer', '/some/page2.html') + .expect('Location', '/some/page2.html') + .expect(200, done) + }) + + it('should set the header to "/" without referrer', function (done) { + var app = express() + + app.use(function (req, res) { + res.location('back').end() + }) + + request(app) + .get('/') + .expect('Location', '/') + .expect(200, done) + }) + }) }) }) From de41c0bfa4fc9ff78fb5f0f72daf5e83e53a93ae Mon Sep 17 00:00:00 2001 From: Tony Anisimov Date: Tue, 9 May 2017 23:35:20 +0300 Subject: [PATCH 232/889] Fix res.cookie jsdoc comment closes #3304 --- lib/response.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/response.js b/lib/response.js index 6aefe1b1782..f3f043f5cd6 100644 --- a/lib/response.js +++ b/lib/response.js @@ -777,7 +777,7 @@ res.clearCookie = function clearCookie(name, options) { * * @param {String} name * @param {String|Object} value - * @param {Options} options + * @param {Object} [options] * @return {ServerResponse} for chaining * @public */ From 5ea2a8ff8e78349484d2887db2f10a94ec79b8d7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 14 May 2017 23:29:13 -0400 Subject: [PATCH 233/889] build: Node.js@7.9 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1230c7e2f95..b4beea77f36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ node_js: - "4.8" - "5.12" - "6.10" - - "7.6" + - "7.9" matrix: include: - node_js: "8.0" diff --git a/appveyor.yml b/appveyor.yml index b4bb184dd8f..cd4f9d23e5e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ environment: - nodejs_version: "4.8" - nodejs_version: "5.12" - nodejs_version: "6.10" - - nodejs_version: "7.6" + - nodejs_version: "7.9" cache: - node_modules install: From ae0b630ac7e8f34e4ea37285f30db4b52adf8436 Mon Sep 17 00:00:00 2001 From: Oz Michaeli Date: Wed, 10 May 2017 16:23:55 -0400 Subject: [PATCH 234/889] Fix error when res.set cannot add charset to Content-Type fixes #3303 closes #3305 closes #3307 --- History.md | 1 + lib/response.js | 11 ++++++++--- test/res.set.js | 13 +++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 10b15b2b6a0..cbf13eb837e 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Fix error when `res.set` cannot add charset to `Content-Type` * deps: debug@2.6.3 - Fix: `DEBUG_MAX_ARRAY_LENGTH` * deps: finalhandler@~1.0.1 diff --git a/lib/response.js b/lib/response.js index f3f043f5cd6..b852a60e2f5 100644 --- a/lib/response.js +++ b/lib/response.js @@ -717,9 +717,14 @@ res.header = function header(field, val) { : 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(); + if (field.toLowerCase() === 'content-type') { + if (Array.isArray(value)) { + throw new TypeError('Content-Type cannot be set to an Array'); + } + if (!charsetRegExp.test(value)) { + var charset = mime.charsets.lookup(value.split(';')[0]); + if (charset) value += '; charset=' + charset.toLowerCase(); + } } this.setHeader(field, value); diff --git a/test/res.set.js b/test/res.set.js index b15bc5d7e3d..e46d123947a 100644 --- a/test/res.set.js +++ b/test/res.set.js @@ -73,6 +73,19 @@ describe('res', function(){ .expect('Content-Type', 'text/html; charset=lol') .expect(200, done); }) + + it('should throw when Content-Type is an array', function (done) { + var app = express() + + app.use(function (req, res) { + res.set('Content-Type', ['text/html']) + res.end() + }); + + request(app) + .get('/') + .expect(500, /TypeError: Content-Type cannot be set to an Array/, done) + }) }) describe('.set(object)', function(){ From 1ba9a9ac23e48cc7295a53919953e1b3f0b0ea7f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 May 2017 01:28:21 -0400 Subject: [PATCH 235/889] deps: update example dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 1fbff92544f..67a20144c35 100644 --- a/package.json +++ b/package.json @@ -61,11 +61,11 @@ "body-parser": "1.17.1", "cookie-parser": "~1.4.3", "ejs": "2.5.6", - "express-session": "1.15.1", + "express-session": "1.15.2", "hbs": "4.0.1", "istanbul": "0.4.5", "marked": "0.3.6", - "method-override": "2.3.7", + "method-override": "2.3.8", "mocha": "3.2.0", "morgan": "1.8.1", "multiparty": "4.1.3", From ad4456c491fc2ecd8358fd3958da5c0a95c2c3ab Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 May 2017 01:46:34 -0400 Subject: [PATCH 236/889] deps: send@0.15.3 --- History.md | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index cbf13eb837e..b62e24b6e6b 100644 --- a/History.md +++ b/History.md @@ -9,9 +9,9 @@ unreleased - deps: debug@2.6.3 * deps: proxy-addr@~1.1.4 - deps: ipaddr.js@1.3.0 - * deps: send@0.15.2 - - deps: debug@2.6.4 - - deps: ms@1.0.0 + * deps: send@0.15.3 + - deps: debug@2.6.7 + - deps: ms@2.0.0 * deps: serve-static@1.12.2 - deps: send@0.15.2 * deps: type-is@~1.6.15 diff --git a/package.json b/package.json index 67a20144c35..6e2c5995c8d 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "proxy-addr": "~1.1.4", "qs": "6.4.0", "range-parser": "~1.2.0", - "send": "0.15.2", + "send": "0.15.3", "serve-static": "1.12.2", "setprototypeof": "1.0.3", "statuses": "~1.3.1", From 58cfc9911b5f1e67397ba481535320a1c3b9e954 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 May 2017 01:47:17 -0400 Subject: [PATCH 237/889] deps: serve-static@1.12.3 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index b62e24b6e6b..0ebb6ea31a2 100644 --- a/History.md +++ b/History.md @@ -12,8 +12,8 @@ unreleased * deps: send@0.15.3 - deps: debug@2.6.7 - deps: ms@2.0.0 - * deps: serve-static@1.12.2 - - deps: send@0.15.2 + * deps: serve-static@1.12.3 + - deps: send@0.15.3 * deps: type-is@~1.6.15 - deps: mime-types@~2.1.15 * deps: vary@~1.1.1 diff --git a/package.json b/package.json index 6e2c5995c8d..d9f003e8531 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "qs": "6.4.0", "range-parser": "~1.2.0", "send": "0.15.3", - "serve-static": "1.12.2", + "serve-static": "1.12.3", "setprototypeof": "1.0.3", "statuses": "~1.3.1", "type-is": "~1.6.15", From bc2986fe59c233ac58d981e620fddd4c58b55c9b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 May 2017 01:56:36 -0400 Subject: [PATCH 238/889] deps: finalhandler@~1.0.3 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 0ebb6ea31a2..4ca0255a6cd 100644 --- a/History.md +++ b/History.md @@ -4,9 +4,9 @@ unreleased * Fix error when `res.set` cannot add charset to `Content-Type` * deps: debug@2.6.3 - Fix: `DEBUG_MAX_ARRAY_LENGTH` - * deps: finalhandler@~1.0.1 + * deps: finalhandler@~1.0.3 - Fix missing `` in HTML document - - deps: debug@2.6.3 + - deps: debug@2.6.7 * deps: proxy-addr@~1.1.4 - deps: ipaddr.js@1.3.0 * deps: send@0.15.3 diff --git a/package.json b/package.json index d9f003e8531..f469ca5a713 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.8.0", - "finalhandler": "~1.0.1", + "finalhandler": "~1.0.3", "fresh": "0.5.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", From 65494692c2d83bb99586166afe463ba1177dbbdb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 May 2017 01:57:31 -0400 Subject: [PATCH 239/889] build: mocha@3.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f469ca5a713..ac2f32d6796 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "istanbul": "0.4.5", "marked": "0.3.6", "method-override": "2.3.8", - "mocha": "3.2.0", + "mocha": "3.4.1", "morgan": "1.8.1", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", From 5cf473dc5d51c66a0cd373f4eca469505dfa4f32 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 May 2017 02:08:50 -0400 Subject: [PATCH 240/889] deps: debug@2.6.7 --- History.md | 5 +++-- package.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 4ca0255a6cd..2222778710b 100644 --- a/History.md +++ b/History.md @@ -2,8 +2,9 @@ unreleased ========== * Fix error when `res.set` cannot add charset to `Content-Type` - * deps: debug@2.6.3 - - Fix: `DEBUG_MAX_ARRAY_LENGTH` + * deps: debug@2.6.7 + - Fix `DEBUG_MAX_ARRAY_LENGTH` + - deps: ms@2.0.0 * deps: finalhandler@~1.0.3 - Fix missing `` in HTML document - deps: debug@2.6.7 diff --git a/package.json b/package.json index ac2f32d6796..4acb1ff2e58 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "content-type": "~1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", - "debug": "2.6.3", + "debug": "2.6.7", "depd": "~1.1.0", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", From 6da454c7fb37e68ed65ffe0371aa688b89f5bd6e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 17 May 2017 02:14:11 -0400 Subject: [PATCH 241/889] 4.15.3 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 2222778710b..83b439c63e8 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.15.3 / 2017-05-16 +=================== * Fix error when `res.set` cannot add charset to `Content-Type` * deps: debug@2.6.7 diff --git a/package.json b/package.json index 4acb1ff2e58..98adaea686a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.15.2", + "version": "4.15.3", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From fde8f647d368df1dc62d55ce4d68370ef3eb0a49 Mon Sep 17 00:00:00 2001 From: Owen Luke Date: Wed, 17 May 2017 16:00:49 +0800 Subject: [PATCH 242/889] examples: fix route in params example closes #3310 --- examples/params/index.js | 2 +- test/acceptance/params.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/params/index.js b/examples/params/index.js index d70f0beeeb1..f918b5fd30d 100644 --- a/examples/params/index.js +++ b/examples/params/index.js @@ -68,7 +68,7 @@ app.get('/users/:from-:to', function(req, res, next){ var from = req.params.from; var to = req.params.to; var names = users.map(function(user){ return user.name; }); - res.send('users ' + names.slice(from, to).join(', ')); + res.send('users ' + names.slice(from, to + 1).join(', ')); }); /* istanbul ignore next */ diff --git a/test/acceptance/params.js b/test/acceptance/params.js index 56b7a72ce0f..e7c30cf7732 100644 --- a/test/acceptance/params.js +++ b/test/acceptance/params.js @@ -29,8 +29,8 @@ describe('params', function(){ describe('GET /users/0-2', function(){ it('should respond with three users', function(done){ request(app) - .get('/users/0-2') - .expect(/users tj, tobi/,done) + .get('/users/0-2') + .expect(/users tj, tobi, loki/, done) }) }) From 60f87f8074c28a1727305530058d8c2c9596387c Mon Sep 17 00:00:00 2001 From: Owen Luke Date: Wed, 17 May 2017 17:04:10 +0800 Subject: [PATCH 243/889] examples: fix posts link in route-separation example closes #3310 --- examples/route-separation/views/index.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/route-separation/views/index.ejs b/examples/route-separation/views/index.ejs index 6d1afb4ac3d..2a0b095fa36 100644 --- a/examples/route-separation/views/index.ejs +++ b/examples/route-separation/views/index.ejs @@ -4,7 +4,7 @@ <% include footer %> From cf37240e7306c5085f3d2a232a4649279d020667 Mon Sep 17 00:00:00 2001 From: Owen Luke Date: Wed, 17 May 2017 17:10:38 +0800 Subject: [PATCH 244/889] examples: fix reference error in view-constructor closes #3310 --- examples/view-constructor/github-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/view-constructor/github-view.js b/examples/view-constructor/github-view.js index 53890291056..0a98a908434 100644 --- a/examples/view-constructor/github-view.js +++ b/examples/view-constructor/github-view.js @@ -2,7 +2,7 @@ * Module dependencies. */ -var http = require('http'); +var https = require('https'); var path = require('path'); var extname = path.extname; From 9f019c8c6966736803a65eb4a96d0e7e87e85ede Mon Sep 17 00:00:00 2001 From: Owen Luke Date: Wed, 17 May 2017 23:55:27 +0800 Subject: [PATCH 245/889] examples: add comment about Redis install in examples closes #3310 --- examples/online/index.js | 6 +++++- examples/search/index.js | 6 +++++- examples/session/index.js | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/examples/online/index.js b/examples/online/index.js index 5cdaa6ca8d2..f14474c08d3 100644 --- a/examples/online/index.js +++ b/examples/online/index.js @@ -1,4 +1,8 @@ -// first: + +// install redis first: +// https://redis.io/ + +// then: // $ npm install redis online // $ redis-server diff --git a/examples/search/index.js b/examples/search/index.js index 79f5d9f4d36..246993caa5a 100644 --- a/examples/search/index.js +++ b/examples/search/index.js @@ -1,4 +1,8 @@ -// first: + +// install redis first: +// https://redis.io/ + +// then: // $ npm install redis // $ redis-server diff --git a/examples/session/index.js b/examples/session/index.js index de41a77d2c0..9bae48b8d33 100644 --- a/examples/session/index.js +++ b/examples/session/index.js @@ -1,4 +1,8 @@ -// first: + +// install redis first: +// https://redis.io/ + +// then: // $ npm install redis // $ redis-server From 9467a392e33ad1575f2d76aad5fc19f9290d6cd6 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 4 Jun 2017 19:09:25 -0400 Subject: [PATCH 246/889] build: Node.js@7.10 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b4beea77f36..c9172c302ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ node_js: - "4.8" - "5.12" - "6.10" - - "7.9" + - "7.10" matrix: include: - node_js: "8.0" diff --git a/appveyor.yml b/appveyor.yml index cd4f9d23e5e..9fbc9d39a38 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ environment: - nodejs_version: "4.8" - nodejs_version: "5.12" - nodejs_version: "6.10" - - nodejs_version: "7.9" + - nodejs_version: "7.10" cache: - node_modules install: From 48777dc37774eaa2c328a1d9bb9541dfa47ca90f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 4 Jun 2017 19:12:30 -0400 Subject: [PATCH 247/889] build: mocha@3.4.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 98adaea686a..1788e9ffd16 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "istanbul": "0.4.5", "marked": "0.3.6", "method-override": "2.3.8", - "mocha": "3.4.1", + "mocha": "3.4.2", "morgan": "1.8.1", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", From deffce5704913df9e6b00aca5536345610222417 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 30 Jun 2017 23:47:12 -0400 Subject: [PATCH 248/889] deps: qs@6.5.0 --- History.md | 5 +++++ lib/middleware/query.js | 3 ++- package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 83b439c63e8..36fadc4b990 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * deps: qs@6.5.0 + 4.15.3 / 2017-05-16 =================== diff --git a/lib/middleware/query.js b/lib/middleware/query.js index 5f76f8458f0..7e9166947af 100644 --- a/lib/middleware/query.js +++ b/lib/middleware/query.js @@ -12,6 +12,7 @@ * Module dependencies. */ +var merge = require('utils-merge') var parseUrl = require('parseurl'); var qs = require('qs'); @@ -22,7 +23,7 @@ var qs = require('qs'); */ module.exports = function query(options) { - var opts = Object.create(options || null); + var opts = merge({}, options) var queryparse = qs.parse; if (typeof options === 'function') { diff --git a/package.json b/package.json index 1788e9ffd16..cb37b98a7f5 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.4", - "qs": "6.4.0", + "qs": "6.5.0", "range-parser": "~1.2.0", "send": "0.15.3", "serve-static": "1.12.3", From bd5951e603c16c1db779a76bc5e500c243f96cf8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 30 Jun 2017 23:51:18 -0400 Subject: [PATCH 249/889] deps: debug@2.6.8 closes #3286 closes #3337 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 36fadc4b990..59663eb712d 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * deps: debug@2.6.8 * deps: qs@6.5.0 4.15.3 / 2017-05-16 diff --git a/package.json b/package.json index cb37b98a7f5..674c8601ab0 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "content-type": "~1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", - "debug": "2.6.7", + "debug": "2.6.8", "depd": "~1.1.0", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", From 1adee79e636400c734f2307c1ef4fb0fff5db92b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 30 Jun 2017 23:58:01 -0400 Subject: [PATCH 250/889] deps: update example dependencies --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 674c8601ab0..7f401132cae 100644 --- a/package.json +++ b/package.json @@ -58,16 +58,16 @@ }, "devDependencies": { "after": "0.8.2", - "body-parser": "1.17.1", + "body-parser": "1.17.2", "cookie-parser": "~1.4.3", "ejs": "2.5.6", - "express-session": "1.15.2", + "express-session": "1.15.3", "hbs": "4.0.1", "istanbul": "0.4.5", "marked": "0.3.6", - "method-override": "2.3.8", + "method-override": "2.3.9", "mocha": "3.4.2", - "morgan": "1.8.1", + "morgan": "1.8.2", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", "should": "11.2.1", From 04beebb2c087e3b9795d6f1c3d0bd1112bf1f244 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 26 Jul 2017 11:52:42 -0400 Subject: [PATCH 251/889] build: Node.js@6.11 --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c9172c302ca..3e899dd2351 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ node_js: - "3.3" - "4.8" - "5.12" - - "6.10" + - "6.11" - "7.10" matrix: include: diff --git a/appveyor.yml b/appveyor.yml index 9fbc9d39a38..ed8d4aa9f05 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ environment: - nodejs_version: "3.3" - nodejs_version: "4.8" - nodejs_version: "5.12" - - nodejs_version: "6.10" + - nodejs_version: "6.11" - nodejs_version: "7.10" cache: - node_modules From 43dff4ceb3446397aa3fe8c48b2de67b9e76a031 Mon Sep 17 00:00:00 2001 From: Piper Chester Date: Tue, 27 Jun 2017 11:48:08 +0200 Subject: [PATCH 252/889] docs: fix GitHub capitalization closes #3353 --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 786756a1cd2..17326615776 100644 --- a/Readme.md +++ b/Readme.md @@ -39,7 +39,7 @@ $ npm install express * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)] * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC - * [Github Organization](https://github.com/expressjs) for Official Middleware & Modules + * [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules * Visit the [Wiki](https://github.com/expressjs/express/wiki) * [Google Group](https://groups.google.com/group/express-js) for discussion * [Gitter](https://gitter.im/expressjs/express) for support and discussion From 5e16f400f17ca4bac48226446b09299e392db3b2 Mon Sep 17 00:00:00 2001 From: Owen Luke Date: Fri, 19 May 2017 00:18:28 +0800 Subject: [PATCH 253/889] examples: use 1-based visitor count in cookie-sessions closes #3312 --- examples/cookie-sessions/index.js | 5 ++--- test/acceptance/cookie-sessions.js | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/cookie-sessions/index.js b/examples/cookie-sessions/index.js index 73653f63af9..1dda15de612 100644 --- a/examples/cookie-sessions/index.js +++ b/examples/cookie-sessions/index.js @@ -15,9 +15,8 @@ app.use(count); // custom middleware function count(req, res) { - req.session.count = req.session.count || 0; - var n = req.session.count++; - res.send('viewed ' + n + ' times\n'); + req.session.count = (req.session.count || 0) + 1 + res.send('viewed ' + req.session.count + ' times\n') } /* istanbul ignore next */ diff --git a/test/acceptance/cookie-sessions.js b/test/acceptance/cookie-sessions.js index 611ebe462a2..d438cfe6d5d 100644 --- a/test/acceptance/cookie-sessions.js +++ b/test/acceptance/cookie-sessions.js @@ -7,7 +7,7 @@ describe('cookie-sessions', function () { it('should display no views', function (done) { request(app) .get('/') - .expect(200, 'viewed 0 times\n', done) + .expect(200, 'viewed 1 times\n', done) }) it('should set a session cookie', function (done) { @@ -20,12 +20,12 @@ describe('cookie-sessions', function () { it('should display 1 view on revisit', function (done) { request(app) .get('/') - .expect(200, 'viewed 0 times\n', function (err, res) { + .expect(200, 'viewed 1 times\n', function (err, res) { if (err) return done(err) request(app) .get('/') .set('Cookie', getCookies(res)) - .expect(200, 'viewed 1 times\n', done) + .expect(200, 'viewed 2 times\n', done) }) }) }) From 582381bcebf2a2344e7e054eed9606cc2221dd97 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 26 Jul 2017 13:09:46 -0400 Subject: [PATCH 254/889] deps: proxy-addr@~1.1.5 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 59663eb712d..a724e84231f 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,9 @@ unreleased ========== * deps: debug@2.6.8 + * deps: proxy-addr@~1.1.5 + - Fix array argument being altered + - deps: ipaddr.js@1.4.0 * deps: qs@6.5.0 4.15.3 / 2017-05-16 diff --git a/package.json b/package.json index 7f401132cae..daf1f1feb1f 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", - "proxy-addr": "~1.1.4", + "proxy-addr": "~1.1.5", "qs": "6.5.0", "range-parser": "~1.2.0", "send": "0.15.3", From 3eb16c233c5bf76fb12558101565971372693c73 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 2 Aug 2017 23:30:47 -0400 Subject: [PATCH 255/889] deps: depd@~1.1.1 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index a724e84231f..af2bcfb384c 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,8 @@ unreleased ========== * deps: debug@2.6.8 + * deps: depd@~1.1.1 + - Remove unnecessary `Buffer` loading * deps: proxy-addr@~1.1.5 - Fix array argument being altered - deps: ipaddr.js@1.4.0 diff --git a/package.json b/package.json index daf1f1feb1f..0a3848134fd 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.8", - "depd": "~1.1.0", + "depd": "~1.1.1", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.8.0", From b2af1018215540964390aab0c739c1e688865122 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 2 Aug 2017 23:32:44 -0400 Subject: [PATCH 256/889] build: ejs@2.5.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a3848134fd..c14b8126b11 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "after": "0.8.2", "body-parser": "1.17.2", "cookie-parser": "~1.4.3", - "ejs": "2.5.6", + "ejs": "2.5.7", "express-session": "1.15.3", "hbs": "4.0.1", "istanbul": "0.4.5", From daf66beda49ebac6086b81dd1896a34395306a71 Mon Sep 17 00:00:00 2001 From: Hung HOANG Date: Thu, 3 Aug 2017 11:33:29 +0200 Subject: [PATCH 257/889] examples: fix path join in ejs example fixes #3382 closes #3383 closes #3385 --- examples/ejs/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ejs/index.js b/examples/ejs/index.js index b868bdd7cb9..72780912938 100644 --- a/examples/ejs/index.js +++ b/examples/ejs/index.js @@ -26,7 +26,7 @@ app.set('views', path.join(__dirname, 'views')); // Path to our public directory -app.use(express.static(path.join(__dirname + 'public'))); +app.use(express.static(path.join(__dirname, 'public'))); // Without this you would need to // supply the extension to res.render() From 85770a71fc3f3c7f3a1efe3e01d9f0c5fd68f82e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 4 Aug 2017 00:25:59 -0400 Subject: [PATCH 258/889] deps: finalhandler@~1.0.4 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index af2bcfb384c..c67fd941745 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,8 @@ unreleased * deps: debug@2.6.8 * deps: depd@~1.1.1 - Remove unnecessary `Buffer` loading + * deps: finalhandler@~1.0.4 + - deps: debug@2.6.8 * deps: proxy-addr@~1.1.5 - Fix array argument being altered - deps: ipaddr.js@1.4.0 diff --git a/package.json b/package.json index c14b8126b11..839f370cbcb 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.8.0", - "finalhandler": "~1.0.3", + "finalhandler": "~1.0.4", "fresh": "0.5.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", From e0aa8bf74eed76df4e5cf02005233d9de2401348 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 4 Aug 2017 00:26:50 -0400 Subject: [PATCH 259/889] build: mocha@3.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 839f370cbcb..15e80f1934b 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "istanbul": "0.4.5", "marked": "0.3.6", "method-override": "2.3.9", - "mocha": "3.4.2", + "mocha": "3.5.0", "morgan": "1.8.2", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", From 713d2aed93586a7c11fc2c8beeaa0c03c6f565c9 Mon Sep 17 00:00:00 2001 From: Daniel Walasek Date: Sat, 5 Aug 2017 12:42:45 +0200 Subject: [PATCH 260/889] tests: fix incorrect should usage closes #3387 --- test/Route.js | 14 +++++++------- test/Router.js | 2 +- test/app.js | 4 ++-- test/app.param.js | 6 +++--- test/app.render.js | 2 +- test/app.routes.error.js | 8 ++++---- test/exports.js | 8 ++++---- test/req.acceptsEncoding.js | 6 +++--- test/req.acceptsEncodings.js | 6 +++--- test/req.acceptsLanguage.js | 12 ++++++------ test/req.acceptsLanguages.js | 12 ++++++------ test/req.xhr.js | 8 ++++---- test/res.sendFile.js | 14 +++++++------- 13 files changed, 51 insertions(+), 51 deletions(-) diff --git a/test/Route.js b/test/Route.js index ada54086bf0..d7a80bdbc01 100644 --- a/test/Route.js +++ b/test/Route.js @@ -25,7 +25,7 @@ describe('Route', function(){ route.dispatch(req, {}, function (err) { if (err) return done(err); - should(req.called).be.ok; + should(req.called).be.ok() done(); }); }) @@ -84,7 +84,7 @@ describe('Route', function(){ route.dispatch(req, {}, function (err) { if (err) return done(err); - should(req.called).be.ok; + should(req.called).be.ok() done(); }); }) @@ -104,7 +104,7 @@ describe('Route', function(){ route.dispatch(req, {}, function (err) { if (err) return done(err); - should(req.called).be.true; + should(req.called).be.true() done(); }); }) @@ -156,7 +156,7 @@ describe('Route', function(){ }); route.dispatch(req, {}, function (err) { - should(err).be.ok; + should(err).be.ok() should(err.message).equal('foobar'); req.order.should.equal('a'); done(); @@ -182,7 +182,7 @@ describe('Route', function(){ }); route.dispatch(req, {}, function (err) { - should(err).be.ok; + should(err).be.ok() should(err.message).equal('foobar'); req.order.should.equal('a'); done(); @@ -222,7 +222,7 @@ describe('Route', function(){ }); route.dispatch(req, {}, function(err){ - should(err).be.ok; + should(err).be.ok() err.message.should.equal('boom!'); done(); }); @@ -234,7 +234,7 @@ describe('Route', function(){ route.all(function(err, req, res, next){ // this should not execute - true.should.be.false; + true.should.be.false() }); route.dispatch(req, {}, done); diff --git a/test/Router.js b/test/Router.js index 01a6e2c472b..18153d29267 100644 --- a/test/Router.js +++ b/test/Router.js @@ -47,7 +47,7 @@ describe('Router', function(){ var router = new Router(); router.use(function (req, res) { - false.should.be.true; + false.should.be.true() }); router.handle({ url: '', method: 'GET' }, {}, done); diff --git a/test/app.js b/test/app.js index 941d35ff1cc..e52365c36bb 100644 --- a/test/app.js +++ b/test/app.js @@ -86,7 +86,7 @@ describe('in development', function(){ it('should disable "view cache"', function(){ process.env.NODE_ENV = 'development'; var app = express(); - app.enabled('view cache').should.be.false; + app.enabled('view cache').should.be.false() process.env.NODE_ENV = 'test'; }) }) @@ -95,7 +95,7 @@ describe('in production', function(){ it('should enable "view cache"', function(){ process.env.NODE_ENV = 'production'; var app = express(); - app.enabled('view cache').should.be.true; + app.enabled('view cache').should.be.true() process.env.NODE_ENV = 'test'; }) }) diff --git a/test/app.param.js b/test/app.param.js index c7a375418cd..ba43e46f8e3 100644 --- a/test/app.param.js +++ b/test/app.param.js @@ -57,13 +57,13 @@ describe('app', function(){ app.get('/post/:id', function(req, res){ var id = req.params.id; - id.should.be.a.Number; + id.should.be.a.Number() res.send('' + id); }); app.get('/user/:uid', function(req, res){ var id = req.params.id; - id.should.be.a.Number; + id.should.be.a.Number() res.send('' + id); }); @@ -91,7 +91,7 @@ describe('app', function(){ app.get('/user/:id', function(req, res){ var id = req.params.id; - id.should.be.a.Number; + id.should.be.a.Number() res.send('' + id); }); diff --git a/test/app.render.js b/test/app.render.js index 729b1c97cc8..1485098f582 100644 --- a/test/app.render.js +++ b/test/app.render.js @@ -72,7 +72,7 @@ describe('app', function(){ app.set('view', View); app.render('something', function(err, str){ - err.should.be.ok; + err.should.be.ok() err.message.should.equal('err!'); done(); }) diff --git a/test/app.routes.error.js b/test/app.routes.error.js index 7c49d50ffe2..cbbc23ef574 100644 --- a/test/app.routes.error.js +++ b/test/app.routes.error.js @@ -44,10 +44,10 @@ describe('app', function(){ d = true; next(); }, function(req, res){ - a.should.be.false; - b.should.be.true; - c.should.be.true; - d.should.be.false; + a.should.be.false() + b.should.be.true() + c.should.be.true() + d.should.be.false() res.send(204); }); diff --git a/test/exports.js b/test/exports.js index d34a7b1cf3e..2a80eedbbe8 100644 --- a/test/exports.js +++ b/test/exports.js @@ -5,19 +5,19 @@ var should = require('should'); describe('exports', function(){ it('should expose Router', function(){ - express.Router.should.be.a.Function; + express.Router.should.be.a.Function() }) it('should expose the application prototype', function(){ - express.application.set.should.be.a.Function; + express.application.set.should.be.a.Function() }) it('should expose the request prototype', function(){ - express.request.accepts.should.be.a.Function; + express.request.accepts.should.be.a.Function() }) it('should expose the response prototype', function(){ - express.response.send.should.be.a.Function; + express.response.send.should.be.a.Function() }) it('should permit modifying the .application prototype', function(){ diff --git a/test/req.acceptsEncoding.js b/test/req.acceptsEncoding.js index 12708fc0144..9ed9197829f 100644 --- a/test/req.acceptsEncoding.js +++ b/test/req.acceptsEncoding.js @@ -8,8 +8,8 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsEncoding('gzip').should.be.ok; - req.acceptsEncoding('deflate').should.be.ok; + req.acceptsEncoding('gzip').should.be.ok() + req.acceptsEncoding('deflate').should.be.ok() res.end(); }); @@ -23,7 +23,7 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsEncoding('bogus').should.not.be.ok; + req.acceptsEncoding('bogus').should.not.be.ok() res.end(); }); diff --git a/test/req.acceptsEncodings.js b/test/req.acceptsEncodings.js index c036c297691..aba8ea5fbeb 100644 --- a/test/req.acceptsEncodings.js +++ b/test/req.acceptsEncodings.js @@ -8,8 +8,8 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsEncodings('gzip').should.be.ok; - req.acceptsEncodings('deflate').should.be.ok; + req.acceptsEncodings('gzip').should.be.ok() + req.acceptsEncodings('deflate').should.be.ok() res.end(); }); @@ -23,7 +23,7 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsEncodings('bogus').should.not.be.ok; + req.acceptsEncodings('bogus').should.not.be.ok() res.end(); }); diff --git a/test/req.acceptsLanguage.js b/test/req.acceptsLanguage.js index b14d920bd69..1c7c5fd86f6 100644 --- a/test/req.acceptsLanguage.js +++ b/test/req.acceptsLanguage.js @@ -8,8 +8,8 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsLanguage('en-us').should.be.ok; - req.acceptsLanguage('en').should.be.ok; + req.acceptsLanguage('en-us').should.be.ok() + req.acceptsLanguage('en').should.be.ok() res.end(); }); @@ -23,7 +23,7 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsLanguage('es').should.not.be.ok; + req.acceptsLanguage('es').should.not.be.ok() res.end(); }); @@ -38,9 +38,9 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsLanguage('en').should.be.ok; - req.acceptsLanguage('es').should.be.ok; - req.acceptsLanguage('jp').should.be.ok; + req.acceptsLanguage('en').should.be.ok() + req.acceptsLanguage('es').should.be.ok() + req.acceptsLanguage('jp').should.be.ok() res.end(); }); diff --git a/test/req.acceptsLanguages.js b/test/req.acceptsLanguages.js index 6a9cb3366bc..1d92f44b2b3 100644 --- a/test/req.acceptsLanguages.js +++ b/test/req.acceptsLanguages.js @@ -8,8 +8,8 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsLanguages('en-us').should.be.ok; - req.acceptsLanguages('en').should.be.ok; + req.acceptsLanguages('en-us').should.be.ok() + req.acceptsLanguages('en').should.be.ok() res.end(); }); @@ -23,7 +23,7 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsLanguages('es').should.not.be.ok; + req.acceptsLanguages('es').should.not.be.ok() res.end(); }); @@ -38,9 +38,9 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.acceptsLanguages('en').should.be.ok; - req.acceptsLanguages('es').should.be.ok; - req.acceptsLanguages('jp').should.be.ok; + req.acceptsLanguages('en').should.be.ok() + req.acceptsLanguages('es').should.be.ok() + req.acceptsLanguages('jp').should.be.ok() res.end(); }); diff --git a/test/req.xhr.js b/test/req.xhr.js index cc8754ce4cf..1bbc247104d 100644 --- a/test/req.xhr.js +++ b/test/req.xhr.js @@ -8,7 +8,7 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.xhr.should.be.true; + req.xhr.should.be.true() res.end(); }); @@ -25,7 +25,7 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.xhr.should.be.true; + req.xhr.should.be.true() res.end(); }); @@ -42,7 +42,7 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.xhr.should.be.false; + req.xhr.should.be.false() res.end(); }); @@ -59,7 +59,7 @@ describe('req', function(){ var app = express(); app.use(function(req, res){ - req.xhr.should.be.false; + req.xhr.should.be.false() res.end(); }); diff --git a/test/res.sendFile.js b/test/res.sendFile.js index be3a23ebc2c..a3576d02196 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -108,7 +108,7 @@ describe('res', function(){ }); app.use(function (err, req, res, next) { - err.code.should.be.empty; + err.code.should.be.empty() cb(); }); @@ -224,7 +224,7 @@ describe('res', function(){ app.use(function (req, res) { setImmediate(function () { res.sendFile(path.resolve(fixtures, 'name.txt'), function (err) { - should(err).be.ok; + should(err).be.ok() err.code.should.equal('ECONNABORTED'); cb(); }); @@ -243,7 +243,7 @@ describe('res', function(){ app.use(function (req, res) { onFinished(res, function () { res.sendFile(path.resolve(fixtures, 'name.txt'), function (err) { - should(err).be.ok; + should(err).be.ok() err.code.should.equal('ECONNABORTED'); cb(); }); @@ -294,7 +294,7 @@ describe('res', function(){ app.use(function (req, res) { res.sendFile(path.resolve(fixtures, 'does-not-exist'), function (err) { - should(err).be.ok; + should(err).be.ok() err.status.should.equal(404); res.send('got it'); }); @@ -348,7 +348,7 @@ describe('res', function(){ app.use(function (req, res) { setImmediate(function () { res.sendfile('test/fixtures/name.txt', function (err) { - should(err).be.ok; + should(err).be.ok() err.code.should.equal('ECONNABORTED'); cb(); }); @@ -367,7 +367,7 @@ describe('res', function(){ app.use(function (req, res) { onFinished(res, function () { res.sendfile('test/fixtures/name.txt', function (err) { - should(err).be.ok; + should(err).be.ok() err.code.should.equal('ECONNABORTED'); cb(); }); @@ -600,7 +600,7 @@ describe('res', function(){ }); app.use(function (err, req, res, next) { - err.code.should.be.empty; + err.code.should.be.empty() cb(); }); From 56e90e3c7267782febe35754806ce3f63b527485 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 5 Aug 2017 23:37:39 -0400 Subject: [PATCH 261/889] lint: add eslint rules that cover editorconfig --- .eslintignore | 2 ++ .eslintrc | 7 +++++++ .travis.yml | 4 +++- appveyor.yml | 1 + examples/content-negotiation/db.js | 2 +- examples/mvc/controllers/main/index.js | 2 +- examples/mvc/db.js | 2 +- examples/resource/index.js | 2 +- examples/route-separation/site.js | 2 +- examples/search/public/client.js | 2 +- examples/static-files/public/js/app.js | 2 +- examples/web-service/index.js | 2 +- package.json | 2 ++ test/acceptance/error-pages.js | 2 +- test/acceptance/error.js | 2 +- test/acceptance/route-map.js | 2 +- test/app.engine.js | 4 ++-- test/config.js | 12 ++++++------ 18 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000000..62562b74a3b --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +coverage +node_modules diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000000..8f51db362e8 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,7 @@ +{ + "rules": { + "eol-last": "error", + "indent": ["error", 2, { "SwitchCase": 1 }], + "no-trailing-spaces": "error" + } +} diff --git a/.travis.yml b/.travis.yml index 3e899dd2351..5926ca5650a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,5 +27,7 @@ before_install: # Update Node.js modules - "test ! -d node_modules || npm prune" - "test ! -d node_modules || npm rebuild" -script: "npm run-script test-ci" +script: + - "npm run test-ci" + - "npm run lint" after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls" diff --git a/appveyor.yml b/appveyor.yml index ed8d4aa9f05..9863c08e272 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,4 +22,5 @@ test_script: - node --version - npm --version - npm run test-ci + - npm run lint version: "{build}" diff --git a/examples/content-negotiation/db.js b/examples/content-negotiation/db.js index 8def2f5ad21..43fb04baa18 100644 --- a/examples/content-negotiation/db.js +++ b/examples/content-negotiation/db.js @@ -4,4 +4,4 @@ users.push({ name: 'Tobi' }); users.push({ name: 'Loki' }); users.push({ name: 'Jane' }); -module.exports = users; \ No newline at end of file +module.exports = users; diff --git a/examples/mvc/controllers/main/index.js b/examples/mvc/controllers/main/index.js index 83db90f6f20..031862d345e 100644 --- a/examples/mvc/controllers/main/index.js +++ b/examples/mvc/controllers/main/index.js @@ -1,3 +1,3 @@ exports.index = function(req, res){ res.redirect('/users'); -}; \ No newline at end of file +}; diff --git a/examples/mvc/db.js b/examples/mvc/db.js index 565fdfaa507..c992afcfd74 100644 --- a/examples/mvc/db.js +++ b/examples/mvc/db.js @@ -11,4 +11,4 @@ var users = exports.users = []; users.push({ name: 'TJ', pets: [pets[0], pets[1], pets[2]], id: 0 }); users.push({ name: 'Guillermo', pets: [pets[3]], id: 1 }); -users.push({ name: 'Nathan', pets: [], id: 2 }); \ No newline at end of file +users.push({ name: 'Nathan', pets: [], id: 2 }); diff --git a/examples/resource/index.js b/examples/resource/index.js index 9137167cdf9..0c2a7a32079 100644 --- a/examples/resource/index.js +++ b/examples/resource/index.js @@ -75,7 +75,7 @@ app.resource('/users', User); app.get('/', function(req, res){ res.send([ - '

    Examples:

      ' + '

      Examples:

        ' , '
      • GET /users
      • ' , '
      • GET /users/1
      • ' , '
      • GET /users/3
      • ' diff --git a/examples/route-separation/site.js b/examples/route-separation/site.js index 698892cc89c..a3d20bc8a1f 100644 --- a/examples/route-separation/site.js +++ b/examples/route-separation/site.js @@ -1,3 +1,3 @@ exports.index = function(req, res){ res.render('index', { title: 'Route Separation Example' }); -}; \ No newline at end of file +}; diff --git a/examples/search/public/client.js b/examples/search/public/client.js index 0c198cc39fa..a7eeb6a75af 100644 --- a/examples/search/public/client.js +++ b/examples/search/public/client.js @@ -10,4 +10,4 @@ search.addEventListener('keyup', function(){ } }; xhr.send(); -}, false); \ No newline at end of file +}, false); diff --git a/examples/static-files/public/js/app.js b/examples/static-files/public/js/app.js index 19102815663..257cc5642cb 100644 --- a/examples/static-files/public/js/app.js +++ b/examples/static-files/public/js/app.js @@ -1 +1 @@ -foo \ No newline at end of file +foo diff --git a/examples/web-service/index.js b/examples/web-service/index.js index 694e121d91b..41747cfdc7f 100644 --- a/examples/web-service/index.js +++ b/examples/web-service/index.js @@ -61,7 +61,7 @@ var users = [ ]; var userRepos = { - tobi: [repos[0], repos[1]] + tobi: [repos[0], repos[1]] , loki: [repos[1]] , jane: [repos[2]] }; diff --git a/package.json b/package.json index 15e80f1934b..9f38f52bc1a 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "body-parser": "1.17.2", "cookie-parser": "~1.4.3", "ejs": "2.5.7", + "eslint": "2.13.1", "express-session": "1.15.3", "hbs": "4.0.1", "istanbul": "0.4.5", @@ -87,6 +88,7 @@ "lib/" ], "scripts": { + "lint": "eslint .", "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/", "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/", "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/", diff --git a/test/acceptance/error-pages.js b/test/acceptance/error-pages.js index 886cedcabe3..9af950178da 100644 --- a/test/acceptance/error-pages.js +++ b/test/acceptance/error-pages.js @@ -99,4 +99,4 @@ describe('error-pages', function(){ }) }) }) -}) \ No newline at end of file +}) diff --git a/test/acceptance/error.js b/test/acceptance/error.js index 6010f2e2ae4..6bdf099feed 100644 --- a/test/acceptance/error.js +++ b/test/acceptance/error.js @@ -26,4 +26,4 @@ describe('error', function(){ .expect(404,done) }) }) -}) \ No newline at end of file +}) diff --git a/test/acceptance/route-map.js b/test/acceptance/route-map.js index ae3eeea6507..0bd2a6d32e1 100644 --- a/test/acceptance/route-map.js +++ b/test/acceptance/route-map.js @@ -42,4 +42,4 @@ describe('route-map', function(){ .expect('delete 12\'s pet 2', done); }) }) -}) \ No newline at end of file +}) diff --git a/test/app.engine.js b/test/app.engine.js index 6d1ee1cacbf..b198292fa03 100644 --- a/test/app.engine.js +++ b/test/app.engine.js @@ -47,7 +47,7 @@ describe('app', function(){ done(); }) }) - + it('should work "view engine" setting', function(done){ var app = express(); @@ -62,7 +62,7 @@ describe('app', function(){ done(); }) }) - + it('should work "view engine" with leading "."', function(done){ var app = express(); diff --git a/test/config.js b/test/config.js index e298e76a5c5..17a02b7ebab 100644 --- a/test/config.js +++ b/test/config.js @@ -49,7 +49,7 @@ describe('config', function () { var app = express(); assert.strictEqual(app.get('foo'), undefined); }) - + it('should otherwise return the value', function(){ var app = express(); app.set('foo', 'bar'); @@ -125,7 +125,7 @@ describe('config', function () { assert.strictEqual(app.get('tobi'), true); }) }) - + describe('.disable()', function(){ it('should set the value to false', function(){ var app = express(); @@ -133,26 +133,26 @@ describe('config', function () { assert.strictEqual(app.get('tobi'), false); }) }) - + describe('.enabled()', function(){ it('should default to false', function(){ var app = express(); assert.strictEqual(app.enabled('foo'), false); }) - + it('should return true when set', function(){ var app = express(); app.set('foo', 'bar'); assert.strictEqual(app.enabled('foo'), true); }) }) - + describe('.disabled()', function(){ it('should default to true', function(){ var app = express(); assert.strictEqual(app.disabled('foo'), true); }) - + it('should return false when set', function(){ var app = express(); app.set('foo', 'bar'); From 1dbaae51ddb64c7397d19546bacb0792dbb7d59b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 5 Aug 2017 23:54:31 -0400 Subject: [PATCH 262/889] deps: update example dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9f38f52bc1a..ab6db290342 100644 --- a/package.json +++ b/package.json @@ -60,9 +60,10 @@ "after": "0.8.2", "body-parser": "1.17.2", "cookie-parser": "~1.4.3", + "cookie-session": "1.3.0", "ejs": "2.5.7", "eslint": "2.13.1", - "express-session": "1.15.3", + "express-session": "1.15.5", "hbs": "4.0.1", "istanbul": "0.4.5", "marked": "0.3.6", @@ -74,7 +75,6 @@ "should": "11.2.1", "supertest": "1.2.0", "connect-redis": "~2.4.1", - "cookie-session": "~1.2.0", "vhost": "~3.0.2" }, "engines": { From 44881fabe3680722368df75c66125fbd5f8ed569 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Aug 2017 00:18:57 -0400 Subject: [PATCH 263/889] docs: update collaborator guide for lint script --- Collaborator-Guide.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Collaborator-Guide.md b/Collaborator-Guide.md index 7c0d265dd0a..75d4e7c8f28 100644 --- a/Collaborator-Guide.md +++ b/Collaborator-Guide.md @@ -6,7 +6,7 @@ Open issues for the expressjs.com website in https://github.com/expressjs/expres ## PRs and Code contributions * Tests must pass. -* Follow the [JavaScript Standard Style](http://standardjs.com/). +* Follow the [JavaScript Standard Style](http://standardjs.com/) and `npm run lint`. * If you fix a bug, add a test. ## Branches @@ -27,7 +27,9 @@ a future release of Express. each new issue you work on, although not compulsory. 4. To run the test suite, first install the dependencies by running `npm install`, then run `npm test`. -5. If the tests pass, you can commit your changes to your fork and then create +5. Ensure your code is linted by running `npm run lint` -- fix any issue you + see listed. +6. If the tests pass, you can commit your changes to your fork and then create a pull request from there. Make sure to reference your issue from the pull request comments by including the issue number e.g. `#123`. From e0066227f787931bb0db09e76e007450d0f365b7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Aug 2017 00:19:32 -0400 Subject: [PATCH 264/889] lint: remove all unused varaibles --- .eslintrc | 3 ++- benchmarks/middleware.js | 1 - examples/view-constructor/index.js | 1 - lib/utils.js | 1 - lib/view.js | 1 - test/Route.js | 1 - test/app.listen.js | 1 - test/app.locals.js | 1 - test/app.router.js | 1 - test/req.host.js | 1 - test/req.hostname.js | 1 - test/req.range.js | 1 - test/res.download.js | 1 - test/res.format.js | 1 - test/res.send.js | 1 - test/res.sendFile.js | 4 ---- test/res.sendStatus.js | 1 - test/res.vary.js | 1 - 18 files changed, 2 insertions(+), 21 deletions(-) diff --git a/.eslintrc b/.eslintrc index 8f51db362e8..ad9c0ce9eb7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,6 +2,7 @@ "rules": { "eol-last": "error", "indent": ["error", 2, { "SwitchCase": 1 }], - "no-trailing-spaces": "error" + "no-trailing-spaces": "error", + "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }] } } diff --git a/benchmarks/middleware.js b/benchmarks/middleware.js index 3aa7a8b4ac7..efbac12983a 100644 --- a/benchmarks/middleware.js +++ b/benchmarks/middleware.js @@ -1,5 +1,4 @@ -var http = require('http'); var express = require('..'); var app = express(); diff --git a/examples/view-constructor/index.js b/examples/view-constructor/index.js index 195d32db0eb..175a254e4ee 100644 --- a/examples/view-constructor/index.js +++ b/examples/view-constructor/index.js @@ -3,7 +3,6 @@ */ var express = require('../../'); -var http = require('http'); var GithubView = require('./github-view'); var md = require('marked').parse; diff --git a/lib/utils.js b/lib/utils.js index f418c5807c7..ae2a7f862d2 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -17,7 +17,6 @@ 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'); var proxyaddr = require('proxy-addr'); var qs = require('qs'); diff --git a/lib/view.js b/lib/view.js index 1728725d291..99d5aed7a07 100644 --- a/lib/view.js +++ b/lib/view.js @@ -16,7 +16,6 @@ var debug = require('debug')('express:view'); var path = require('path'); var fs = require('fs'); -var utils = require('./utils'); /** * Module variables. diff --git a/test/Route.js b/test/Route.js index d7a80bdbc01..8f90152d8c8 100644 --- a/test/Route.js +++ b/test/Route.js @@ -4,7 +4,6 @@ var should = require('should'); var express = require('../') , Route = express.Route , methods = require('methods') - , assert = require('assert'); describe('Route', function(){ it('should work without handlers', function(done) { diff --git a/test/app.listen.js b/test/app.listen.js index b6f68578934..a78d16e4e1a 100644 --- a/test/app.listen.js +++ b/test/app.listen.js @@ -1,6 +1,5 @@ var express = require('../') - , request = require('supertest'); describe('app.listen()', function(){ it('should wrap with an HTTP server', function(done){ diff --git a/test/app.locals.js b/test/app.locals.js index a8b022957a2..d8bfb5a9874 100644 --- a/test/app.locals.js +++ b/test/app.locals.js @@ -1,6 +1,5 @@ var express = require('../') - , request = require('supertest'); describe('app', function(){ describe('.locals(obj)', function(){ diff --git a/test/app.router.js b/test/app.router.js index 95680f9139c..28561c2fbcd 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -39,7 +39,6 @@ describe('app.router', function(){ it('should include ' + method.toUpperCase(), function(done){ var app = express(); - var calls = []; app[method]('/foo', function(req, res){ if ('head' == method) { diff --git a/test/req.host.js b/test/req.host.js index 8fa3409054f..7bb0b27acf8 100644 --- a/test/req.host.js +++ b/test/req.host.js @@ -1,7 +1,6 @@ var express = require('../') , request = require('supertest') - , assert = require('assert'); describe('req', function(){ describe('.host', function(){ diff --git a/test/req.hostname.js b/test/req.hostname.js index 65c2be81a1f..816cd597990 100644 --- a/test/req.hostname.js +++ b/test/req.hostname.js @@ -1,7 +1,6 @@ var express = require('../') , request = require('supertest') - , assert = require('assert'); describe('req', function(){ describe('.hostname', function(){ diff --git a/test/req.range.js b/test/req.range.js index 09459d1e127..5443c0658d2 100644 --- a/test/req.range.js +++ b/test/req.range.js @@ -1,5 +1,4 @@ -var assert = require('assert'); var express = require('..'); var request = require('supertest') diff --git a/test/res.download.js b/test/res.download.js index 0671d8318c4..fad56ee256a 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -89,7 +89,6 @@ describe('res', function(){ it('should remove Content-Disposition', function(done){ var app = express() - , calls = 0; app.use(function (req, res, next) { res.download('test/fixtures/foobar.html', function(err){ diff --git a/test/res.format.js b/test/res.format.js index 2b0dfd517e7..3c1d095b426 100644 --- a/test/res.format.js +++ b/test/res.format.js @@ -1,7 +1,6 @@ var express = require('../') , request = require('supertest') - , utils = require('../lib/utils') , assert = require('assert'); var app1 = express(); diff --git a/test/res.send.js b/test/res.send.js index f2e7d759c15..88d231eab55 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -1,5 +1,4 @@ -var assert = require('assert'); var express = require('..'); var methods = require('methods'); var request = require('supertest'); diff --git a/test/res.sendFile.js b/test/res.sendFile.js index a3576d02196..ff4b1cb2dd1 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -446,12 +446,10 @@ describe('res', function(){ it('should invoke the callback on 403', function(done){ var app = express() - , calls = 0; app.use(function(req, res){ res.sendfile('test/fixtures/foo/../user.html', function(err){ assert(!res.headersSent); - ++calls; res.send(err.message); }); }); @@ -464,7 +462,6 @@ describe('res', function(){ it('should invoke the callback on socket error', function(done){ var app = express() - , calls = 0; app.use(function(req, res){ res.sendfile('test/fixtures/user.html', function(err){ @@ -715,7 +712,6 @@ describe('res', function(){ describe('with non-GET', function(){ it('should still serve', function(done){ var app = express() - , calls = 0; app.use(function(req, res){ res.sendfile(path.join(__dirname, '/fixtures/name.txt')) diff --git a/test/res.sendStatus.js b/test/res.sendStatus.js index a97e1bf8d81..c355bc408f3 100644 --- a/test/res.sendStatus.js +++ b/test/res.sendStatus.js @@ -1,5 +1,4 @@ -var assert = require('assert') var express = require('..') var request = require('supertest') diff --git a/test/res.vary.js b/test/res.vary.js index 9a2edd24c09..9d39a341c0b 100644 --- a/test/res.vary.js +++ b/test/res.vary.js @@ -1,5 +1,4 @@ -var assert = require('assert'); var express = require('..'); var request = require('supertest'); var utils = require('./support/utils'); From e2d725e01620fc3c8b3720e5521a124836e32cb2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Aug 2017 02:37:10 -0400 Subject: [PATCH 265/889] deps: send@0.15.4 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c67fd941745..422d52dede3 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,10 @@ unreleased - Fix array argument being altered - deps: ipaddr.js@1.4.0 * deps: qs@6.5.0 + * deps: send@0.15.4 + - deps: debug@2.6.8 + - deps: depd@~1.1.1 + - deps: http-errors@~1.6.2 4.15.3 / 2017-05-16 =================== diff --git a/package.json b/package.json index ab6db290342..5c9e94f4898 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "proxy-addr": "~1.1.5", "qs": "6.5.0", "range-parser": "~1.2.0", - "send": "0.15.3", + "send": "0.15.4", "serve-static": "1.12.3", "setprototypeof": "1.0.3", "statuses": "~1.3.1", From a50f1098d014e2393e2d5f4beae37a85830c203d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Aug 2017 02:38:02 -0400 Subject: [PATCH 266/889] deps: serve-static@1.12.4 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 422d52dede3..91707e6c03d 100644 --- a/History.md +++ b/History.md @@ -14,6 +14,8 @@ unreleased - deps: debug@2.6.8 - deps: depd@~1.1.1 - deps: http-errors@~1.6.2 + * deps: serve-static@1.12.4 + - deps: send@0.15.4 4.15.3 / 2017-05-16 =================== diff --git a/package.json b/package.json index 5c9e94f4898..d5b9ae405df 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "qs": "6.5.0", "range-parser": "~1.2.0", "send": "0.15.4", - "serve-static": "1.12.3", + "serve-static": "1.12.4", "setprototypeof": "1.0.3", "statuses": "~1.3.1", "type-is": "~1.6.15", From a4bd4373b2c3b2521ee4c499cb8e90e98f78bfa5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Aug 2017 22:03:53 -0400 Subject: [PATCH 267/889] 4.15.4 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 91707e6c03d..f297e3b075c 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.15.4 / 2017-08-06 +=================== * deps: debug@2.6.8 * deps: depd@~1.1.1 diff --git a/package.json b/package.json index d5b9ae405df..d8ec444d539 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.15.3", + "version": "4.15.4", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From e3bd14dcca6128afc8ba7f11a4f7e2b34923d66e Mon Sep 17 00:00:00 2001 From: Mike Tunnicliffe Date: Mon, 14 Mar 2016 12:32:35 +0000 Subject: [PATCH 268/889] Remove res.send(status, body) signature closes #2942 --- History.md | 2 ++ lib/response.js | 7 ------- test/res.format.js | 15 ++++++++++----- test/res.send.js | 30 ------------------------------ 4 files changed, 12 insertions(+), 42 deletions(-) diff --git a/History.md b/History.md index 2c0588a0a01..37d728ac055 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ This incorporates all changes after 4.15.2 up to 4.15.4. + * remove: + - `res.send(status, body)` signature - use `res.status(status).send(body)` * deps: router@~1.3.1 - deps: debug@2.6.8 diff --git a/lib/response.js b/lib/response.js index f3fa4d4af13..9b583a66ef6 100644 --- a/lib/response.js +++ b/lib/response.js @@ -113,13 +113,6 @@ res.send = function send(body) { // settings var app = this.app; - // support res.send(status, body) - if (arguments.length === 2) { - deprecate('res.send(status, body): Use res.status(status).send(body) instead'); - this.statusCode = arguments[0]; - chunk = arguments[1]; - } - switch (typeof chunk) { // string defaulting to html case 'string': diff --git a/test/res.format.js b/test/res.format.js index 3c1d095b426..2c470c658a4 100644 --- a/test/res.format.js +++ b/test/res.format.js @@ -26,7 +26,8 @@ app1.use(function(req, res, next){ app1.use(function(err, req, res, next){ if (!err.types) throw err; - res.send(err.status, 'Supports: ' + err.types.join(', ')); + res.status(err.status) + res.send('Supports: ' + err.types.join(', ')) }) var app2 = express(); @@ -40,7 +41,8 @@ app2.use(function(req, res, next){ }); app2.use(function(err, req, res, next){ - res.send(err.status, 'Supports: ' + err.types.join(', ')); + res.status(err.status) + res.send('Supports: ' + err.types.join(', ')) }) var app3 = express(); @@ -63,7 +65,8 @@ app4.get('/', function(req, res, next){ }); app4.use(function(err, req, res, next){ - res.send(err.status, 'Supports: ' + err.types.join(', ')); + res.status(err.status) + res.send('Supports: ' + err.types.join(', ')) }) var app5 = express(); @@ -96,7 +99,8 @@ describe('res', function(){ }); app.use(function(err, req, res, next){ - res.send(err.status, 'Supports: ' + err.types.join(', ')); + res.status(err.status) + res.send('Supports: ' + err.types.join(', ')) }); test(app); @@ -135,7 +139,8 @@ describe('res', function(){ }); router.use(function(err, req, res, next){ - res.send(err.status, 'Supports: ' + err.types.join(', ')); + res.status(err.status) + res.send('Supports: ' + err.types.join(', ')) }) app.use(router) diff --git a/test/res.send.js b/test/res.send.js index 13fd2442ce6..88ed35948ae 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -48,36 +48,6 @@ describe('res', function(){ }) }) - describe('.send(code, body)', function(){ - it('should set .statusCode and body', function(done){ - var app = express(); - - app.use(function(req, res){ - res.send(201, 'Created :)'); - }); - - request(app) - .get('/') - .expect('Created :)') - .expect(201, done); - }) - }) - - describe('.send(code, number)', function(){ - it('should send number as json', function(done){ - var app = express(); - - app.use(function(req, res){ - res.send(200, 0.123); - }); - - request(app) - .get('/') - .expect('Content-Type', 'application/json; charset=utf-8') - .expect(200, '0.123', done); - }) - }) - describe('.send(Number)', function(){ it('should send as application/json', function(done){ var app = express(); From 71395f59337e8d5b5b3d4c9652a9332a9432af26 Mon Sep 17 00:00:00 2001 From: Mike Tunnicliffe Date: Mon, 14 Mar 2016 12:10:13 +0000 Subject: [PATCH 269/889] Remove res.redirect(url, status) signature closes #2941 --- History.md | 1 + lib/response.js | 10 ++-------- test/res.redirect.js | 15 --------------- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/History.md b/History.md index 37d728ac055..7e4577ff36d 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ This incorporates all changes after 4.15.2 up to 4.15.4. * remove: + - `res.redirect(url, status)` signature - use `res.redirect(status, url)` - `res.send(status, body)` signature - use `res.status(status).send(body)` * deps: router@~1.3.1 - deps: debug@2.6.8 diff --git a/lib/response.js b/lib/response.js index 9b583a66ef6..61ab75d2473 100644 --- a/lib/response.js +++ b/lib/response.js @@ -13,7 +13,6 @@ */ var contentDisposition = require('content-disposition'); -var deprecate = require('depd')('express'); var encodeUrl = require('encodeurl'); var escapeHtml = require('escape-html'); var http = require('http'); @@ -745,13 +744,8 @@ res.redirect = function redirect(url) { // allow status / url if (arguments.length === 2) { - if (typeof arguments[0] === 'number') { - status = arguments[0]; - address = arguments[1]; - } else { - deprecate('res.redirect(url, status): Use res.redirect(status, url) instead'); - status = arguments[1]; - } + status = arguments[0] + address = arguments[1] } // Set location header diff --git a/test/res.redirect.js b/test/res.redirect.js index 755bb1c1c6c..d7a068af5b3 100644 --- a/test/res.redirect.js +++ b/test/res.redirect.js @@ -60,21 +60,6 @@ describe('res', function(){ }) }) - describe('.redirect(url, status)', function(){ - it('should set the response status', function(done){ - var app = express(); - - app.use(function(req, res){ - res.redirect('http://google.com/', 303); - }); - - request(app) - .get('/') - .expect('Location', 'http://google.com/') - .expect(303, done) - }) - }) - describe('when the request method is HEAD', function(){ it('should ignore the body', function(done){ var app = express(); From 48817a798f3820bbe252d30d33bd701779511dc5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 17 Aug 2017 22:03:40 -0400 Subject: [PATCH 270/889] build: remove minor pin for nightly --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5926ca5650a..3dbeb41fcda 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ node_js: - "7.10" matrix: include: - - node_js: "8.0" + - node_js: "8" env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly" allow_failures: # Allow the nightly installs to fail From 78e55108e40ce8ce751baa10324f48a6bb21b47e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 13 Sep 2017 20:03:42 -0400 Subject: [PATCH 271/889] build: mocha@3.5.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8ec444d539..2eec2887a7b 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "istanbul": "0.4.5", "marked": "0.3.6", "method-override": "2.3.9", - "mocha": "3.5.0", + "mocha": "3.5.3", "morgan": "1.8.2", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", From b208b24f8323930419d9b5bbe0f442b36852dc36 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 13 Sep 2017 20:09:33 -0400 Subject: [PATCH 272/889] build: should@13.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2eec2887a7b..5068a5d6144 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "morgan": "1.8.2", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", - "should": "11.2.1", + "should": "13.0.1", "supertest": "1.2.0", "connect-redis": "~2.4.1", "vhost": "~3.0.2" From de5fb62b1ac8d02efcb7931ef12936cb0a954307 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 17 Sep 2017 20:13:05 -0400 Subject: [PATCH 273/889] deps: update example dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5068a5d6144..a02a6943d37 100644 --- a/package.json +++ b/package.json @@ -58,9 +58,9 @@ }, "devDependencies": { "after": "0.8.2", - "body-parser": "1.17.2", + "body-parser": "1.18.1", "cookie-parser": "~1.4.3", - "cookie-session": "1.3.0", + "cookie-session": "1.3.1", "ejs": "2.5.7", "eslint": "2.13.1", "express-session": "1.15.5", From 9e067ad2cb96f23f7997758a7f5a3c69ada03c12 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Sep 2017 20:45:32 -0400 Subject: [PATCH 274/889] deps: fresh@0.5.2 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index f297e3b075c..e7e37e92e24 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +unreleased +========== + + * deps: fresh@0.5.2 + - Fix handling of modified headers with invalid dates + - perf: improve ETag match loop + - perf: improve `If-None-Match` token parsing + 4.15.4 / 2017-08-06 =================== diff --git a/package.json b/package.json index a02a6943d37..87e4ee8eae4 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "escape-html": "~1.0.3", "etag": "~1.8.0", "finalhandler": "~1.0.4", - "fresh": "0.5.0", + "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", From 9e0fa7f1ca2efe768e91ee84534f837d2cff243a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Sep 2017 20:46:42 -0400 Subject: [PATCH 275/889] deps: send@0.15.5 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e7e37e92e24..83cd43185e5 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,10 @@ unreleased - Fix handling of modified headers with invalid dates - perf: improve ETag match loop - perf: improve `If-None-Match` token parsing + * deps: send@0.15.5 + - Fix handling of modified headers with invalid dates + - deps: etag@~1.8.1 + - deps: fresh@0.5.2 4.15.4 / 2017-08-06 =================== diff --git a/package.json b/package.json index 87e4ee8eae4..2ad3c5e2a99 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "proxy-addr": "~1.1.5", "qs": "6.5.0", "range-parser": "~1.2.0", - "send": "0.15.4", + "send": "0.15.5", "serve-static": "1.12.4", "setprototypeof": "1.0.3", "statuses": "~1.3.1", From 961dbff904d3e6b1b10cfe6741506ae851d272ff Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Sep 2017 20:48:23 -0400 Subject: [PATCH 276/889] deps: serve-static@1.12.5 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 83cd43185e5..95fad3d3d97 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,9 @@ unreleased - Fix handling of modified headers with invalid dates - deps: etag@~1.8.1 - deps: fresh@0.5.2 + * deps: serve-static@1.12.5 + - deps: parseurl@~1.3.2 + - deps: send@0.15.5 4.15.4 / 2017-08-06 =================== diff --git a/package.json b/package.json index 2ad3c5e2a99..4bb68915b8e 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "qs": "6.5.0", "range-parser": "~1.2.0", "send": "0.15.5", - "serve-static": "1.12.4", + "serve-static": "1.12.5", "setprototypeof": "1.0.3", "statuses": "~1.3.1", "type-is": "~1.6.15", From d7da22550da484ddcdf77623272b64c36030b216 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Sep 2017 20:49:14 -0400 Subject: [PATCH 277/889] build: should@13.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4bb68915b8e..97f94459b83 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "morgan": "1.8.2", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", - "should": "13.0.1", + "should": "13.1.0", "supertest": "1.2.0", "connect-redis": "~2.4.1", "vhost": "~3.0.2" From 19a2eeb47697feecae5960a726fb5b7ae2c7644b Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Tue, 21 Mar 2017 14:53:42 -0700 Subject: [PATCH 278/889] tests: check render error without engine-specific message closes #3251 --- test/app.render.js | 10 ++++------ test/res.render.js | 10 ++++++---- test/support/tmpl.js | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/test/app.render.js b/test/app.render.js index 1485098f582..54f6c2ca82d 100644 --- a/test/app.render.js +++ b/test/app.render.js @@ -97,12 +97,10 @@ describe('app', function(){ app.set('views', path.join(__dirname, 'fixtures')) - app.render('user.tmpl', function (err, str) { - // nextTick to prevent cyclic - process.nextTick(function(){ - err.message.should.match(/Cannot read property '[^']+' of undefined/); - done(); - }); + app.render('user.tmpl', function (err) { + assert.ok(err) + assert.equal(err.name, 'RenderError') + done() }) }) }) diff --git a/test/res.render.js b/test/res.render.js index 2e3a16f1370..e19e8cc542b 100644 --- a/test/res.render.js +++ b/test/res.render.js @@ -105,12 +105,12 @@ describe('res', function(){ }); app.use(function(err, req, res, next){ - res.end(err.message); + res.status(500).send('got error: ' + err.name) }); request(app) .get('/') - .expect(/Cannot read property '[^']+' of undefined/, done); + .expect(500, 'got error: RenderError', done) }) }) @@ -329,13 +329,15 @@ describe('res', function(){ app.use(function(req, res){ res.render('user.tmpl', function (err) { - res.end(err.message); + if (err) { + res.status(500).send('got error: ' + err.name) + } }); }); request(app) .get('/') - .expect(/Cannot read property '[^']+' of undefined/, done); + .expect(500, 'got error: RenderError', done) }) }) }) diff --git a/test/support/tmpl.js b/test/support/tmpl.js index 2e8bec86388..bab65669d33 100644 --- a/test/support/tmpl.js +++ b/test/support/tmpl.js @@ -13,6 +13,7 @@ module.exports = function renderFile(fileName, options, callback) { str = str.replace(variableRegExp, generateVariableLookup(options)); } catch (e) { err = e; + err.name = 'RenderError' } callback(err, str); From 9395db4c22567d09f19ac7cd629e23908784ec6d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 22 Sep 2017 20:25:18 -0400 Subject: [PATCH 279/889] deps: debug@2.6.9 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 95fad3d3d97..5bf412451be 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * deps: debug@2.6.9 * deps: fresh@0.5.2 - Fix handling of modified headers with invalid dates - perf: improve ETag match loop diff --git a/package.json b/package.json index 97f94459b83..7f465d0e642 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "content-type": "~1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", - "debug": "2.6.8", + "debug": "2.6.9", "depd": "~1.1.1", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", From bd1672f0a45e2722126a05723aca68cbd65e3f74 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 22 Sep 2017 20:26:30 -0400 Subject: [PATCH 280/889] deps: finalhandler@~1.0.6 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5bf412451be..e4770be6885 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,9 @@ unreleased ========== * deps: debug@2.6.9 + * deps: finalhandler@~1.0.6 + - deps: debug@2.6.9 + - deps: parseurl@~1.3.2 * deps: fresh@0.5.2 - Fix handling of modified headers with invalid dates - perf: improve ETag match loop diff --git a/package.json b/package.json index 7f465d0e642..3afcec06718 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.8.0", - "finalhandler": "~1.0.4", + "finalhandler": "~1.0.6", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", From 7137bf567db674fa5a93b71fffda09e7ac4ec73c Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 22 Sep 2017 20:27:37 -0400 Subject: [PATCH 281/889] deps: send@0.15.6 --- History.md | 4 +++- package.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index e4770be6885..3d2bb66505c 100644 --- a/History.md +++ b/History.md @@ -9,10 +9,12 @@ unreleased - Fix handling of modified headers with invalid dates - perf: improve ETag match loop - perf: improve `If-None-Match` token parsing - * deps: send@0.15.5 + * deps: send@0.15.6 - Fix handling of modified headers with invalid dates + - deps: debug@2.6.9 - deps: etag@~1.8.1 - deps: fresh@0.5.2 + - perf: improve `If-Match` token parsing * deps: serve-static@1.12.5 - deps: parseurl@~1.3.2 - deps: send@0.15.5 diff --git a/package.json b/package.json index 3afcec06718..16b11d6fdb1 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "proxy-addr": "~1.1.5", "qs": "6.5.0", "range-parser": "~1.2.0", - "send": "0.15.5", + "send": "0.15.6", "serve-static": "1.12.5", "setprototypeof": "1.0.3", "statuses": "~1.3.1", From 40435ec99779b08202f9f139c9a0a7d64e941b40 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 22 Sep 2017 20:28:52 -0400 Subject: [PATCH 282/889] deps: serve-static@1.12.6 --- History.md | 5 +++-- package.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 3d2bb66505c..fa520920d7c 100644 --- a/History.md +++ b/History.md @@ -15,9 +15,10 @@ unreleased - deps: etag@~1.8.1 - deps: fresh@0.5.2 - perf: improve `If-Match` token parsing - * deps: serve-static@1.12.5 + * deps: serve-static@1.12.6 - deps: parseurl@~1.3.2 - - deps: send@0.15.5 + - deps: send@0.15.6 + - perf: improve slash collapsing 4.15.4 / 2017-08-06 =================== diff --git a/package.json b/package.json index 16b11d6fdb1..bf48b83c7cc 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "qs": "6.5.0", "range-parser": "~1.2.0", "send": "0.15.6", - "serve-static": "1.12.5", + "serve-static": "1.12.6", "setprototypeof": "1.0.3", "statuses": "~1.3.1", "type-is": "~1.6.15", From ea3d60565242c47be97088ead2708d7b88390858 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Sep 2017 01:04:38 -0400 Subject: [PATCH 283/889] 4.15.5 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index fa520920d7c..707677eb17a 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.15.5 / 2017-09-24 +=================== * deps: debug@2.6.9 * deps: finalhandler@~1.0.6 diff --git a/package.json b/package.json index bf48b83c7cc..954c20b3c30 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.15.4", + "version": "4.15.5", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From f4120a645301366891775d1f03925449239a2cb7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Sep 2017 01:28:00 -0400 Subject: [PATCH 284/889] 5.0.0-alpha.6 --- History.md | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 61cab4d7309..1bd1cb6c5be 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,8 @@ -5.x -=== +5.0.0-alpha.6 / 2017-09-24 +========================== -This incorporates all changes after 4.15.2 up to 4.15.5. +This is the sixth Express 5.0 alpha release, based off 4.15.5 and includes +changes from 5.0.0-alpha.5. * remove: - `res.redirect(url, status)` signature - use `res.redirect(status, url)` diff --git a/package.json b/package.json index fe756671f15..de1a1dbb002 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-alpha.5", + "version": "5.0.0-alpha.6", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 94fdb674b1df2e36d389fce51f5e07071f807adb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Sep 2017 20:57:54 -0400 Subject: [PATCH 285/889] build: support Node.js 8.x --- .gitignore | 1 + .travis.yml | 4 ++++ appveyor.yml | 2 ++ 3 files changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 9723e60591d..5fee6a2dc97 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ Desktop.ini # npm node_modules +package-lock.json *.log *.gz diff --git a/.travis.yml b/.travis.yml index 3dbeb41fcda..3e487a6f186 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ node_js: - "5.12" - "6.11" - "7.10" + - "8.4" matrix: include: - node_js: "8" @@ -21,6 +22,9 @@ cache: directories: - node_modules before_install: + # Skip updating shrinkwrap / lock + - "npm config set shrinkwrap false" + # Remove all non-test dependencies - "npm rm --save-dev connect-redis" diff --git a/appveyor.yml b/appveyor.yml index 9863c08e272..193660af715 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,10 +9,12 @@ environment: - nodejs_version: "5.12" - nodejs_version: "6.11" - nodejs_version: "7.10" + - nodejs_version: "8.4" cache: - node_modules install: - ps: Install-Product node $env:nodejs_version + - npm config set shrinkwrap false - npm rm --save-dev connect-redis - if exist node_modules npm prune - if exist node_modules npm rebuild From c3fb7e5adc1fd40e301ed1e25f0d5b5a393d0295 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Sep 2017 21:06:00 -0400 Subject: [PATCH 286/889] build: test against Node.js 9.x nightly --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3e487a6f186..855168ff540 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,8 @@ matrix: include: - node_js: "8" env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly" + - node_js: "9" + env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly" allow_failures: # Allow the nightly installs to fail - env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly" From 80f1ea9bec3c5aedb08a6917ecc24fb8d22b707d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Sep 2017 21:11:33 -0400 Subject: [PATCH 287/889] Improve error message when autoloading invalid view engine fixes #3403 --- History.md | 5 +++++ lib/view.js | 10 +++++++++- test/fixtures/broken.send | 0 test/res.render.js | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/broken.send diff --git a/History.md b/History.md index 707677eb17a..765f050318a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Improve error message when autoloading invalid view engine + 4.15.5 / 2017-09-24 =================== diff --git a/lib/view.js b/lib/view.js index 99d5aed7a07..cf101caeab9 100644 --- a/lib/view.js +++ b/lib/view.js @@ -76,7 +76,15 @@ function View(name, options) { // load engine var mod = this.ext.substr(1) debug('require "%s"', mod) - opts.engines[this.ext] = require(mod).__express + + // default engine export + var fn = require(mod).__express + + if (typeof fn !== 'function') { + throw new Error('Module "' + mod + '" does not provide a view engine.') + } + + opts.engines[this.ext] = fn } // store loaded engine diff --git a/test/fixtures/broken.send b/test/fixtures/broken.send new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/res.render.js b/test/res.render.js index e19e8cc542b..643a57002a0 100644 --- a/test/res.render.js +++ b/test/res.render.js @@ -35,6 +35,20 @@ describe('res', function(){ .expect('

        tobi

        ', done); }) + it('should error without "view engine" set and file extension to a non-engine module', function (done) { + var app = createApp() + + app.locals.user = { name: 'tobi' } + + app.use(function (req, res) { + res.render(path.join(__dirname, 'fixtures', 'broken.send')) + }) + + request(app) + .get('/') + .expect(500, /does not provide a view engine/, done) + }) + it('should error without "view engine" set and no file extension', function (done) { var app = createApp(); From 48940e61202be07677659b3b9d87c967fc4e8bdc Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Sep 2017 21:12:47 -0400 Subject: [PATCH 288/889] Skip Buffer encoding when not generating ETag for small response --- History.md | 1 + lib/response.js | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/History.md b/History.md index 765f050318a..83ba2cc5d76 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ unreleased ========== * Improve error message when autoloading invalid view engine + * Skip `Buffer` encoding when not generating ETag for small response 4.15.5 / 2017-09-24 =================== diff --git a/lib/response.js b/lib/response.js index b852a60e2f5..e34af49d693 100644 --- a/lib/response.js +++ b/lib/response.js @@ -106,7 +106,6 @@ res.links = function(links){ res.send = function send(body) { var chunk = body; var encoding; - var len; var req = this.req; var type; @@ -171,23 +170,33 @@ res.send = function send(body) { } } + // determine if ETag should be generated + var etagFn = app.get('etag fn') + var generateETag = !this.get('ETag') && typeof etagFn === 'function' + // populate Content-Length + var len if (chunk !== undefined) { - if (!Buffer.isBuffer(chunk)) { - // convert chunk to Buffer; saves later double conversions + if (!generateETag && chunk.length < 1000) { + // just calculate length when no ETag + small chunk + len = Buffer.byteLength(chunk, encoding) + } else if (!Buffer.isBuffer(chunk)) { + // convert chunk to Buffer and calculate chunk = new Buffer(chunk, encoding); encoding = undefined; + len = chunk.length + } else { + // get length of Buffer + len = chunk.length } - len = chunk.length; this.set('Content-Length', len); } // populate ETag var etag; - var generateETag = len !== undefined && app.get('etag fn'); - if (typeof generateETag === 'function' && !this.get('ETag')) { - if ((etag = generateETag(chunk, encoding))) { + if (generateETag && len !== undefined) { + if ((etag = etagFn(chunk, encoding))) { this.set('ETag', etag); } } From 550043c21727674a9d00c30504beb95cfbd7bbba Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Sep 2017 21:14:00 -0400 Subject: [PATCH 289/889] deps: setprototypeof@1.1.0 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 83ba2cc5d76..e8fcafa4149 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ unreleased * Improve error message when autoloading invalid view engine * Skip `Buffer` encoding when not generating ETag for small response + * deps: setprototypeof@1.1.0 4.15.5 / 2017-09-24 =================== diff --git a/package.json b/package.json index 954c20b3c30..cd94d1cf94a 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "range-parser": "~1.2.0", "send": "0.15.6", "serve-static": "1.12.6", - "setprototypeof": "1.0.3", + "setprototypeof": "1.1.0", "statuses": "~1.3.1", "type-is": "~1.6.15", "utils-merge": "1.0.0", From 9a99c152703048591c031bd10d2a2e3ca55ebcac Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 27 Sep 2017 21:28:25 -0400 Subject: [PATCH 290/889] deps: accepts@~1.3.4 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e8fcafa4149..0c206496496 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ unreleased * Improve error message when autoloading invalid view engine * Skip `Buffer` encoding when not generating ETag for small response + * deps: accepts@~1.3.4 + - deps: mime-types@~2.1.16 * deps: setprototypeof@1.1.0 4.15.5 / 2017-09-24 diff --git a/package.json b/package.json index cd94d1cf94a..9351cf2e05b 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "api" ], "dependencies": { - "accepts": "~1.3.3", + "accepts": "~1.3.4", "array-flatten": "1.1.1", "content-disposition": "0.5.2", "content-type": "~1.0.2", From 70589c3aef6fb64ce396848e78ca7ea0768d2d5d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 27 Sep 2017 21:30:08 -0400 Subject: [PATCH 291/889] deps: content-type@~1.0.4 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0c206496496..0f6f82bffef 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,9 @@ unreleased * Skip `Buffer` encoding when not generating ETag for small response * deps: accepts@~1.3.4 - deps: mime-types@~2.1.16 + * deps: content-type@~1.0.4 + - perf: remove argument reassignment + - perf: skip parameter parsing when no parameters * deps: setprototypeof@1.1.0 4.15.5 / 2017-09-24 diff --git a/package.json b/package.json index 9351cf2e05b..5febf1048e5 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "accepts": "~1.3.4", "array-flatten": "1.1.1", "content-disposition": "0.5.2", - "content-type": "~1.0.2", + "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", From e62bb8bf9f68382414cdd7997fe661de4647c987 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 27 Sep 2017 21:30:43 -0400 Subject: [PATCH 292/889] deps: etag@~1.8.1 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0f6f82bffef..077eec931b5 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,8 @@ unreleased * deps: content-type@~1.0.4 - perf: remove argument reassignment - perf: skip parameter parsing when no parameters + * deps: etag@~1.8.1 + - perf: replace regular expression with substring * deps: setprototypeof@1.1.0 4.15.5 / 2017-09-24 diff --git a/package.json b/package.json index 5febf1048e5..78834c50721 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "depd": "~1.1.1", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", - "etag": "~1.8.0", + "etag": "~1.8.1", "finalhandler": "~1.0.6", "fresh": "0.5.2", "merge-descriptors": "1.0.1", From ad7d96db479e6e9d93ab4848d5fe163905e123ed Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 27 Sep 2017 21:31:39 -0400 Subject: [PATCH 293/889] deps: qs@6.5.1 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 077eec931b5..012d8a2ffed 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,8 @@ unreleased - perf: skip parameter parsing when no parameters * deps: etag@~1.8.1 - perf: replace regular expression with substring + * deps: qs@6.5.1 + - Fix parsing & compacting very deep objects * deps: setprototypeof@1.1.0 4.15.5 / 2017-09-24 diff --git a/package.json b/package.json index 78834c50721..0bbfeb8e6ea 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "parseurl": "~1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.5", - "qs": "6.5.0", + "qs": "6.5.1", "range-parser": "~1.2.0", "send": "0.15.6", "serve-static": "1.12.6", From 5cc761c86593f2e87c7a9dac02135548096bb952 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Sep 2017 00:04:47 -0400 Subject: [PATCH 294/889] deps: parseurl@~1.3.2 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 012d8a2ffed..2c9866dbb5d 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,9 @@ unreleased - perf: skip parameter parsing when no parameters * deps: etag@~1.8.1 - perf: replace regular expression with substring + * deps: parseurl@~1.3.2 + - perf: reduce overhead for full URLs + - perf: unroll the "fast-path" `RegExp` * deps: qs@6.5.1 - Fix parsing & compacting very deep objects * deps: setprototypeof@1.1.0 diff --git a/package.json b/package.json index 0bbfeb8e6ea..4330b141f08 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", - "parseurl": "~1.3.1", + "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.5", "qs": "6.5.1", From 673d51f4f0fa83f6b663ed6f9f0426940d07664b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Sep 2017 00:19:30 -0400 Subject: [PATCH 295/889] deps: utils-merge@1.0.1 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2c9866dbb5d..eb01929864f 100644 --- a/History.md +++ b/History.md @@ -16,6 +16,7 @@ unreleased * deps: qs@6.5.1 - Fix parsing & compacting very deep objects * deps: setprototypeof@1.1.0 + * deps: utils-merge@1.0.1 4.15.5 / 2017-09-24 =================== diff --git a/package.json b/package.json index 4330b141f08..1298b943275 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "setprototypeof": "1.1.0", "statuses": "~1.3.1", "type-is": "~1.6.15", - "utils-merge": "1.0.0", + "utils-merge": "1.0.1", "vary": "~1.1.1" }, "devDependencies": { From c2f4fb535688eaec14c713190a4ab881e195a41a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Sep 2017 00:42:05 -0400 Subject: [PATCH 296/889] deps: finalhandler@1.1.0 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index eb01929864f..c4b34a76439 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,8 @@ unreleased - perf: skip parameter parsing when no parameters * deps: etag@~1.8.1 - perf: replace regular expression with substring + * deps: finalhandler@1.1.0 + - Use `res.headersSent` when available * deps: parseurl@~1.3.2 - perf: reduce overhead for full URLs - perf: unroll the "fast-path" `RegExp` diff --git a/package.json b/package.json index 1298b943275..ea49823cbbf 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.0.6", + "finalhandler": "1.1.0", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", From 02a9d5fb28e313fd94ee5ec24fe5da02fbc0d6eb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Sep 2017 01:18:04 -0400 Subject: [PATCH 297/889] deps: proxy-addr@~2.0.2 closes #3432 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c4b34a76439..4352f26acdf 100644 --- a/History.md +++ b/History.md @@ -15,6 +15,11 @@ unreleased * deps: parseurl@~1.3.2 - perf: reduce overhead for full URLs - perf: unroll the "fast-path" `RegExp` + * deps: proxy-addr@~2.0.2 + - Fix trimming leading / trailing OWS in `X-Forwarded-For` + - deps: forwarded@~0.1.2 + - deps: ipaddr.js@1.5.2 + - perf: reduce overhead when no `X-Forwarded-For` header * deps: qs@6.5.1 - Fix parsing & compacting very deep objects * deps: setprototypeof@1.1.0 diff --git a/package.json b/package.json index ea49823cbbf..219e21fe23b 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "~1.1.5", + "proxy-addr": "~2.0.2", "qs": "6.5.1", "range-parser": "~1.2.0", "send": "0.15.6", From d9d09b8b9041504b645f3173ca70ef173c7e1563 Mon Sep 17 00:00:00 2001 From: Lawrence Page Date: Thu, 18 May 2017 11:04:27 -0700 Subject: [PATCH 298/889] perf: re-use options object when generating ETags closes #3313 closes #3314 --- History.md | 1 + lib/utils.js | 35 +++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/History.md b/History.md index 4352f26acdf..4b4f0dd5cbf 100644 --- a/History.md +++ b/History.md @@ -24,6 +24,7 @@ unreleased - Fix parsing & compacting very deep objects * deps: setprototypeof@1.1.0 * deps: utils-merge@1.0.1 + * perf: re-use options object when generating ETags 4.15.5 / 2017-09-24 =================== diff --git a/lib/utils.js b/lib/utils.js index ae2a7f862d2..80f4edae3a3 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -31,13 +31,7 @@ var querystring = require('querystring'); * @api private */ -exports.etag = function (body, encoding) { - var buf = !Buffer.isBuffer(body) - ? new Buffer(body, encoding) - : body; - - return etag(buf, {weak: false}); -}; +exports.etag = createETagGenerator({ weak: false }) /** * Return weak ETag for `body`. @@ -48,13 +42,7 @@ exports.etag = function (body, encoding) { * @api private */ -exports.wetag = function wetag(body, encoding){ - var buf = !Buffer.isBuffer(body) - ? new Buffer(body, encoding) - : body; - - return etag(buf, {weak: true}); -}; +exports.wetag = createETagGenerator({ weak: true }) /** * Check if `path` looks absolute. @@ -273,6 +261,25 @@ exports.setCharset = function setCharset(type, charset) { return contentType.format(parsed); }; +/** + * Create an ETag generator function, generating ETags with + * the given options. + * + * @param {object} options + * @return {function} + * @private + */ + +function createETagGenerator (options) { + return function generateETag (body, encoding) { + var buf = !Buffer.isBuffer(body) + ? new Buffer(body, encoding) + : body + + return etag(buf, options) + } +} + /** * Parse an extended query string with qs. * From fa272edf843a31aa242390d46935437451707d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hrvoje=20=C5=A0imi=C4=87?= Date: Wed, 27 Sep 2017 15:17:03 +0200 Subject: [PATCH 299/889] docs: fix typo in jsdoc comment closes #3430 --- lib/application.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/application.js b/lib/application.js index 1abe8d08f58..8097d81a3b9 100644 --- a/lib/application.js +++ b/lib/application.js @@ -338,7 +338,7 @@ app.param = function param(name, fn) { * Assign `setting` to `val`, or return `setting`'s value. * * app.set('foo', 'bar'); - * app.get('foo'); + * app.set('foo'); * // => "bar" * * Mounted servers inherit their parent server's settings. From 12c37124689380837b24a7ed962432596237b440 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Sep 2017 08:26:39 -0400 Subject: [PATCH 300/889] Use safe-buffer for improved Buffer API --- History.md | 1 + benchmarks/middleware.js | 4 +--- lib/response.js | 5 +++-- lib/utils.js | 3 ++- package.json | 1 + test/res.attachment.js | 3 ++- test/res.send.js | 12 ++++++------ test/utils.js | 7 +++---- 8 files changed, 19 insertions(+), 17 deletions(-) diff --git a/History.md b/History.md index 4b4f0dd5cbf..18f5e5da371 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ unreleased * Improve error message when autoloading invalid view engine * Skip `Buffer` encoding when not generating ETag for small response + * Use `safe-buffer` for improved Buffer API * deps: accepts@~1.3.4 - deps: mime-types@~2.1.16 * deps: content-type@~1.0.4 diff --git a/benchmarks/middleware.js b/benchmarks/middleware.js index efbac12983a..df4df2c5ac5 100644 --- a/benchmarks/middleware.js +++ b/benchmarks/middleware.js @@ -13,10 +13,8 @@ while (n--) { }); } -var body = new Buffer('Hello World'); - app.use(function(req, res, next){ - res.send(body); + res.send('Hello World') }); app.listen(3333); diff --git a/lib/response.js b/lib/response.js index e34af49d693..285daf4fb4b 100644 --- a/lib/response.js +++ b/lib/response.js @@ -12,6 +12,7 @@ * @private */ +var Buffer = require('safe-buffer').Buffer var contentDisposition = require('content-disposition'); var deprecate = require('depd')('express'); var encodeUrl = require('encodeurl'); @@ -95,7 +96,7 @@ res.links = function(links){ * * Examples: * - * res.send(new Buffer('wahoo')); + * res.send(Buffer.from('wahoo')); * res.send({ some: 'json' }); * res.send('

        some html

        '); * @@ -182,7 +183,7 @@ res.send = function send(body) { len = Buffer.byteLength(chunk, encoding) } else if (!Buffer.isBuffer(chunk)) { // convert chunk to Buffer and calculate - chunk = new Buffer(chunk, encoding); + chunk = Buffer.from(chunk, encoding) encoding = undefined; len = chunk.length } else { diff --git a/lib/utils.js b/lib/utils.js index 80f4edae3a3..bd81ac7f6d9 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -12,6 +12,7 @@ * @api private */ +var Buffer = require('safe-buffer').Buffer var contentDisposition = require('content-disposition'); var contentType = require('content-type'); var deprecate = require('depd')('express'); @@ -273,7 +274,7 @@ exports.setCharset = function setCharset(type, charset) { function createETagGenerator (options) { return function generateETag (body, encoding) { var buf = !Buffer.isBuffer(body) - ? new Buffer(body, encoding) + ? Buffer.from(body, encoding) : body return etag(buf, options) diff --git a/package.json b/package.json index 219e21fe23b..dbbd7810042 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "proxy-addr": "~2.0.2", "qs": "6.5.1", "range-parser": "~1.2.0", + "safe-buffer": "5.1.1", "send": "0.15.6", "serve-static": "1.12.6", "setprototypeof": "1.1.0", diff --git a/test/res.attachment.js b/test/res.attachment.js index 662b1dd4e01..4c3d4aa2f1b 100644 --- a/test/res.attachment.js +++ b/test/res.attachment.js @@ -1,4 +1,5 @@ +var Buffer = require('safe-buffer').Buffer var express = require('../') , request = require('supertest'); @@ -36,7 +37,7 @@ describe('res', function(){ app.use(function(req, res){ res.attachment('/path/to/image.png'); - res.send(new Buffer(4)); + res.send(Buffer.alloc(4, '.')) }); request(app) diff --git a/test/res.send.js b/test/res.send.js index 88d231eab55..7aa8d7d90e2 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -1,4 +1,5 @@ +var Buffer = require('safe-buffer').Buffer var express = require('..'); var methods = require('methods'); var request = require('supertest'); @@ -166,7 +167,7 @@ describe('res', function(){ var app = express(); app.use(function(req, res){ - res.set('Content-Type', 'text/plain; charset=iso-8859-1').send(new Buffer('hi')); + res.set('Content-Type', 'text/plain; charset=iso-8859-1').send(Buffer.from('hi')) }); request(app) @@ -181,7 +182,7 @@ describe('res', function(){ var app = express(); app.use(function(req, res){ - res.send(new Buffer('hello')); + res.send(Buffer.from('hello')) }); request(app) @@ -194,8 +195,7 @@ describe('res', function(){ var app = express(); app.use(function (req, res) { - var str = Array(1000).join('-'); - res.send(new Buffer(str)); + res.send(Buffer.alloc(999, '-')) }); request(app) @@ -208,7 +208,7 @@ describe('res', function(){ var app = express(); app.use(function(req, res){ - res.set('Content-Type', 'text/plain').send(new Buffer('hey')); + res.set('Content-Type', 'text/plain').send(Buffer.from('hey')) }); request(app) @@ -512,7 +512,7 @@ describe('res', function(){ app.set('etag', function (body, encoding) { var chunk = !Buffer.isBuffer(body) - ? new Buffer(body, encoding) + ? Buffer.from(body, encoding) : body; chunk.toString().should.equal('hello, world!'); return '"custom"'; diff --git a/test/utils.js b/test/utils.js index c49019fe126..b51d223af97 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,5 +1,6 @@ var assert = require('assert'); +var Buffer = require('safe-buffer').Buffer var utils = require('../lib/utils'); describe('utils.etag(body, encoding)', function(){ @@ -14,8 +15,7 @@ describe('utils.etag(body, encoding)', function(){ }) it('should support buffer', function(){ - var buf = new Buffer('express!') - utils.etag(buf) + utils.etag(Buffer.from('express!')) .should.eql('"8-O2uVAFaQ1rZvlKLT14RnuvjPIdg"') }) @@ -59,8 +59,7 @@ describe('utils.wetag(body, encoding)', function(){ }) it('should support buffer', function(){ - var buf = new Buffer('express!') - utils.wetag(buf) + utils.wetag(Buffer.from('express!')) .should.eql('W/"8-O2uVAFaQ1rZvlKLT14RnuvjPIdg"') }) From 2df1ad26a58bf51228d7600df0d62ed17a90ff71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hrvoje=20=C5=A0imi=C4=87?= Date: Tue, 26 Sep 2017 16:00:53 +0200 Subject: [PATCH 301/889] Improve error messages when non-function provided as middleware closes #3426 --- History.md | 1 + lib/application.js | 2 +- lib/router/index.js | 4 ++-- lib/router/route.js | 4 ++-- test/Router.js | 30 +++++++++++++++++++++--------- test/app.use.js | 31 ++++++++++++++++++++++--------- 6 files changed, 49 insertions(+), 23 deletions(-) diff --git a/History.md b/History.md index 18f5e5da371..63a1bdf60b7 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ unreleased ========== * Improve error message when autoloading invalid view engine + * Improve error messages when non-function provided as middleware * Skip `Buffer` encoding when not generating ETag for small response * Use `safe-buffer` for improved Buffer API * deps: accepts@~1.3.4 diff --git a/lib/application.js b/lib/application.js index 8097d81a3b9..91f77d241e4 100644 --- a/lib/application.js +++ b/lib/application.js @@ -207,7 +207,7 @@ app.use = function use(fn) { var fns = flatten(slice.call(arguments, offset)); if (fns.length === 0) { - throw new TypeError('app.use() requires middleware functions'); + throw new TypeError('app.use() requires a middleware function') } // setup router diff --git a/lib/router/index.js b/lib/router/index.js index 51db4c28ff9..60727ed6d64 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -448,14 +448,14 @@ proto.use = function use(fn) { var callbacks = flatten(slice.call(arguments, offset)); if (callbacks.length === 0) { - throw new TypeError('Router.use() requires middleware functions'); + throw new TypeError('Router.use() requires a middleware function') } 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)); + throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn)) } // add the middleware diff --git a/lib/router/route.js b/lib/router/route.js index ea82ed29df5..178df0d5160 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -175,7 +175,7 @@ Route.prototype.all = function all() { if (typeof handle !== 'function') { var type = toString.call(handle); - var msg = 'Route.all() requires callback functions but got a ' + type; + var msg = 'Route.all() requires a callback function but got a ' + type throw new TypeError(msg); } @@ -198,7 +198,7 @@ methods.forEach(function(method){ if (typeof handle !== 'function') { var type = toString.call(handle); - var msg = 'Route.' + method + '() requires callback functions but got a ' + type; + var msg = 'Route.' + method + '() requires a callback function but got a ' + type throw new Error(msg); } diff --git a/test/Router.js b/test/Router.js index 18153d29267..057ce443df4 100644 --- a/test/Router.js +++ b/test/Router.js @@ -368,17 +368,29 @@ describe('Router', function(){ }) describe('.use', function() { - it('should require arguments', function(){ - var router = new Router(); - router.use.bind(router).should.throw(/requires middleware function/) + it('should require middleware', function () { + var router = new Router() + assert.throws(function () { router.use('/') }, /requires a middleware function/) }) - it('should not accept non-functions', function(){ - var router = new Router(); - router.use.bind(router, '/', 'hello').should.throw(/requires middleware function.*string/) - router.use.bind(router, '/', 5).should.throw(/requires middleware function.*number/) - router.use.bind(router, '/', null).should.throw(/requires middleware function.*Null/) - router.use.bind(router, '/', new Date()).should.throw(/requires middleware function.*Date/) + it('should reject string as middleware', function () { + var router = new Router() + assert.throws(function () { router.use('/', 'foo') }, /requires a middleware function but got a string/) + }) + + it('should reject number as middleware', function () { + var router = new Router() + assert.throws(function () { router.use('/', 42) }, /requires a middleware function but got a number/) + }) + + it('should reject null as middleware', function () { + var router = new Router() + assert.throws(function () { router.use('/', null) }, /requires a middleware function but got a Null/) + }) + + it('should reject Date as middleware', function () { + var router = new Router() + assert.throws(function () { router.use('/', new Date()) }, /requires a middleware function but got a Date/) }) it('should be called for any URL', function (done) { diff --git a/test/app.use.js b/test/app.use.js index b2031e4c56c..347937fbb3b 100644 --- a/test/app.use.js +++ b/test/app.use.js @@ -1,5 +1,6 @@ var after = require('after'); +var assert = require('assert') var express = require('..'); var request = require('supertest'); @@ -253,17 +254,29 @@ describe('app', function(){ }) describe('.use(path, middleware)', function(){ - it('should reject missing functions', function () { - var app = express(); - app.use.bind(app, '/').should.throw(/requires middleware function/); + it('should require middleware', function () { + var app = express() + assert.throws(function () { app.use('/') }, /requires a middleware function/) }) - it('should reject non-functions as middleware', function () { - var app = express(); - app.use.bind(app, '/', 'hi').should.throw(/requires middleware function.*string/); - app.use.bind(app, '/', 5).should.throw(/requires middleware function.*number/); - app.use.bind(app, '/', null).should.throw(/requires middleware function.*Null/); - app.use.bind(app, '/', new Date()).should.throw(/requires middleware function.*Date/); + it('should reject string as middleware', function () { + var app = express() + assert.throws(function () { app.use('/', 'foo') }, /requires a middleware function but got a string/) + }) + + it('should reject number as middleware', function () { + var app = express() + assert.throws(function () { app.use('/', 42) }, /requires a middleware function but got a number/) + }) + + it('should reject null as middleware', function () { + var app = express() + assert.throws(function () { app.use('/', null) }, /requires a middleware function but got a Null/) + }) + + it('should reject Date as middleware', function () { + var app = express() + assert.throws(function () { app.use('/', new Date()) }, /requires a middleware function but got a Date/) }) it('should strip path from req.url', function (done) { From 44591fee234dd83e05894c5b055703db1f68184c Mon Sep 17 00:00:00 2001 From: chainhelen Date: Thu, 28 Sep 2017 12:25:27 +0800 Subject: [PATCH 302/889] deps: vary@~1.1.2 closes #3434 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 63a1bdf60b7..04b68978330 100644 --- a/History.md +++ b/History.md @@ -26,6 +26,8 @@ unreleased - Fix parsing & compacting very deep objects * deps: setprototypeof@1.1.0 * deps: utils-merge@1.0.1 + * deps: vary@~1.1.2 + - perf: improve header token parsing speed * perf: re-use options object when generating ETags 4.15.5 / 2017-09-24 diff --git a/package.json b/package.json index dbbd7810042..0a476d67d90 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "statuses": "~1.3.1", "type-is": "~1.6.15", "utils-merge": "1.0.1", - "vary": "~1.1.1" + "vary": "~1.1.2" }, "devDependencies": { "after": "0.8.2", From 95fb5cc26848d4c2c57b0a7a74f088538d47d312 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Sep 2017 10:30:10 -0400 Subject: [PATCH 303/889] perf: remove dead .charset set in res.jsonp --- History.md | 1 + lib/response.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 04b68978330..c2d2595731a 100644 --- a/History.md +++ b/History.md @@ -29,6 +29,7 @@ unreleased * deps: vary@~1.1.2 - perf: improve header token parsing speed * perf: re-use options object when generating ETags + * perf: remove dead `.charset` set in `res.jsonp` 4.15.5 / 2017-09-24 =================== diff --git a/lib/response.js b/lib/response.js index 285daf4fb4b..9f61648c17b 100644 --- a/lib/response.js +++ b/lib/response.js @@ -314,7 +314,6 @@ res.jsonp = function jsonp(obj) { // jsonp if (typeof callback === 'string' && callback.length !== 0) { - this.charset = 'utf-8'; this.set('X-Content-Type-Options', 'nosniff'); this.set('Content-Type', 'text/javascript'); From a24fd0ca6cfd29329444fddf678bcdd1c08e56ae Mon Sep 17 00:00:00 2001 From: Aaron Clover Date: Thu, 20 Jul 2017 21:24:04 +1000 Subject: [PATCH 304/889] Add options to res.download closes #3327 closes #3370 --- lib/response.js | 34 ++++++++++++++++--- test/res.download.js | 80 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/lib/response.js b/lib/response.js index 9f61648c17b..ae028ae81b6 100644 --- a/lib/response.js +++ b/lib/response.js @@ -515,19 +515,29 @@ res.sendfile = deprecate.function(res.sendfile, * 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()`. + * Optionally providing an `options` object to use with `res.sendFile()`. + * This function will set the `Content-Disposition` header, overriding + * any `Content-Disposition` header passed as header options in order + * to set the attachment and filename. + * + * This method uses `res.sendFile()`. * * @public */ -res.download = function download(path, filename, callback) { +res.download = function download (path, filename, options, callback) { var done = callback; var name = filename; + var opts = options || null - // support function as second arg + // support function as second or third arg if (typeof filename === 'function') { done = filename; name = null; + opts = null + } else if (typeof options === 'function') { + done = options + opts = null } // set Content-Disposition when file is sent @@ -535,10 +545,26 @@ res.download = function download(path, filename, callback) { 'Content-Disposition': contentDisposition(name || path) }; + // merge user-provided headers + if (opts && opts.headers) { + var keys = Object.keys(opts.headers) + for (var i = 0; i < keys.length; i++) { + var key = keys[i] + if (key.toLowerCase() !== 'content-disposition') { + headers[key] = opts.headers[key] + } + } + } + + // merge user-provided options + opts = Object.create(opts) + opts.headers = headers + // Resolve the full path for sendFile var fullPath = resolve(path); - return this.sendFile(fullPath, { headers: headers }, done); + // send file + return this.sendFile(fullPath, opts, done) }; /** diff --git a/test/res.download.js b/test/res.download.js index fad56ee256a..30215bf6764 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -71,6 +71,86 @@ describe('res', function(){ }) }) + describe('.download(path, filename, options, fn)', function () { + it('should invoke the callback', function (done) { + var app = express() + var cb = after(2, done) + var options = {} + + app.use(function (req, res) { + res.download('test/fixtures/user.html', 'document', options, done) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Type', 'text/html; charset=UTF-8') + .expect('Content-Disposition', 'attachment; filename="document"') + .end(cb) + }) + + it('should allow options to res.sendFile()', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/.name', 'document', { + dotfiles: 'allow', + maxAge: '4h' + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Disposition', 'attachment; filename="document"') + .expect('Cache-Control', 'public, max-age=14400') + .expect('tobi') + .end(done) + }) + + describe('when options.headers contains Content-Disposition', function () { + it('should should be ignored', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/user.html', 'document', { + headers: { + 'Content-Type': 'text/x-custom', + 'Content-Disposition': 'inline' + } + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Type', 'text/x-custom') + .expect('Content-Disposition', 'attachment; filename="document"') + .end(done) + }) + + it('should should be ignored case-insensitively', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/user.html', 'document', { + headers: { + 'content-type': 'text/x-custom', + 'content-disposition': 'inline' + } + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Type', 'text/x-custom') + .expect('Content-Disposition', 'attachment; filename="document"') + .end(done) + }) + }) + }) + describe('on failure', function(){ it('should invoke the callback', function(done){ var app = express(); From 628438d8d890f3707b8eecf57aeff7d0da348e8e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Sep 2017 11:36:20 -0400 Subject: [PATCH 305/889] deps: update example dependencies --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0a476d67d90..addbdcb7f30 100644 --- a/package.json +++ b/package.json @@ -59,18 +59,18 @@ }, "devDependencies": { "after": "0.8.2", - "body-parser": "1.18.1", + "body-parser": "1.18.2", "cookie-parser": "~1.4.3", - "cookie-session": "1.3.1", + "cookie-session": "1.3.2", "ejs": "2.5.7", "eslint": "2.13.1", - "express-session": "1.15.5", + "express-session": "1.15.6", "hbs": "4.0.1", "istanbul": "0.4.5", "marked": "0.3.6", - "method-override": "2.3.9", + "method-override": "2.3.10", "mocha": "3.5.3", - "morgan": "1.8.2", + "morgan": "1.9.0", "multiparty": "4.1.3", "pbkdf2-password": "1.2.1", "should": "13.1.0", From 715401478516c39ea9b2f855d4109d7d6e1131e0 Mon Sep 17 00:00:00 2001 From: Greg Guthe Date: Wed, 5 Apr 2017 17:42:09 -0400 Subject: [PATCH 306/889] Add "escape json" setting for res.json and res.jsonp closes #3268 closes #3269 --- History.md | 1 + lib/response.js | 36 +++++++++++++++++++++++++++++++----- test/res.json.js | 22 ++++++++++++++++++++++ test/res.jsonp.js | 22 ++++++++++++++++++++++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index c2d2595731a..248b1c7a678 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Add `"json escape"` setting for `res.json` and `res.jsonp` * Improve error message when autoloading invalid view engine * Improve error messages when non-function provided as middleware * Skip `Buffer` encoding when not generating ETag for small response diff --git a/lib/response.js b/lib/response.js index ae028ae81b6..832044be9ae 100644 --- a/lib/response.js +++ b/lib/response.js @@ -254,9 +254,10 @@ res.json = function json(obj) { // settings var app = this.app; + var escape = app.get('json escape') var replacer = app.get('json replacer'); var spaces = app.get('json spaces'); - var body = stringify(val, replacer, spaces); + var body = stringify(val, replacer, spaces, escape) // content-type if (!this.get('Content-Type')) { @@ -296,9 +297,10 @@ res.jsonp = function jsonp(obj) { // settings var app = this.app; + var escape = app.get('json escape') var replacer = app.get('json replacer'); var spaces = app.get('json spaces'); - var body = stringify(val, replacer, spaces); + var body = stringify(val, replacer, spaces, escape) var callback = this.req.query[app.get('jsonp callback name')]; // content-type @@ -1098,14 +1100,38 @@ function sendfile(res, file, options, callback) { } /** - * Stringify JSON, like JSON.stringify, but v8 optimized. + * Stringify JSON, like JSON.stringify, but v8 optimized, with the + * ability to escape characters that can trigger HTML sniffing. + * + * @param {*} value + * @param {function} replaces + * @param {number} spaces + * @param {boolean} escape + * @returns {string} * @private */ -function stringify(value, replacer, spaces) { +function stringify (value, replacer, spaces, escape) { // v8 checks arguments.length for optimizing simple call // https://bugs.chromium.org/p/v8/issues/detail?id=4730 - return replacer || spaces + var json = replacer || spaces ? JSON.stringify(value, replacer, spaces) : JSON.stringify(value); + + if (escape) { + json = json.replace(/[<>&]/g, function (c) { + switch (c.charCodeAt(0)) { + case 0x3c: + return '\\u003c' + case 0x3e: + return '\\u003e' + case 0x26: + return '\\u0026' + default: + return c + } + }) + } + + return json } diff --git a/test/res.json.js b/test/res.json.js index 69f6723af54..1041376235c 100644 --- a/test/res.json.js +++ b/test/res.json.js @@ -102,6 +102,28 @@ describe('res', function(){ }) }) + describe('"json escape" setting', function () { + it('should be undefined by default', function () { + var app = express() + assert.strictEqual(app.get('json escape'), undefined) + }) + + it('should unicode escape HTML-sniffing characters', function (done) { + var app = express() + + app.enable('json escape') + + app.use(function (req, res) { + res.json({ '&': ' From bf4c3ee00f3b95a329fc1dd4dd0cd17c74178121 Mon Sep 17 00:00:00 2001 From: Hashen <37979557+Hashen110@users.noreply.github.com> Date: Sun, 20 Mar 2022 20:13:23 +0530 Subject: [PATCH 577/889] docs: fix incomplete JSDoc comment closes #4867 --- lib/utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utils.js b/lib/utils.js index 7797b068530..799a6a2b4ee 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -120,6 +120,7 @@ exports.contentDisposition = deprecate.function(contentDisposition, * also includes `.originalIndex` for stable sorting * * @param {String} str + * @param {Number} index * @return {Object} * @api private */ From 947b6b7d57939d1a3b33ce008765f9aba3eb6f70 Mon Sep 17 00:00:00 2001 From: Hashen <37979557+Hashen110@users.noreply.github.com> Date: Sun, 20 Mar 2022 21:08:08 +0530 Subject: [PATCH 578/889] lint: remove unnecessary continue statement in loop closes #4868 --- lib/router/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/router/index.js b/lib/router/index.js index 467d30458c2..791a600f86a 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -251,7 +251,6 @@ proto.handle = function handle(req, res, out) { // don't even bother matching route if (!has_method && method !== 'HEAD') { match = false; - continue; } } From eb4c930d5fb79e55c53b25d6e8a8a5cd15fc5554 Mon Sep 17 00:00:00 2001 From: Kris Kalavantavanich Date: Sun, 5 Dec 2021 15:14:40 +0700 Subject: [PATCH 579/889] build: support Node.js 15.x --- .github/workflows/ci.yml | 4 ++++ appveyor.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6e1b168ec1..8e60f419c62 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,7 @@ jobs: - Node.js 12.x - Node.js 13.x - Node.js 14.x + - Node.js 15.x include: - name: Node.js 0.10 @@ -90,6 +91,9 @@ jobs: - name: Node.js 14.x node-version: "14.19" + - name: Node.js 15.x + node-version: "15.14" + steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index db54a3fdb04..fc867adee7a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,6 +16,7 @@ environment: - nodejs_version: "12.22" - nodejs_version: "13.14" - nodejs_version: "14.19" + - nodejs_version: "15.14" cache: - node_modules install: From 8bf072039100cd264be920f06635fe77f083c751 Mon Sep 17 00:00:00 2001 From: Kris Kalavantavanich Date: Sun, 5 Dec 2021 15:15:26 +0700 Subject: [PATCH 580/889] build: support Node.js 16.x --- .github/workflows/ci.yml | 4 ++++ appveyor.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e60f419c62..7b153d1b436 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,7 @@ jobs: - Node.js 13.x - Node.js 14.x - Node.js 15.x + - Node.js 16.x include: - name: Node.js 0.10 @@ -94,6 +95,9 @@ jobs: - name: Node.js 15.x node-version: "15.14" + - name: Node.js 16.x + node-version: "16.14" + steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index fc867adee7a..2a2507b411b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,6 +17,7 @@ environment: - nodejs_version: "13.14" - nodejs_version: "14.19" - nodejs_version: "15.14" + - nodejs_version: "16.14" cache: - node_modules install: From 87279c08aa46d178fe6f2e235d2345f17d6b5a37 Mon Sep 17 00:00:00 2001 From: "Tito D. Kesumo Siregar" Date: Thu, 20 May 2021 11:23:33 +0700 Subject: [PATCH 581/889] Support proper 205 responses using res.send closes #4592 closes #4596 --- History.md | 5 +++++ lib/response.js | 7 +++++++ test/res.send.js | 16 ++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/History.md b/History.md index 9f3f876512d..fbe01269074 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Support proper 205 responses using `res.send` + 4.17.3 / 2022-02-16 =================== diff --git a/lib/response.js b/lib/response.js index ccf8d91b2c3..9cf3d52be52 100644 --- a/lib/response.js +++ b/lib/response.js @@ -213,6 +213,13 @@ res.send = function send(body) { chunk = ''; } + // alter headers for 205 + if (this.statusCode === 205) { + this.set('Content-Length', '0') + this.removeHeader('Transfer-Encoding') + chunk = '' + } + if (req.method === 'HEAD') { // skip body for HEAD this.end(); diff --git a/test/res.send.js b/test/res.send.js index 6ba55422882..c92568db6ad 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -283,6 +283,22 @@ describe('res', function(){ }) }) + describe('when .statusCode is 205', function () { + it('should strip Transfer-Encoding field and body, set Content-Length', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(205).set('Transfer-Encoding', 'chunked').send('foo') + }) + + request(app) + .get('/') + .expect(utils.shouldNotHaveHeader('Transfer-Encoding')) + .expect('Content-Length', '0') + .expect(205, '', done) + }) + }) + describe('when .statusCode is 304', function(){ it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){ var app = express(); From c17fe058613dc7dfb7779fbe68a9738a108fe408 Mon Sep 17 00:00:00 2001 From: Evan Hahn Date: Wed, 2 Feb 2022 19:13:54 -0600 Subject: [PATCH 582/889] Ignore Object.prototype values in settings through app.set/app.get closes #4802 closes #4803 --- History.md | 1 + lib/application.js | 19 ++++++++++++++++++- test/config.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index fbe01269074..97345bb411a 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Support proper 205 responses using `res.send` 4.17.3 / 2022-02-16 diff --git a/lib/application.js b/lib/application.js index e65ba588959..ebb30b51b3d 100644 --- a/lib/application.js +++ b/lib/application.js @@ -29,6 +29,13 @@ var flatten = require('array-flatten'); var merge = require('utils-merge'); var resolve = require('path').resolve; var setPrototypeOf = require('setprototypeof') + +/** + * Module variables. + * @private + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty var slice = Array.prototype.slice; /** @@ -352,7 +359,17 @@ app.param = function param(name, fn) { app.set = function set(setting, val) { if (arguments.length === 1) { // app.get(setting) - return this.settings[setting]; + var settings = this.settings + + while (settings && settings !== Object.prototype) { + if (hasOwnProperty.call(settings, setting)) { + return settings[setting] + } + + settings = Object.getPrototypeOf(settings) + } + + return undefined } debug('set "%s" to %o', setting, val); diff --git a/test/config.js b/test/config.js index 8386a4471c3..b04367fdbf8 100644 --- a/test/config.js +++ b/test/config.js @@ -11,6 +11,12 @@ describe('config', function () { assert.equal(app.get('foo'), 'bar'); }) + it('should set prototype values', function () { + var app = express() + app.set('hasOwnProperty', 42) + assert.strictEqual(app.get('hasOwnProperty'), 42) + }) + it('should return the app', function () { var app = express(); assert.equal(app.set('foo', 'bar'), app); @@ -21,6 +27,17 @@ describe('config', function () { assert.equal(app.set('foo', undefined), app); }) + it('should return set value', function () { + var app = express() + app.set('foo', 'bar') + assert.strictEqual(app.set('foo'), 'bar') + }) + + it('should return undefined for prototype values', function () { + var app = express() + assert.strictEqual(app.set('hasOwnProperty'), undefined) + }) + describe('"etag"', function(){ it('should throw on bad value', function(){ var app = express(); @@ -51,6 +68,11 @@ describe('config', function () { assert.strictEqual(app.get('foo'), undefined); }) + it('should return undefined for prototype values', function () { + var app = express() + assert.strictEqual(app.get('hasOwnProperty'), undefined) + }) + it('should otherwise return the value', function(){ var app = express(); app.set('foo', 'bar'); @@ -125,6 +147,12 @@ describe('config', function () { assert.equal(app.enable('tobi'), app); assert.strictEqual(app.get('tobi'), true); }) + + it('should set prototype values', function () { + var app = express() + app.enable('hasOwnProperty') + assert.strictEqual(app.get('hasOwnProperty'), true) + }) }) describe('.disable()', function(){ @@ -133,6 +161,12 @@ describe('config', function () { assert.equal(app.disable('tobi'), app); assert.strictEqual(app.get('tobi'), false); }) + + it('should set prototype values', function () { + var app = express() + app.disable('hasOwnProperty') + assert.strictEqual(app.get('hasOwnProperty'), false) + }) }) describe('.enabled()', function(){ @@ -146,6 +180,11 @@ describe('config', function () { app.set('foo', 'bar'); assert.strictEqual(app.enabled('foo'), true); }) + + it('should default to false for prototype values', function () { + var app = express() + assert.strictEqual(app.enabled('hasOwnProperty'), false) + }) }) describe('.disabled()', function(){ @@ -159,5 +198,10 @@ describe('config', function () { app.set('foo', 'bar'); assert.strictEqual(app.disabled('foo'), false); }) + + it('should default to true for prototype values', function () { + var app = express() + assert.strictEqual(app.disabled('hasOwnProperty'), true) + }) }) }) From 4847d0efa123fae8f12a2c1b88f7e1a87a5f145a Mon Sep 17 00:00:00 2001 From: Jon Church Date: Sat, 21 Mar 2020 05:04:16 -0400 Subject: [PATCH 583/889] Deprecate string and non-integer arguments to res.status closes #4223 --- History.md | 1 + lib/response.js | 3 + test/res.status.js | 205 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 197 insertions(+), 12 deletions(-) diff --git a/History.md b/History.md index 97345bb411a..2e549136a54 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Deprecate string and non-integer arguments to `res.status` * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Support proper 205 responses using `res.send` diff --git a/lib/response.js b/lib/response.js index 9cf3d52be52..7a9564d2625 100644 --- a/lib/response.js +++ b/lib/response.js @@ -64,6 +64,9 @@ var charsetRegExp = /;\s*charset\s*=/; */ res.status = function status(code) { + if ((typeof code === 'string' || Math.floor(code) !== code) && code > 99 && code < 1000) { + deprecate('res.status(' + JSON.stringify(code) + '): use res.status(' + Math.floor(code) + ') instead') + } this.statusCode = code; return this; }; diff --git a/test/res.status.js b/test/res.status.js index e0abc73c4c0..1fe08344eaa 100644 --- a/test/res.status.js +++ b/test/res.status.js @@ -1,21 +1,202 @@ 'use strict' var express = require('../') - , request = require('supertest'); +var request = require('supertest') -describe('res', function(){ - describe('.status(code)', function(){ - it('should set the response .statusCode', function(done){ - var app = express(); +var isIoJs = process.release + ? process.release.name === 'io.js' + : ['v1.', 'v2.', 'v3.'].indexOf(process.version.slice(0, 3)) !== -1 - app.use(function(req, res){ - res.status(201).end('Created'); - }); +describe('res', function () { + describe('.status(code)', function () { + describe('when "code" is undefined', function () { + it('should raise error for invalid status code', function (done) { + var app = express() - request(app) - .get('/') - .expect('Created') - .expect(201, done); + app.use(function (req, res) { + res.status(undefined).end() + }) + + request(app) + .get('/') + .expect(500, /Invalid status code/, function (err) { + if (isIoJs) { + done(err ? null : new Error('expected error')) + } else { + done(err) + } + }) + }) + }) + + describe('when "code" is null', function () { + it('should raise error for invalid status code', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(null).end() + }) + + request(app) + .get('/') + .expect(500, /Invalid status code/, function (err) { + if (isIoJs) { + done(err ? null : new Error('expected error')) + } else { + done(err) + } + }) + }) + }) + + describe('when "code" is 201', function () { + it('should set the response status code to 201', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(201).end() + }) + + request(app) + .get('/') + .expect(201, done) + }) + }) + + describe('when "code" is 302', function () { + it('should set the response status code to 302', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(302).end() + }) + + request(app) + .get('/') + .expect(302, done) + }) + }) + + describe('when "code" is 403', function () { + it('should set the response status code to 403', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(403).end() + }) + + request(app) + .get('/') + .expect(403, done) + }) + }) + + describe('when "code" is 501', function () { + it('should set the response status code to 501', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(501).end() + }) + + request(app) + .get('/') + .expect(501, done) + }) + }) + + describe('when "code" is "410"', function () { + it('should set the response status code to 410', function (done) { + var app = express() + + app.use(function (req, res) { + res.status('410').end() + }) + + request(app) + .get('/') + .expect(410, done) + }) + }) + + describe('when "code" is 410.1', function () { + it('should set the response status code to 410', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(410.1).end() + }) + + request(app) + .get('/') + .expect(410, function (err) { + if (isIoJs) { + done(err ? null : new Error('expected error')) + } else { + done(err) + } + }) + }) + }) + + describe('when "code" is 1000', function () { + it('should raise error for invalid status code', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(1000).end() + }) + + request(app) + .get('/') + .expect(500, /Invalid status code/, function (err) { + if (isIoJs) { + done(err ? null : new Error('expected error')) + } else { + done(err) + } + }) + }) + }) + + describe('when "code" is 99', function () { + it('should raise error for invalid status code', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(99).end() + }) + + request(app) + .get('/') + .expect(500, /Invalid status code/, function (err) { + if (isIoJs) { + done(err ? null : new Error('expected error')) + } else { + done(err) + } + }) + }) + }) + + describe('when "code" is -401', function () { + it('should raise error for invalid status code', function (done) { + var app = express() + + app.use(function (req, res) { + res.status(-401).end() + }) + + request(app) + .get('/') + .expect(500, /Invalid status code/, function (err) { + if (isIoJs) { + done(err ? null : new Error('expected error')) + } else { + done(err) + } + }) + }) }) }) }) From 0def9bb659557df1bd659411a1a6f2c5b8b9d893 Mon Sep 17 00:00:00 2001 From: Tommaso Tofacchi Date: Fri, 11 Mar 2022 10:02:43 +0100 Subject: [PATCH 584/889] Add "root" option to res.download fixes #4834 closes #4855 --- History.md | 1 + lib/response.js | 4 ++- test/res.download.js | 74 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2e549136a54..d7a2e43c350 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Add "root" option to `res.download` * Deprecate string and non-integer arguments to `res.status` * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Support proper 205 responses using `res.send` diff --git a/lib/response.js b/lib/response.js index 7a9564d2625..101311e0ebf 100644 --- a/lib/response.js +++ b/lib/response.js @@ -582,7 +582,9 @@ res.download = function download (path, filename, options, callback) { opts.headers = headers // Resolve the full path for sendFile - var fullPath = resolve(path); + var fullPath = !opts.root + ? resolve(path) + : path // send file return this.sendFile(fullPath, opts, done) diff --git a/test/res.download.js b/test/res.download.js index 1322b0a31f9..51380d4ba16 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -3,9 +3,12 @@ var after = require('after'); var Buffer = require('safe-buffer').Buffer var express = require('..'); +var path = require('path') var request = require('supertest'); var utils = require('./support/utils') +var FIXTURES_PATH = path.join(__dirname, 'fixtures') + describe('res', function(){ describe('.download(path)', function(){ it('should transfer as an attachment', function(done){ @@ -178,6 +181,77 @@ describe('res', function(){ .end(done) }) }) + + describe('with "root" option', function () { + it('should allow relative path', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('name.txt', 'document', { + root: FIXTURES_PATH + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Disposition', 'attachment; filename="document"') + .expect(utils.shouldHaveBody(Buffer.from('tobi'))) + .end(done) + }) + + it('should allow up within root', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('fake/../name.txt', 'document', { + root: FIXTURES_PATH + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Disposition', 'attachment; filename="document"') + .expect(utils.shouldHaveBody(Buffer.from('tobi'))) + .end(done) + }) + + it('should reject up outside root', function (done) { + var app = express() + + app.use(function (req, res) { + var p = '..' + path.sep + + path.relative(path.dirname(FIXTURES_PATH), path.join(FIXTURES_PATH, 'name.txt')) + + res.download(p, 'document', { + root: FIXTURES_PATH + }) + }) + + request(app) + .get('/') + .expect(403) + .expect(utils.shouldNotHaveHeader('Content-Disposition')) + .end(done) + }) + + it('should reject reading outside root', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('../name.txt', 'document', { + root: FIXTURES_PATH + }) + }) + + request(app) + .get('/') + .expect(403) + .expect(utils.shouldNotHaveHeader('Content-Disposition')) + .end(done) + }) + }) }) describe('on failure', function(){ From dd69eedd189eb55658ec435b821df13062cc5a8e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 25 Mar 2022 01:43:45 -0400 Subject: [PATCH 585/889] deps: send@0.18.0 --- History.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index d7a2e43c350..c5242a99a47 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,14 @@ unreleased * Deprecate string and non-integer arguments to `res.status` * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Support proper 205 responses using `res.send` + * deps: send@0.18.0 + - Fix emitted 416 error missing headers property + - Limit the headers removed for 304 response + - deps: depd@2.0.0 + - deps: destroy@1.2.0 + - deps: http-errors@2.0.0 + - deps: on-finished@2.4.1 + - deps: statuses@2.0.1 4.17.3 / 2022-02-16 =================== diff --git a/package.json b/package.json index 79921666294..14000074355 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "qs": "6.9.7", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.17.2", + "send": "0.18.0", "serve-static": "1.14.2", "setprototypeof": "1.2.0", "statuses": "~1.5.0", From c92420648e18f78d22db24e0ffec99155ec54a49 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 25 Mar 2022 01:44:51 -0400 Subject: [PATCH 586/889] deps: serve-static@1.15.0 --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c5242a99a47..9e4f0d3a8e9 100644 --- a/History.md +++ b/History.md @@ -13,6 +13,8 @@ unreleased - deps: http-errors@2.0.0 - deps: on-finished@2.4.1 - deps: statuses@2.0.1 + * deps: serve-static@1.15.0 + - deps: send@0.18.0 4.17.3 / 2022-02-16 =================== diff --git a/package.json b/package.json index 14000074355..c733bb2e507 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", - "serve-static": "1.14.2", + "serve-static": "1.15.0", "setprototypeof": "1.2.0", "statuses": "~1.5.0", "type-is": "~1.6.18", From f739b162d9cc9fcfc1f514c2441c69f9fcb4364d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 25 Mar 2022 01:46:32 -0400 Subject: [PATCH 587/889] deps: finalhandler@1.2.0 --- History.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 9e4f0d3a8e9..03b7ba9c7d9 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,10 @@ unreleased * Deprecate string and non-integer arguments to `res.status` * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Support proper 205 responses using `res.send` + * deps: finalhandler@1.2.0 + - Remove set content headers that break response + - deps: on-finished@2.4.1 + - deps: statuses@2.0.1 * deps: send@0.18.0 - Fix emitted 416 error missing headers property - Limit the headers removed for 304 response diff --git a/package.json b/package.json index c733bb2e507..6de4bfff428 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", From 03dc3671874b214f67dacaca90f39a1c389f822e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 25 Mar 2022 18:13:42 -0400 Subject: [PATCH 588/889] Allow options without filename in res.download --- History.md | 1 + lib/response.js | 7 ++ test/res.download.js | 260 ++++++++++++++++++++++++++++++++----------- 3 files changed, 206 insertions(+), 62 deletions(-) diff --git a/History.md b/History.md index 03b7ba9c7d9..9b4bf4bce55 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ unreleased ========== * Add "root" option to `res.download` + * Allow `options` without `filename` in `res.download` * Deprecate string and non-integer arguments to `res.status` * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Support proper 205 responses using `res.send` diff --git a/lib/response.js b/lib/response.js index 101311e0ebf..3713e6f9a97 100644 --- a/lib/response.js +++ b/lib/response.js @@ -561,6 +561,13 @@ res.download = function download (path, filename, options, callback) { opts = null } + // support optional filename, where options may be in it's place + if (typeof filename === 'object' && + (typeof options === 'function' || options === undefined)) { + name = null + opts = filename + } + // set Content-Disposition when file is sent var headers = { 'Content-Disposition': contentDisposition(name || path) diff --git a/test/res.download.js b/test/res.download.js index 51380d4ba16..91b074e8bf6 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -86,46 +86,12 @@ describe('res', function(){ }) }) - describe('.download(path, filename, fn)', function(){ - it('should invoke the callback', function(done){ - var app = express(); - var cb = after(2, done); - - app.use(function(req, res){ - res.download('test/fixtures/user.html', 'document', cb) - }); - - request(app) - .get('/') - .expect('Content-Type', 'text/html; charset=UTF-8') - .expect('Content-Disposition', 'attachment; filename="document"') - .expect(200, cb); - }) - }) - - describe('.download(path, filename, options, fn)', function () { - it('should invoke the callback', function (done) { - var app = express() - var cb = after(2, done) - var options = {} - - app.use(function (req, res) { - res.download('test/fixtures/user.html', 'document', options, cb) - }) - - request(app) - .get('/') - .expect(200) - .expect('Content-Type', 'text/html; charset=UTF-8') - .expect('Content-Disposition', 'attachment; filename="document"') - .end(cb) - }) - + describe('.download(path, options)', function () { it('should allow options to res.sendFile()', function (done) { var app = express() app.use(function (req, res) { - res.download('test/fixtures/.name', 'document', { + res.download('test/fixtures/.name', { dotfiles: 'allow', maxAge: '4h' }) @@ -134,51 +100,124 @@ describe('res', function(){ request(app) .get('/') .expect(200) - .expect('Content-Disposition', 'attachment; filename="document"') + .expect('Content-Disposition', 'attachment; filename=".name"') .expect('Cache-Control', 'public, max-age=14400') .expect(utils.shouldHaveBody(Buffer.from('tobi'))) .end(done) }) - describe('when options.headers contains Content-Disposition', function () { - it('should be ignored', function (done) { + describe('with "headers" option', function () { + it('should set headers on response', function (done) { var app = express() app.use(function (req, res) { - res.download('test/fixtures/user.html', 'document', { + res.download('test/fixtures/user.html', { headers: { - 'Content-Type': 'text/x-custom', - 'Content-Disposition': 'inline' + 'X-Foo': 'Bar', + 'X-Bar': 'Foo' } }) }) request(app) - .get('/') - .expect(200) - .expect('Content-Type', 'text/x-custom') - .expect('Content-Disposition', 'attachment; filename="document"') - .end(done) + .get('/') + .expect(200) + .expect('X-Foo', 'Bar') + .expect('X-Bar', 'Foo') + .end(done) }) - it('should be ignored case-insensitively', function (done) { + it('should use last header when duplicated', function (done) { var app = express() app.use(function (req, res) { - res.download('test/fixtures/user.html', 'document', { + res.download('test/fixtures/user.html', { headers: { - 'content-type': 'text/x-custom', - 'content-disposition': 'inline' + 'X-Foo': 'Bar', + 'x-foo': 'bar' } }) }) request(app) - .get('/') - .expect(200) - .expect('Content-Type', 'text/x-custom') - .expect('Content-Disposition', 'attachment; filename="document"') - .end(done) + .get('/') + .expect(200) + .expect('X-Foo', 'bar') + .end(done) + }) + + it('should override Content-Type', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/user.html', { + headers: { + 'Content-Type': 'text/x-custom' + } + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Type', 'text/x-custom') + .end(done) + }) + + it('should not set headers on 404', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/does-not-exist', { + headers: { + 'X-Foo': 'Bar' + } + }) + }) + + request(app) + .get('/') + .expect(404) + .expect(utils.shouldNotHaveHeader('X-Foo')) + .end(done) + }) + + describe('when headers contains Content-Disposition', function () { + it('should be ignored', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/user.html', { + headers: { + 'Content-Disposition': 'inline' + } + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Disposition', 'attachment; filename="user.html"') + .end(done) + }) + + it('should be ignored case-insensitively', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/user.html', { + headers: { + 'content-disposition': 'inline' + } + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Disposition', 'attachment; filename="user.html"') + .end(done) + }) }) }) @@ -187,7 +226,7 @@ describe('res', function(){ var app = express() app.use(function (req, res) { - res.download('name.txt', 'document', { + res.download('name.txt', { root: FIXTURES_PATH }) }) @@ -195,7 +234,7 @@ describe('res', function(){ request(app) .get('/') .expect(200) - .expect('Content-Disposition', 'attachment; filename="document"') + .expect('Content-Disposition', 'attachment; filename="name.txt"') .expect(utils.shouldHaveBody(Buffer.from('tobi'))) .end(done) }) @@ -204,7 +243,7 @@ describe('res', function(){ var app = express() app.use(function (req, res) { - res.download('fake/../name.txt', 'document', { + res.download('fake/../name.txt', { root: FIXTURES_PATH }) }) @@ -212,7 +251,7 @@ describe('res', function(){ request(app) .get('/') .expect(200) - .expect('Content-Disposition', 'attachment; filename="document"') + .expect('Content-Disposition', 'attachment; filename="name.txt"') .expect(utils.shouldHaveBody(Buffer.from('tobi'))) .end(done) }) @@ -224,7 +263,7 @@ describe('res', function(){ var p = '..' + path.sep + path.relative(path.dirname(FIXTURES_PATH), path.join(FIXTURES_PATH, 'name.txt')) - res.download(p, 'document', { + res.download(p, { root: FIXTURES_PATH }) }) @@ -240,7 +279,7 @@ describe('res', function(){ var app = express() app.use(function (req, res) { - res.download('../name.txt', 'document', { + res.download('../name.txt', { root: FIXTURES_PATH }) }) @@ -254,6 +293,103 @@ describe('res', function(){ }) }) + describe('.download(path, filename, fn)', function(){ + it('should invoke the callback', function(done){ + var app = express(); + var cb = after(2, done); + + app.use(function(req, res){ + res.download('test/fixtures/user.html', 'document', cb) + }); + + request(app) + .get('/') + .expect('Content-Type', 'text/html; charset=UTF-8') + .expect('Content-Disposition', 'attachment; filename="document"') + .expect(200, cb); + }) + }) + + describe('.download(path, filename, options, fn)', function () { + it('should invoke the callback', function (done) { + var app = express() + var cb = after(2, done) + var options = {} + + app.use(function (req, res) { + res.download('test/fixtures/user.html', 'document', options, cb) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Type', 'text/html; charset=UTF-8') + .expect('Content-Disposition', 'attachment; filename="document"') + .end(cb) + }) + + it('should allow options to res.sendFile()', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/.name', 'document', { + dotfiles: 'allow', + maxAge: '4h' + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Disposition', 'attachment; filename="document"') + .expect('Cache-Control', 'public, max-age=14400') + .expect(utils.shouldHaveBody(Buffer.from('tobi'))) + .end(done) + }) + + describe('when options.headers contains Content-Disposition', function () { + it('should be ignored', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/user.html', 'document', { + headers: { + 'Content-Type': 'text/x-custom', + 'Content-Disposition': 'inline' + } + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Type', 'text/x-custom') + .expect('Content-Disposition', 'attachment; filename="document"') + .end(done) + }) + + it('should be ignored case-insensitively', function (done) { + var app = express() + + app.use(function (req, res) { + res.download('test/fixtures/user.html', 'document', { + headers: { + 'content-type': 'text/x-custom', + 'content-disposition': 'inline' + } + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('Content-Type', 'text/x-custom') + .expect('Content-Disposition', 'attachment; filename="document"') + .end(done) + }) + }) + }) + describe('on failure', function(){ it('should invoke the callback', function(done){ var app = express(); From 10b9b507b7d113d04965cccd8d170ee524e3d555 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 25 Mar 2022 18:14:27 -0400 Subject: [PATCH 589/889] examples: use updated res.download in example --- examples/downloads/index.js | 5 +---- package.json | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/downloads/index.js b/examples/downloads/index.js index 62e7fa6e3eb..6b67e0c8862 100644 --- a/examples/downloads/index.js +++ b/examples/downloads/index.js @@ -6,7 +6,6 @@ var express = require('../../'); var path = require('path'); -var resolvePath = require('resolve-path') var app = module.exports = express(); @@ -25,9 +24,7 @@ app.get('/', function(req, res){ // /files/* is accessed via req.params[0] // but here we name it :file app.get('/files/:file(*)', function(req, res, next){ - var filePath = resolvePath(FILES_DIR, req.params.file) - - res.download(filePath, function (err) { + res.download(req.params.file, { root: FILES_DIR }, function (err) { if (!err) return; // file sent if (err.status !== 404) return next(err); // non-404 error // file for download not found diff --git a/package.json b/package.json index 6de4bfff428..8f8959a4c33 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,6 @@ "multiparty": "4.2.3", "nyc": "15.1.0", "pbkdf2-password": "1.2.1", - "resolve-path": "1.4.0", "supertest": "6.2.2", "vhost": "~3.0.2" }, From 9482b82d0b9c498140561087d68f0409078a86ea Mon Sep 17 00:00:00 2001 From: Nadav Ivgi Date: Tue, 13 Mar 2018 08:14:06 +0200 Subject: [PATCH 590/889] Invoke default with same arguments as types in res.format closes #3587 --- History.md | 1 + lib/response.js | 9 ++++----- test/res.format.js | 29 ++++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index 9b4bf4bce55..d1aa9b3b88d 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ unreleased * Allow `options` without `filename` in `res.download` * Deprecate string and non-integer arguments to `res.status` * Ignore `Object.prototype` values in settings through `app.set`/`app.get` + * Invoke `default` with same arguments as types in `res.format` * Support proper 205 responses using `res.send` * deps: finalhandler@1.2.0 - Remove set content headers that break response diff --git a/lib/response.js b/lib/response.js index 3713e6f9a97..bfa7871434f 100644 --- a/lib/response.js +++ b/lib/response.js @@ -684,9 +684,8 @@ res.format = function(obj){ var req = this.req; var next = req.next; - var fn = obj.default; - if (fn) delete obj.default; - var keys = Object.keys(obj); + var keys = Object.keys(obj) + .filter(function (v) { return v !== 'default' }) var key = keys.length > 0 ? req.accepts(keys) @@ -697,8 +696,8 @@ res.format = function(obj){ if (key) { this.set('Content-Type', normalizeType(key).value); obj[key](req, this, next); - } else if (fn) { - fn(); + } else if (obj.default) { + obj.default(req, this, next) } else { var err = new Error('Not Acceptable'); err.status = err.statusCode = 406; diff --git a/test/res.format.js b/test/res.format.js index 24e18d95528..45243d17a1b 100644 --- a/test/res.format.js +++ b/test/res.format.js @@ -50,7 +50,12 @@ var app3 = express(); app3.use(function(req, res, next){ res.format({ text: function(){ res.send('hey') }, - default: function(){ res.send('default') } + default: function (a, b, c) { + assert(req === a) + assert(res === b) + assert(next === c) + res.send('default') + } }) }); @@ -118,6 +123,28 @@ describe('res', function(){ .set('Accept', '*/*') .expect('hey', done); }) + + it('should be able to invoke other formatter', function (done) { + var app = express() + + app.use(function (req, res, next) { + res.format({ + json: function () { res.send('json') }, + default: function () { + res.header('x-default', '1') + this.json() + } + }) + }) + + request(app) + .get('/') + .set('Accept', 'text/plain') + .expect(200) + .expect('x-default', '1') + .expect('json') + .end(done) + }) }) describe('in router', function(){ From 1cc816993832eba829a2f556f7c08e27e6371301 Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Wed, 5 Feb 2020 17:56:51 +0100 Subject: [PATCH 591/889] deps: depd@2.0.0 closes #4174 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index d1aa9b3b88d..0b54e1d27b2 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,9 @@ unreleased * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Invoke `default` with same arguments as types in `res.format` * Support proper 205 responses using `res.send` + * deps: depd@2.0.0 + - Replace internal `eval` usage with `Function` constructor + - Use instance methods on `process` to check for listeners * deps: finalhandler@1.2.0 - Remove set content headers that break response - deps: on-finished@2.4.1 diff --git a/package.json b/package.json index 8f8959a4c33..d9fbe976986 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", From 5855339455a7f60774bef4166829e742a5056fa8 Mon Sep 17 00:00:00 2001 From: Chris Barth Date: Thu, 18 Apr 2019 09:12:33 -0400 Subject: [PATCH 592/889] Fix behavior of null/undefined as "maxAge" in res.cookie fixes #3935 closes #3936 --- History.md | 1 + lib/response.js | 10 +++++++--- test/res.cookie.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 0b54e1d27b2..8d9d39b2b80 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ unreleased * Add "root" option to `res.download` * Allow `options` without `filename` in `res.download` * Deprecate string and non-integer arguments to `res.status` + * Fix behavior of `null`/`undefined` as `maxAge` in `res.cookie` * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Invoke `default` with same arguments as types in `res.format` * Support proper 205 responses using `res.send` diff --git a/lib/response.js b/lib/response.js index bfa7871434f..eeeee1c806b 100644 --- a/lib/response.js +++ b/lib/response.js @@ -868,9 +868,13 @@ res.cookie = function (name, value, options) { val = 's:' + sign(val, secret); } - if ('maxAge' in opts) { - opts.expires = new Date(Date.now() + opts.maxAge); - opts.maxAge /= 1000; + if (opts.maxAge != null) { + var maxAge = opts.maxAge - 0 + + if (!isNaN(maxAge)) { + opts.expires = new Date(Date.now() + maxAge) + opts.maxAge = Math.floor(maxAge / 1000) + } } if (opts.path == null) { diff --git a/test/res.cookie.js b/test/res.cookie.js index d10e48646b6..e3a921301f4 100644 --- a/test/res.cookie.js +++ b/test/res.cookie.js @@ -111,6 +111,36 @@ describe('res', function(){ .expect(200, optionsCopy, done) }) + it('should not throw on null', function (done) { + var app = express() + + app.use(function (req, res) { + res.cookie('name', 'tobi', { maxAge: null }) + res.end() + }) + + request(app) + .get('/') + .expect(200) + .expect('Set-Cookie', 'name=tobi; Path=/') + .end(done) + }) + + it('should not throw on undefined', function (done) { + var app = express() + + app.use(function (req, res) { + res.cookie('name', 'tobi', { maxAge: undefined }) + res.end() + }) + + request(app) + .get('/') + .expect(200) + .expect('Set-Cookie', 'name=tobi; Path=/') + .end(done) + }) + it('should throw an error with invalid maxAge', function (done) { var app = express() From a10770286e7420c5a56ed3cc0b6add2c028ae56e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 27 Mar 2022 23:41:31 -0400 Subject: [PATCH 593/889] Use http-errors for res.format error --- History.md | 1 + lib/response.js | 8 ++++---- package.json | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 8d9d39b2b80..2e542333d91 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,7 @@ unreleased * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Invoke `default` with same arguments as types in `res.format` * Support proper 205 responses using `res.send` + * Use `http-errors` for `res.format` error * deps: depd@2.0.0 - Replace internal `eval` usage with `Function` constructor - Use instance methods on `process` to check for listeners diff --git a/lib/response.js b/lib/response.js index eeeee1c806b..d9b8db1c201 100644 --- a/lib/response.js +++ b/lib/response.js @@ -14,6 +14,7 @@ var Buffer = require('safe-buffer').Buffer var contentDisposition = require('content-disposition'); +var createError = require('http-errors') var deprecate = require('depd')('express'); var encodeUrl = require('encodeurl'); var escapeHtml = require('escape-html'); @@ -699,10 +700,9 @@ res.format = function(obj){ } else if (obj.default) { obj.default(req, this, next) } else { - var err = new Error('Not Acceptable'); - err.status = err.statusCode = 406; - err.types = normalizeTypes(keys).map(function(o){ return o.value }); - next(err); + next(createError(406, { + types: normalizeTypes(keys).map(function (o) { return o.value }) + })) } return this; diff --git a/package.json b/package.json index d9fbe976986..71c110e5f23 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "etag": "~1.8.1", "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "~2.3.0", From 32c558d414b4ac0f5bd70fa6a0f39a5558a7b016 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 2 Apr 2022 21:51:31 -0400 Subject: [PATCH 594/889] deps: body-parser@1.20.0 --- History.md | 10 ++ package.json | 2 +- test/express.json.js | 339 +++++++++++++++++++++++++------------ test/express.raw.js | 203 ++++++++++++++++++++-- test/express.text.js | 221 ++++++++++++++++++++---- test/express.urlencoded.js | 263 ++++++++++++++++++++-------- 6 files changed, 817 insertions(+), 221 deletions(-) diff --git a/History.md b/History.md index 2e542333d91..cba82afcbd2 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,16 @@ unreleased * Invoke `default` with same arguments as types in `res.format` * Support proper 205 responses using `res.send` * Use `http-errors` for `res.format` error + * deps: body-parser@1.20.0 + - Fix error message for json parse whitespace in `strict` + - Fix internal error when inflated body exceeds limit + - Prevent loss of async hooks context + - Prevent hanging when request already read + - deps: depd@2.0.0 + - deps: http-errors@2.0.0 + - deps: on-finished@2.4.1 + - deps: qs@6.10.3 + - deps: raw-body@2.5.1 * deps: depd@2.0.0 - Replace internal `eval` usage with `Function` constructor - Use instance methods on `process` to check for listeners diff --git a/package.json b/package.json index 71c110e5f23..ce6604bd7dd 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.2", + "body-parser": "1.20.0", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.4.2", diff --git a/test/express.json.js b/test/express.json.js index 53a39565a9b..a8cfebc41e2 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -1,10 +1,15 @@ 'use strict' var assert = require('assert') +var asyncHooks = tryRequire('async_hooks') var Buffer = require('safe-buffer').Buffer var express = require('..') var request = require('supertest') +var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' + ? describe + : describe.skip + describe('express.json()', function () { it('should parse JSON', function (done) { request(createApp()) @@ -38,6 +43,14 @@ describe('express.json()', function () { .expect(200, '{}', done) }) + it('should 400 when only whitespace', function (done) { + request(createApp()) + .post('/') + .set('Content-Type', 'application/json') + .send(' \n') + .expect(400, '[entity.parse.failed] ' + parseError(' '), done) + }) + it('should 400 when invalid content-length', function (done) { var app = express() @@ -59,6 +72,32 @@ describe('express.json()', function () { .expect(400, /content length/, done) }) + it('should 500 if stream not readable', function (done) { + var app = express() + + app.use(function (req, res, next) { + req.on('end', next) + req.resume() + }) + + app.use(express.json()) + + app.use(function (err, req, res, next) { + res.status(err.status || 500) + res.send('[' + err.type + '] ' + err.message) + }) + + app.post('/', function (req, res) { + res.json(req.body) + }) + + request(app) + .post('/') + .set('Content-Type', 'application/json') + .send('{"user":"tobi"}') + .expect(500, '[stream.not.readable] stream is not readable', done) + }) + it('should handle duplicated middleware', function (done) { var app = express() @@ -86,7 +125,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send('{:') - .expect(400, parseError('{:'), done) + .expect(400, '[entity.parse.failed] ' + parseError('{:'), done) }) it('should 400 for incomplete', function (done) { @@ -94,16 +133,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send('{"user"') - .expect(400, parseError('{"user"'), done) - }) - - it('should error with type = "entity.parse.failed"', function (done) { - request(this.app) - .post('/') - .set('Content-Type', 'application/json') - .set('X-Error-Property', 'type') - .send(' {"user"') - .expect(400, 'entity.parse.failed', done) + .expect(400, '[entity.parse.failed] ' + parseError('{"user"'), done) }) it('should include original body on error object', function (done) { @@ -124,24 +154,13 @@ describe('express.json()', function () { .set('Content-Type', 'application/json') .set('Content-Length', '1034') .send(JSON.stringify({ str: buf.toString() })) - .expect(413, done) - }) - - it('should error with type = "entity.too.large"', function (done) { - var buf = Buffer.alloc(1024, '.') - request(createApp({ limit: '1kb' })) - .post('/') - .set('Content-Type', 'application/json') - .set('Content-Length', '1034') - .set('X-Error-Property', 'type') - .send(JSON.stringify({ str: buf.toString() })) - .expect(413, 'entity.too.large', done) + .expect(413, '[entity.too.large] request entity too large', done) }) it('should 413 when over limit with chunked encoding', function (done) { + var app = createApp({ limit: '1kb' }) var buf = Buffer.alloc(1024, '.') - var server = createApp({ limit: '1kb' }) - var test = request(server).post('/') + var test = request(app).post('/') test.set('Content-Type', 'application/json') test.set('Transfer-Encoding', 'chunked') test.write('{"str":') @@ -149,6 +168,15 @@ describe('express.json()', function () { test.expect(413, done) }) + it('should 413 when inflated body over limit', function (done) { + var app = createApp({ limit: '1kb' }) + var test = request(app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/json') + test.write(Buffer.from('1f8b080000000000000aab562a2e2952b252d21b05a360148c58a0540b0066f7ce1e0a040000', 'hex')) + test.expect(413, done) + }) + it('should accept number of bytes', function (done) { var buf = Buffer.alloc(1024, '.') request(createApp({ limit: 1024 })) @@ -161,11 +189,11 @@ describe('express.json()', function () { it('should not change when options altered', function (done) { var buf = Buffer.alloc(1024, '.') var options = { limit: '1kb' } - var server = createApp(options) + var app = createApp(options) options.limit = '100kb' - request(server) + request(app) .post('/') .set('Content-Type', 'application/json') .send(JSON.stringify({ str: buf.toString() })) @@ -174,14 +202,23 @@ describe('express.json()', function () { it('should not hang response', function (done) { var buf = Buffer.alloc(10240, '.') - var server = createApp({ limit: '8kb' }) - var test = request(server).post('/') + var app = createApp({ limit: '8kb' }) + var test = request(app).post('/') test.set('Content-Type', 'application/json') test.write(buf) test.write(buf) test.write(buf) test.expect(413, done) }) + + it('should not error when inflating', function (done) { + var app = createApp({ limit: '1kb' }) + var test = request(app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/json') + test.write(Buffer.from('1f8b080000000000000aab562a2e2952b252d21b05a360148c58a0540b0066f7ce1e0a0400', 'hex')) + test.expect(413, done) + }) }) describe('with inflate option', function () { @@ -195,7 +232,7 @@ describe('express.json()', function () { test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/json') test.write(Buffer.from('1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000', 'hex')) - test.expect(415, 'content encoding unsupported', done) + test.expect(415, '[encoding.unsupported] content encoding unsupported', done) }) }) @@ -225,7 +262,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send('true') - .expect(400, parseError('#rue').replace('#', 't'), done) + .expect(400, '[entity.parse.failed] ' + parseError('#rue').replace('#', 't'), done) }) }) @@ -253,7 +290,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send('true') - .expect(400, parseError('#rue').replace('#', 't'), done) + .expect(400, '[entity.parse.failed] ' + parseError('#rue').replace('#', 't'), done) }) it('should not parse primitives with leading whitespaces', function (done) { @@ -261,7 +298,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send(' true') - .expect(400, parseError(' #rue').replace('#', 't'), done) + .expect(400, '[entity.parse.failed] ' + parseError(' #rue').replace('#', 't'), done) }) it('should allow leading whitespaces in JSON', function (done) { @@ -272,15 +309,6 @@ describe('express.json()', function () { .expect(200, '{"user":"tobi"}', done) }) - it('should error with type = "entity.parse.failed"', function (done) { - request(this.app) - .post('/') - .set('Content-Type', 'application/json') - .set('X-Error-Property', 'type') - .send('true') - .expect(400, 'entity.parse.failed', done) - }) - it('should include correct message in stack trace', function (done) { request(this.app) .post('/') @@ -397,65 +425,59 @@ describe('express.json()', function () { }) it('should error from verify', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x5b) throw new Error('no arrays') - } }) - - request(app) - .post('/') - .set('Content-Type', 'application/json') - .send('["tobi"]') - .expect(403, 'no arrays', done) - }) - - it('should error with type = "entity.verify.failed"', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x5b) throw new Error('no arrays') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x5b) throw new Error('no arrays') + } + }) request(app) .post('/') .set('Content-Type', 'application/json') - .set('X-Error-Property', 'type') .send('["tobi"]') - .expect(403, 'entity.verify.failed', done) + .expect(403, '[entity.verify.failed] no arrays', done) }) it('should allow custom codes', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] !== 0x5b) return - var err = new Error('no arrays') - err.status = 400 - throw err - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] !== 0x5b) return + var err = new Error('no arrays') + err.status = 400 + throw err + } + }) request(app) .post('/') .set('Content-Type', 'application/json') .send('["tobi"]') - .expect(400, 'no arrays', done) + .expect(400, '[entity.verify.failed] no arrays', done) }) it('should allow custom type', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] !== 0x5b) return - var err = new Error('no arrays') - err.type = 'foo.bar' - throw err - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] !== 0x5b) return + var err = new Error('no arrays') + err.type = 'foo.bar' + throw err + } + }) request(app) .post('/') .set('Content-Type', 'application/json') - .set('X-Error-Property', 'type') .send('["tobi"]') - .expect(403, 'foo.bar', done) + .expect(403, '[foo.bar] no arrays', done) }) it('should include original body on error object', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x5b) throw new Error('no arrays') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x5b) throw new Error('no arrays') + } + }) request(app) .post('/') @@ -466,9 +488,11 @@ describe('express.json()', function () { }) it('should allow pass-through', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x5b) throw new Error('no arrays') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x5b) throw new Error('no arrays') + } + }) request(app) .post('/') @@ -478,9 +502,11 @@ describe('express.json()', function () { }) it('should work with different charsets', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x5b) throw new Error('no arrays') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x5b) throw new Error('no arrays') + } + }) var test = request(app).post('/') test.set('Content-Type', 'application/json; charset=utf-16') @@ -489,14 +515,120 @@ describe('express.json()', function () { }) it('should 415 on unknown charset prior to verify', function (done) { - var app = createApp({ verify: function (req, res, buf) { - throw new Error('unexpected verify call') - } }) + var app = createApp({ + verify: function (req, res, buf) { + throw new Error('unexpected verify call') + } + }) var test = request(app).post('/') test.set('Content-Type', 'application/json; charset=x-bogus') test.write(Buffer.from('00000000', 'hex')) - test.expect(415, 'unsupported charset "X-BOGUS"', done) + test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done) + }) + }) + + describeAsyncHooks('async local storage', function () { + before(function () { + var app = express() + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(express.json()) + + app.use(function (req, res, next) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + next() + }) + + app.use(function (err, req, res, next) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + res.status(err.status || 500) + res.send('[' + err.type + '] ' + err.message) + }) + + app.post('/', function (req, res) { + res.json(req.body) + }) + + this.app = app + }) + + it('should presist store', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/json') + .send('{"user":"tobi"}') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('{"user":"tobi"}') + .end(done) + }) + + it('should presist store when unmatched content-type', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/fizzbuzz') + .send('buzz') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('{}') + .end(done) + }) + + it('should presist store when inflated', function (done) { + var test = request(this.app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/json') + test.write(Buffer.from('1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000', 'hex')) + test.expect(200) + test.expect('x-store-foo', 'bar') + test.expect('{"name":"论"}') + test.end(done) + }) + + it('should presist store when inflate error', function (done) { + var test = request(this.app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/json') + test.write(Buffer.from('1f8b080000000000000bab56cc4d55b2527ab16e97522d00515be1cc0e000000', 'hex')) + test.expect(400) + test.expect('x-store-foo', 'bar') + test.end(done) + }) + + it('should presist store when parse error', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/json') + .send('{"user":') + .expect(400) + .expect('x-store-foo', 'bar') + .end(done) + }) + + it('should presist store when limit exceeded', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/json') + .send('{"user":"' + Buffer.alloc(1024 * 100, '.').toString() + '"}') + .expect(413) + .expect('x-store-foo', 'bar') + .end(done) }) }) @@ -538,15 +670,7 @@ describe('express.json()', function () { var test = request(this.app).post('/') test.set('Content-Type', 'application/json; charset=koi8-r') test.write(Buffer.from('7b226e616d65223a22cec5d4227d', 'hex')) - test.expect(415, 'unsupported charset "KOI8-R"', done) - }) - - it('should error with type = "charset.unsupported"', function (done) { - var test = request(this.app).post('/') - test.set('Content-Type', 'application/json; charset=koi8-r') - test.set('X-Error-Property', 'type') - test.write(Buffer.from('7b226e616d65223a22cec5d4227d', 'hex')) - test.expect(415, 'charset.unsupported', done) + test.expect(415, '[charset.unsupported] unsupported charset "KOI8-R"', done) }) }) @@ -599,16 +723,7 @@ describe('express.json()', function () { test.set('Content-Encoding', 'nulls') test.set('Content-Type', 'application/json') test.write(Buffer.from('000000000000', 'hex')) - test.expect(415, 'unsupported content encoding "nulls"', done) - }) - - it('should error with type = "encoding.unsupported"', function (done) { - var test = request(this.app).post('/') - test.set('Content-Encoding', 'nulls') - test.set('Content-Type', 'application/json') - test.set('X-Error-Property', 'type') - test.write(Buffer.from('000000000000', 'hex')) - test.expect(415, 'encoding.unsupported', done) + test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done) }) it('should 400 on malformed encoding', function (done) { @@ -639,7 +754,9 @@ function createApp (options) { app.use(function (err, req, res, next) { res.status(err.status || 500) - res.send(String(err[req.headers['x-error-property'] || 'message'])) + res.send(String(req.headers['x-error-property'] + ? err[req.headers['x-error-property']] + : ('[' + err.type + '] ' + err.message))) }) app.post('/', function (req, res) { @@ -663,3 +780,11 @@ function shouldContainInBody (str) { 'expected \'' + res.text + '\' to contain \'' + str + '\'') } } + +function tryRequire (name) { + try { + return require(name) + } catch (e) { + return {} + } +} diff --git a/test/express.raw.js b/test/express.raw.js index cbd0736e7cb..4aa62bb85bc 100644 --- a/test/express.raw.js +++ b/test/express.raw.js @@ -1,10 +1,15 @@ 'use strict' var assert = require('assert') +var asyncHooks = tryRequire('async_hooks') var Buffer = require('safe-buffer').Buffer var express = require('..') var request = require('supertest') +var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' + ? describe + : describe.skip + describe('express.raw()', function () { before(function () { this.app = createApp() @@ -60,6 +65,36 @@ describe('express.raw()', function () { .expect(200, { buf: '' }, done) }) + it('should 500 if stream not readable', function (done) { + var app = express() + + app.use(function (req, res, next) { + req.on('end', next) + req.resume() + }) + + app.use(express.raw()) + + app.use(function (err, req, res, next) { + res.status(err.status || 500) + res.send('[' + err.type + '] ' + err.message) + }) + + app.post('/', function (req, res) { + if (Buffer.isBuffer(req.body)) { + res.json({ buf: req.body.toString('hex') }) + } else { + res.json(req.body) + } + }) + + request(app) + .post('/') + .set('Content-Type', 'application/octet-stream') + .send('the user is tobi') + .expect(500, '[stream.not.readable] stream is not readable', done) + }) + it('should handle duplicated middleware', function (done) { var app = express() @@ -102,6 +137,15 @@ describe('express.raw()', function () { test.expect(413, done) }) + it('should 413 when inflated body over limit', function (done) { + var app = createApp({ limit: '1kb' }) + var test = request(app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/octet-stream') + test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a14704040000', 'hex')) + test.expect(413, done) + }) + it('should accept number of bytes', function (done) { var buf = Buffer.alloc(1028, '.') var app = createApp({ limit: 1024 }) @@ -134,6 +178,15 @@ describe('express.raw()', function () { test.write(buf) test.expect(413, done) }) + + it('should not error when inflating', function (done) { + var app = createApp({ limit: '1kb' }) + var test = request(app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/octet-stream') + test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a147040400', 'hex')) + test.expect(413, done) + }) }) describe('with inflate option', function () { @@ -147,7 +200,7 @@ describe('express.raw()', function () { test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/octet-stream') test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex')) - test.expect(415, 'content encoding unsupported', done) + test.expect(415, '[encoding.unsupported] content encoding unsupported', done) }) }) @@ -263,34 +316,40 @@ describe('express.raw()', function () { }) it('should error from verify', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x00) throw new Error('no leading null') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x00) throw new Error('no leading null') + } + }) var test = request(app).post('/') test.set('Content-Type', 'application/octet-stream') test.write(Buffer.from('000102', 'hex')) - test.expect(403, 'no leading null', done) + test.expect(403, '[entity.verify.failed] no leading null', done) }) it('should allow custom codes', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] !== 0x00) return - var err = new Error('no leading null') - err.status = 400 - throw err - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] !== 0x00) return + var err = new Error('no leading null') + err.status = 400 + throw err + } + }) var test = request(app).post('/') test.set('Content-Type', 'application/octet-stream') test.write(Buffer.from('000102', 'hex')) - test.expect(400, 'no leading null', done) + test.expect(400, '[entity.verify.failed] no leading null', done) }) it('should allow pass-through', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x00) throw new Error('no leading null') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x00) throw new Error('no leading null') + } + }) var test = request(app).post('/') test.set('Content-Type', 'application/octet-stream') @@ -299,6 +358,104 @@ describe('express.raw()', function () { }) }) + describeAsyncHooks('async local storage', function () { + before(function () { + var app = express() + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(express.raw()) + + app.use(function (req, res, next) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + next() + }) + + app.use(function (err, req, res, next) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + res.status(err.status || 500) + res.send('[' + err.type + '] ' + err.message) + }) + + app.post('/', function (req, res) { + if (Buffer.isBuffer(req.body)) { + res.json({ buf: req.body.toString('hex') }) + } else { + res.json(req.body) + } + }) + + this.app = app + }) + + it('should presist store', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/octet-stream') + .send('the user is tobi') + .expect(200) + .expect('x-store-foo', 'bar') + .expect({ buf: '746865207573657220697320746f6269' }) + .end(done) + }) + + it('should presist store when unmatched content-type', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/fizzbuzz') + .send('buzz') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('{}') + .end(done) + }) + + it('should presist store when inflated', function (done) { + var test = request(this.app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/octet-stream') + test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex')) + test.expect(200) + test.expect('x-store-foo', 'bar') + test.expect({ buf: '6e616d653de8aeba' }) + test.end(done) + }) + + it('should presist store when inflate error', function (done) { + var test = request(this.app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/octet-stream') + test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad6080000', 'hex')) + test.expect(400) + test.expect('x-store-foo', 'bar') + test.end(done) + }) + + it('should presist store when limit exceeded', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/octet-stream') + .send('the user is ' + Buffer.alloc(1024 * 100, '.').toString()) + .expect(413) + .expect('x-store-foo', 'bar') + .end(done) + }) + }) + describe('charset', function () { before(function () { this.app = createApp() @@ -356,12 +513,12 @@ describe('express.raw()', function () { test.expect(200, { buf: '6e616d653de8aeba' }, done) }) - it('should fail on unknown encoding', function (done) { + it('should 415 on unknown encoding', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'nulls') test.set('Content-Type', 'application/octet-stream') test.write(Buffer.from('000000000000', 'hex')) - test.expect(415, 'unsupported content encoding "nulls"', done) + test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done) }) }) }) @@ -373,7 +530,9 @@ function createApp (options) { app.use(function (err, req, res, next) { res.status(err.status || 500) - res.send(String(err[req.headers['x-error-property'] || 'message'])) + res.send(String(req.headers['x-error-property'] + ? err[req.headers['x-error-property']] + : ('[' + err.type + '] ' + err.message))) }) app.post('/', function (req, res) { @@ -386,3 +545,11 @@ function createApp (options) { return app } + +function tryRequire (name) { + try { + return require(name) + } catch (e) { + return {} + } +} diff --git a/test/express.text.js b/test/express.text.js index ebc12cd1098..cb7750a525c 100644 --- a/test/express.text.js +++ b/test/express.text.js @@ -1,10 +1,15 @@ 'use strict' var assert = require('assert') +var asyncHooks = tryRequire('async_hooks') var Buffer = require('safe-buffer').Buffer var express = require('..') var request = require('supertest') +var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' + ? describe + : describe.skip + describe('express.text()', function () { before(function () { this.app = createApp() @@ -56,6 +61,32 @@ describe('express.text()', function () { .expect(200, '""', done) }) + it('should 500 if stream not readable', function (done) { + var app = express() + + app.use(function (req, res, next) { + req.on('end', next) + req.resume() + }) + + app.use(express.text()) + + app.use(function (err, req, res, next) { + res.status(err.status || 500) + res.send('[' + err.type + '] ' + err.message) + }) + + app.post('/', function (req, res) { + res.json(req.body) + }) + + request(app) + .post('/') + .set('Content-Type', 'text/plain') + .send('user is tobi') + .expect(500, '[stream.not.readable] stream is not readable', done) + }) + it('should handle duplicated middleware', function (done) { var app = express() @@ -75,16 +106,16 @@ describe('express.text()', function () { describe('with defaultCharset option', function () { it('should change default charset', function (done) { - var app = createApp({ defaultCharset: 'koi8-r' }) - var test = request(app).post('/') + var server = createApp({ defaultCharset: 'koi8-r' }) + var test = request(server).post('/') test.set('Content-Type', 'text/plain') test.write(Buffer.from('6e616d6520697320cec5d4', 'hex')) test.expect(200, '"name is нет"', done) }) it('should honor content-type charset', function (done) { - var app = createApp({ defaultCharset: 'koi8-r' }) - var test = request(app).post('/') + var server = createApp({ defaultCharset: 'koi8-r' }) + var test = request(server).post('/') test.set('Content-Type', 'text/plain; charset=utf-8') test.write(Buffer.from('6e616d6520697320e8aeba', 'hex')) test.expect(200, '"name is 论"', done) @@ -103,8 +134,8 @@ describe('express.text()', function () { }) it('should 413 when over limit with chunked encoding', function (done) { - var buf = Buffer.alloc(1028, '.') var app = createApp({ limit: '1kb' }) + var buf = Buffer.alloc(1028, '.') var test = request(app).post('/') test.set('Content-Type', 'text/plain') test.set('Transfer-Encoding', 'chunked') @@ -112,6 +143,15 @@ describe('express.text()', function () { test.expect(413, done) }) + it('should 413 when inflated body over limit', function (done) { + var app = createApp({ limit: '1kb' }) + var test = request(app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'text/plain') + test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a14704040000', 'hex')) + test.expect(413, done) + }) + it('should accept number of bytes', function (done) { var buf = Buffer.alloc(1028, '.') request(createApp({ limit: 1024 })) @@ -136,8 +176,8 @@ describe('express.text()', function () { }) it('should not hang response', function (done) { - var buf = Buffer.alloc(10240, '.') var app = createApp({ limit: '8kb' }) + var buf = Buffer.alloc(10240, '.') var test = request(app).post('/') test.set('Content-Type', 'text/plain') test.write(buf) @@ -145,6 +185,17 @@ describe('express.text()', function () { test.write(buf) test.expect(413, done) }) + + it('should not error when inflating', function (done) { + var app = createApp({ limit: '1kb' }) + var test = request(app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'text/plain') + test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a1470404', 'hex')) + setTimeout(function () { + test.expect(413, done) + }, 100) + }) }) describe('with inflate option', function () { @@ -158,7 +209,7 @@ describe('express.text()', function () { test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'text/plain') test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex')) - test.expect(415, 'content encoding unsupported', done) + test.expect(415, '[encoding.unsupported] content encoding unsupported', done) }) }) @@ -278,36 +329,42 @@ describe('express.text()', function () { }) it('should error from verify', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x20) throw new Error('no leading space') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x20) throw new Error('no leading space') + } + }) request(app) .post('/') .set('Content-Type', 'text/plain') .send(' user is tobi') - .expect(403, 'no leading space', done) + .expect(403, '[entity.verify.failed] no leading space', done) }) it('should allow custom codes', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] !== 0x20) return - var err = new Error('no leading space') - err.status = 400 - throw err - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] !== 0x20) return + var err = new Error('no leading space') + err.status = 400 + throw err + } + }) request(app) .post('/') .set('Content-Type', 'text/plain') .send(' user is tobi') - .expect(400, 'no leading space', done) + .expect(400, '[entity.verify.failed] no leading space', done) }) it('should allow pass-through', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x20) throw new Error('no leading space') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x20) throw new Error('no leading space') + } + }) request(app) .post('/') @@ -317,14 +374,110 @@ describe('express.text()', function () { }) it('should 415 on unknown charset prior to verify', function (done) { - var app = createApp({ verify: function (req, res, buf) { - throw new Error('unexpected verify call') - } }) + var app = createApp({ + verify: function (req, res, buf) { + throw new Error('unexpected verify call') + } + }) var test = request(app).post('/') test.set('Content-Type', 'text/plain; charset=x-bogus') test.write(Buffer.from('00000000', 'hex')) - test.expect(415, 'unsupported charset "X-BOGUS"', done) + test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done) + }) + }) + + describeAsyncHooks('async local storage', function () { + before(function () { + var app = express() + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(express.text()) + + app.use(function (req, res, next) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + next() + }) + + app.use(function (err, req, res, next) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + res.status(err.status || 500) + res.send('[' + err.type + '] ' + err.message) + }) + + app.post('/', function (req, res) { + res.json(req.body) + }) + + this.app = app + }) + + it('should presist store', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'text/plain') + .send('user is tobi') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('"user is tobi"') + .end(done) + }) + + it('should presist store when unmatched content-type', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/fizzbuzz') + .send('buzz') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('{}') + .end(done) + }) + + it('should presist store when inflated', function (done) { + var test = request(this.app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'text/plain') + test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex')) + test.expect(200) + test.expect('x-store-foo', 'bar') + test.expect('"name is 论"') + test.end(done) + }) + + it('should presist store when inflate error', function (done) { + var test = request(this.app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'text/plain') + test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b0000', 'hex')) + test.expect(400) + test.expect('x-store-foo', 'bar') + test.end(done) + }) + + it('should presist store when limit exceeded', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'text/plain') + .send('user is ' + Buffer.alloc(1024 * 100, '.').toString()) + .expect(413) + .expect('x-store-foo', 'bar') + .end(done) }) }) @@ -366,7 +519,7 @@ describe('express.text()', function () { var test = request(this.app).post('/') test.set('Content-Type', 'text/plain; charset=x-bogus') test.write(Buffer.from('00000000', 'hex')) - test.expect(415, 'unsupported charset "X-BOGUS"', done) + test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done) }) }) @@ -414,12 +567,12 @@ describe('express.text()', function () { test.expect(200, '"name is 论"', done) }) - it('should fail on unknown encoding', function (done) { + it('should 415 on unknown encoding', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'nulls') test.set('Content-Type', 'text/plain') test.write(Buffer.from('000000000000', 'hex')) - test.expect(415, 'unsupported content encoding "nulls"', done) + test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done) }) }) }) @@ -431,7 +584,9 @@ function createApp (options) { app.use(function (err, req, res, next) { res.status(err.status || 500) - res.send(err.message) + res.send(String(req.headers['x-error-property'] + ? err[req.headers['x-error-property']] + : ('[' + err.type + '] ' + err.message))) }) app.post('/', function (req, res) { @@ -440,3 +595,11 @@ function createApp (options) { return app } + +function tryRequire (name) { + try { + return require(name) + } catch (e) { + return {} + } +} diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index 340eb74316c..e07432c86c3 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -1,10 +1,15 @@ 'use strict' var assert = require('assert') +var asyncHooks = tryRequire('async_hooks') var Buffer = require('safe-buffer').Buffer var express = require('..') var request = require('supertest') +var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' + ? describe + : describe.skip + describe('express.urlencoded()', function () { before(function () { this.app = createApp() @@ -57,6 +62,32 @@ describe('express.urlencoded()', function () { .expect(200, '{}', done) }) + it('should 500 if stream not readable', function (done) { + var app = express() + + app.use(function (req, res, next) { + req.on('end', next) + req.resume() + }) + + app.use(express.urlencoded()) + + app.use(function (err, req, res, next) { + res.status(err.status || 500) + res.send('[' + err.type + '] ' + err.message) + }) + + app.post('/', function (req, res) { + res.json(req.body) + }) + + request(app) + .post('/') + .set('Content-Type', 'application/x-www-form-urlencoded') + .send('user=tobi') + .expect(500, '[stream.not.readable] stream is not readable', done) + }) + it('should handle duplicated middleware', function (done) { var app = express() @@ -217,7 +248,7 @@ describe('express.urlencoded()', function () { test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/x-www-form-urlencoded') test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex')) - test.expect(415, 'content encoding unsupported', done) + test.expect(415, '[encoding.unsupported] content encoding unsupported', done) }) }) @@ -248,8 +279,8 @@ describe('express.urlencoded()', function () { }) it('should 413 when over limit with chunked encoding', function (done) { - var buf = Buffer.alloc(1024, '.') var app = createApp({ limit: '1kb' }) + var buf = Buffer.alloc(1024, '.') var test = request(app).post('/') test.set('Content-Type', 'application/x-www-form-urlencoded') test.set('Transfer-Encoding', 'chunked') @@ -258,6 +289,15 @@ describe('express.urlencoded()', function () { test.expect(413, done) }) + it('should 413 when inflated body over limit', function (done) { + var app = createApp({ limit: '1kb' }) + var test = request(app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/x-www-form-urlencoded') + test.write(Buffer.from('1f8b080000000000000a2b2e29b2d51b05a360148c580000a0351f9204040000', 'hex')) + test.expect(413, done) + }) + it('should accept number of bytes', function (done) { var buf = Buffer.alloc(1024, '.') request(createApp({ limit: 1024 })) @@ -282,8 +322,8 @@ describe('express.urlencoded()', function () { }) it('should not hang response', function (done) { - var buf = Buffer.alloc(10240, '.') var app = createApp({ limit: '8kb' }) + var buf = Buffer.alloc(10240, '.') var test = request(app).post('/') test.set('Content-Type', 'application/x-www-form-urlencoded') test.write(buf) @@ -291,6 +331,15 @@ describe('express.urlencoded()', function () { test.write(buf) test.expect(413, done) }) + + it('should not error when inflating', function (done) { + var app = createApp({ limit: '1kb' }) + var test = request(app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/x-www-form-urlencoded') + test.write(Buffer.from('1f8b080000000000000a2b2e29b2d51b05a360148c580000a0351f92040400', 'hex')) + test.expect(413, done) + }) }) describe('with parameterLimit option', function () { @@ -310,16 +359,7 @@ describe('express.urlencoded()', function () { .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(11)) - .expect(413, /too many parameters/, done) - }) - - it('should error with type = "parameters.too.many"', function (done) { - request(createApp({ extended: false, parameterLimit: 10 })) - .post('/') - .set('Content-Type', 'application/x-www-form-urlencoded') - .set('X-Error-Property', 'type') - .send(createManyParams(11)) - .expect(413, 'parameters.too.many', done) + .expect(413, '[parameters.too.many] too many parameters', done) }) it('should work when at the limit', function (done) { @@ -374,16 +414,7 @@ describe('express.urlencoded()', function () { .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(11)) - .expect(413, /too many parameters/, done) - }) - - it('should error with type = "parameters.too.many"', function (done) { - request(createApp({ extended: true, parameterLimit: 10 })) - .post('/') - .set('Content-Type', 'application/x-www-form-urlencoded') - .set('X-Error-Property', 'type') - .send(createManyParams(11)) - .expect(413, 'parameters.too.many', done) + .expect(413, '[parameters.too.many] too many parameters', done) }) it('should work when at the limit', function (done) { @@ -526,65 +557,59 @@ describe('express.urlencoded()', function () { }) it('should error from verify', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x20) throw new Error('no leading space') - } }) - - request(app) - .post('/') - .set('Content-Type', 'application/x-www-form-urlencoded') - .send(' user=tobi') - .expect(403, 'no leading space', done) - }) - - it('should error with type = "entity.verify.failed"', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x20) throw new Error('no leading space') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x20) throw new Error('no leading space') + } + }) request(app) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') - .set('X-Error-Property', 'type') .send(' user=tobi') - .expect(403, 'entity.verify.failed', done) + .expect(403, '[entity.verify.failed] no leading space', done) }) it('should allow custom codes', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] !== 0x20) return - var err = new Error('no leading space') - err.status = 400 - throw err - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] !== 0x20) return + var err = new Error('no leading space') + err.status = 400 + throw err + } + }) request(app) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(' user=tobi') - .expect(400, 'no leading space', done) + .expect(400, '[entity.verify.failed] no leading space', done) }) it('should allow custom type', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] !== 0x20) return - var err = new Error('no leading space') - err.type = 'foo.bar' - throw err - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] !== 0x20) return + var err = new Error('no leading space') + err.type = 'foo.bar' + throw err + } + }) request(app) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') - .set('X-Error-Property', 'type') .send(' user=tobi') - .expect(403, 'foo.bar', done) + .expect(403, '[foo.bar] no leading space', done) }) it('should allow pass-through', function (done) { - var app = createApp({ verify: function (req, res, buf) { - if (buf[0] === 0x5b) throw new Error('no arrays') - } }) + var app = createApp({ + verify: function (req, res, buf) { + if (buf[0] === 0x5b) throw new Error('no arrays') + } + }) request(app) .post('/') @@ -594,14 +619,110 @@ describe('express.urlencoded()', function () { }) it('should 415 on unknown charset prior to verify', function (done) { - var app = createApp({ verify: function (req, res, buf) { - throw new Error('unexpected verify call') - } }) + var app = createApp({ + verify: function (req, res, buf) { + throw new Error('unexpected verify call') + } + }) var test = request(app).post('/') test.set('Content-Type', 'application/x-www-form-urlencoded; charset=x-bogus') test.write(Buffer.from('00000000', 'hex')) - test.expect(415, 'unsupported charset "X-BOGUS"', done) + test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done) + }) + }) + + describeAsyncHooks('async local storage', function () { + before(function () { + var app = express() + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(express.urlencoded()) + + app.use(function (req, res, next) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + next() + }) + + app.use(function (err, req, res, next) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + res.status(err.status || 500) + res.send('[' + err.type + '] ' + err.message) + }) + + app.post('/', function (req, res) { + res.json(req.body) + }) + + this.app = app + }) + + it('should presist store', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/x-www-form-urlencoded') + .send('user=tobi') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('{"user":"tobi"}') + .end(done) + }) + + it('should presist store when unmatched content-type', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/fizzbuzz') + .send('buzz') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('{}') + .end(done) + }) + + it('should presist store when inflated', function (done) { + var test = request(this.app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/x-www-form-urlencoded') + test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex')) + test.expect(200) + test.expect('x-store-foo', 'bar') + test.expect('{"name":"论"}') + test.end(done) + }) + + it('should presist store when inflate error', function (done) { + var test = request(this.app).post('/') + test.set('Content-Encoding', 'gzip') + test.set('Content-Type', 'application/x-www-form-urlencoded') + test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad6080000', 'hex')) + test.expect(400) + test.expect('x-store-foo', 'bar') + test.end(done) + }) + + it('should presist store when limit exceeded', function (done) { + request(this.app) + .post('/') + .set('Content-Type', 'application/x-www-form-urlencoded') + .send('user=' + Buffer.alloc(1024 * 100, '.').toString()) + .expect(413) + .expect('x-store-foo', 'bar') + .end(done) }) }) @@ -636,7 +757,7 @@ describe('express.urlencoded()', function () { var test = request(this.app).post('/') test.set('Content-Type', 'application/x-www-form-urlencoded; charset=koi8-r') test.write(Buffer.from('6e616d653dcec5d4', 'hex')) - test.expect(415, 'unsupported charset "KOI8-R"', done) + test.expect(415, '[charset.unsupported] unsupported charset "KOI8-R"', done) }) }) @@ -684,12 +805,12 @@ describe('express.urlencoded()', function () { test.expect(200, '{"name":"论"}', done) }) - it('should fail on unknown encoding', function (done) { + it('should 415 on unknown encoding', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'nulls') test.set('Content-Type', 'application/x-www-form-urlencoded') test.write(Buffer.from('000000000000', 'hex')) - test.expect(415, 'unsupported content encoding "nulls"', done) + test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done) }) }) }) @@ -718,7 +839,9 @@ function createApp (options) { app.use(function (err, req, res, next) { res.status(err.status || 500) - res.send(String(err[req.headers['x-error-property'] || 'message'])) + res.send(String(req.headers['x-error-property'] + ? err[req.headers['x-error-property']] + : ('[' + err.type + '] ' + err.message))) }) app.post('/', function (req, res) { @@ -733,3 +856,11 @@ function expectKeyCount (count) { assert.strictEqual(Object.keys(JSON.parse(res.text)).length, count) } } + +function tryRequire (name) { + try { + return require(name) + } catch (e) { + return {} + } +} From 1df75763e315bd0582669238cd14baadec1d6db5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 2 Apr 2022 21:56:41 -0400 Subject: [PATCH 595/889] deps: qs@6.10.3 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index cba82afcbd2..ef5ce5fc020 100644 --- a/History.md +++ b/History.md @@ -26,6 +26,7 @@ unreleased - Remove set content headers that break response - deps: on-finished@2.4.1 - deps: statuses@2.0.1 + * deps: qs@6.10.3 * deps: send@0.18.0 - Fix emitted 416 error missing headers property - Limit the headers removed for 304 response diff --git a/package.json b/package.json index ce6604bd7dd..04e39b06e1e 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.7", + "qs": "6.10.3", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", From 980d881e3b023db079de60477a2588a91f046ca5 Mon Sep 17 00:00:00 2001 From: 3imed-jaberi Date: Fri, 3 Jul 2020 05:38:59 +0200 Subject: [PATCH 596/889] deps: statuses@2.0.1 closes #4336 --- History.md | 3 +++ lib/response.js | 8 ++++---- package.json | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index ef5ce5fc020..ef9bbb6e427 100644 --- a/History.md +++ b/History.md @@ -37,6 +37,9 @@ unreleased - deps: statuses@2.0.1 * deps: serve-static@1.15.0 - deps: send@0.18.0 + * deps: statuses@2.0.1 + - Remove code 306 + - Rename `425 Unordered Collection` to standard `425 Too Early` 4.17.3 / 2022-02-16 =================== diff --git a/lib/response.js b/lib/response.js index d9b8db1c201..fede486c06d 100644 --- a/lib/response.js +++ b/lib/response.js @@ -139,7 +139,7 @@ res.send = function send(body) { deprecate('res.send(status): Use res.sendStatus(status) instead'); this.statusCode = chunk; - chunk = statuses[chunk] + chunk = statuses.message[chunk] } switch (typeof chunk) { @@ -367,7 +367,7 @@ res.jsonp = function jsonp(obj) { */ res.sendStatus = function sendStatus(statusCode) { - var body = statuses[statusCode] || String(statusCode) + var body = statuses.message[statusCode] || String(statusCode) this.statusCode = statusCode; this.type('txt'); @@ -955,12 +955,12 @@ res.redirect = function redirect(url) { // Support text/{plain,html} by default this.format({ text: function(){ - body = statuses[status] + '. Redirecting to ' + address + body = statuses.message[status] + '. Redirecting to ' + address }, html: function(){ var u = escapeHtml(address); - body = '

        ' + statuses[status] + '. Redirecting to ' + u + '

        ' + body = '

        ' + statuses.message[status] + '. Redirecting to ' + u + '

        ' }, default: function(){ diff --git a/package.json b/package.json index 04e39b06e1e..1e1f6740977 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "send": "0.18.0", "serve-static": "1.15.0", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" From 2e2d78c4d99829250018c6e4d20f3c6377a90683 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 3 Apr 2022 01:15:37 -0400 Subject: [PATCH 597/889] deps: on-finished@2.4.1 --- History.md | 2 + package.json | 2 +- test/res.download.js | 73 ++++++++++++++++++++++++ test/res.sendFile.js | 129 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index ef9bbb6e427..84efe9b4d8a 100644 --- a/History.md +++ b/History.md @@ -26,6 +26,8 @@ unreleased - Remove set content headers that break response - deps: on-finished@2.4.1 - deps: statuses@2.0.1 + * deps: on-finished@2.4.1 + - Prevent loss of async hooks context * deps: qs@6.10.3 * deps: send@0.18.0 - Fix emitted 416 error missing headers property diff --git a/package.json b/package.json index 1e1f6740977..dfce12352ca 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", diff --git a/test/res.download.js b/test/res.download.js index 91b074e8bf6..b52e66803c6 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -1,6 +1,8 @@ 'use strict' var after = require('after'); +var assert = require('assert') +var asyncHooks = tryRequire('async_hooks') var Buffer = require('safe-buffer').Buffer var express = require('..'); var path = require('path') @@ -9,6 +11,10 @@ var utils = require('./support/utils') var FIXTURES_PATH = path.join(__dirname, 'fixtures') +var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' + ? describe + : describe.skip + describe('res', function(){ describe('.download(path)', function(){ it('should transfer as an attachment', function(done){ @@ -84,6 +90,65 @@ describe('res', function(){ .expect('Content-Disposition', 'attachment; filename="user.html"') .expect(200, cb); }) + + describeAsyncHooks('async local storage', function () { + it('should presist store', function (done) { + var app = express() + var cb = after(2, done) + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(function (req, res) { + res.download('test/fixtures/name.txt', function (err) { + if (err) return cb(err) + + var local = req.asyncLocalStorage.getStore() + + assert.strictEqual(local.foo, 'bar') + cb() + }) + }) + + request(app) + .get('/') + .expect('Content-Type', 'text/plain; charset=UTF-8') + .expect('Content-Disposition', 'attachment; filename="name.txt"') + .expect(200, 'tobi', cb) + }) + + it('should presist store on error', function (done) { + var app = express() + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(function (req, res) { + res.download('test/fixtures/does-not-exist', function (err) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + res.send(err ? 'got ' + err.status + ' error' : 'no error') + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('got 404 error') + .end(done) + }) + }) }) describe('.download(path, options)', function () { @@ -423,3 +488,11 @@ describe('res', function(){ }) }) }) + +function tryRequire (name) { + try { + return require(name) + } catch (e) { + return {} + } +} diff --git a/test/res.sendFile.js b/test/res.sendFile.js index e828c17e255..ba5c33516b1 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -1,6 +1,7 @@ 'use strict' var after = require('after'); +var asyncHooks = tryRequire('async_hooks') var Buffer = require('safe-buffer').Buffer var express = require('../') , request = require('supertest') @@ -10,6 +11,10 @@ var path = require('path'); var fixtures = path.join(__dirname, 'fixtures'); var utils = require('./support/utils'); +var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' + ? describe + : describe.skip + describe('res', function(){ describe('.sendFile(path)', function () { it('should error missing path', function (done) { @@ -261,6 +266,64 @@ describe('res', function(){ .get('/') .expect(200, 'got 404 error', done) }) + + describeAsyncHooks('async local storage', function () { + it('should presist store', function (done) { + var app = express() + var cb = after(2, done) + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(function (req, res) { + res.sendFile(path.resolve(fixtures, 'name.txt'), function (err) { + if (err) return cb(err) + + var local = req.asyncLocalStorage.getStore() + + assert.strictEqual(local.foo, 'bar') + cb() + }) + }) + + request(app) + .get('/') + .expect('Content-Type', 'text/plain; charset=UTF-8') + .expect(200, 'tobi', cb) + }) + + it('should presist store on error', function (done) { + var app = express() + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(function (req, res) { + res.sendFile(path.resolve(fixtures, 'does-not-exist'), function (err) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + res.send(err ? 'got ' + err.status + ' error' : 'no error') + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('got 404 error') + .end(done) + }) + }) }) describe('.sendFile(path, options)', function () { @@ -999,6 +1062,64 @@ describe('res', function(){ .get('/') .end(function(){}); }) + + describeAsyncHooks('async local storage', function () { + it('should presist store', function (done) { + var app = express() + var cb = after(2, done) + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(function (req, res) { + res.sendfile('test/fixtures/name.txt', function (err) { + if (err) return cb(err) + + var local = req.asyncLocalStorage.getStore() + + assert.strictEqual(local.foo, 'bar') + cb() + }) + }) + + request(app) + .get('/') + .expect('Content-Type', 'text/plain; charset=UTF-8') + .expect(200, 'tobi', cb) + }) + + it('should presist store on error', function (done) { + var app = express() + var store = { foo: 'bar' } + + app.use(function (req, res, next) { + req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage.run(store, next) + }) + + app.use(function (req, res) { + res.sendfile('test/fixtures/does-not-exist', function (err) { + var local = req.asyncLocalStorage.getStore() + + if (local) { + res.setHeader('x-store-foo', String(local.foo)) + } + + res.send(err ? 'got ' + err.status + ' error' : 'no error') + }) + }) + + request(app) + .get('/') + .expect(200) + .expect('x-store-foo', 'bar') + .expect('got 404 error') + .end(done) + }) + }) }) describe('.sendfile(path)', function(){ @@ -1280,3 +1401,11 @@ function createApp(path, options, fn) { return app; } + +function tryRequire (name) { + try { + return require(name) + } catch (e) { + return {} + } +} From 04da4aaf1a484e81856fc4713340300e4d84d573 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 7 Apr 2022 19:17:10 -0400 Subject: [PATCH 598/889] build: use supertest@3.4.2 for Node.js 6.x --- .github/workflows/ci.yml | 2 +- appveyor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b153d1b436..83a8edee87d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,7 +61,7 @@ jobs: - name: Node.js 6.x node-version: "6.17" - npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6 + npm-i: mocha@6.2.2 nyc@14.1.1 supertest@3.4.2 - name: Node.js 7.x node-version: "7.10" diff --git a/appveyor.yml b/appveyor.yml index 2a2507b411b..93ea2c81616 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -71,11 +71,11 @@ install: - ps: | # supertest for http calls # - use 2.0.0 for Node.js < 4 - # - use 3.4.2 for Node.js < 6 + # - use 3.4.2 for Node.js < 7 # - use 6.1.6 for Node.js < 8 if ([int]$env:nodejs_version.split(".")[0] -lt 4) { npm install --silent --save-dev supertest@2.0.0 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) { + } elseif ([int]$env:nodejs_version.split(".")[0] -lt 7) { npm install --silent --save-dev supertest@3.4.2 } elseif ([int]$env:nodejs_version.split(".")[0] -lt 8) { npm install --silent --save-dev supertest@6.1.6 From 1b2e097be2f5b62b7db7dae09f399ace54836e0a Mon Sep 17 00:00:00 2001 From: Hashen <37979557+Hashen110@users.noreply.github.com> Date: Thu, 7 Apr 2022 21:14:16 +0530 Subject: [PATCH 599/889] tests: fix typo in description closes #4882 --- test/res.sendFile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/res.sendFile.js b/test/res.sendFile.js index ba5c33516b1..eb71adeb6a8 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -747,7 +747,7 @@ describe('res', function(){ }) describe('when cacheControl: false', function () { - it('shold not send cache-control', function (done) { + it('should not send cache-control', function (done) { var app = express() app.use(function (req, res) { From 99175c3ef63166d199bab8f402103522dec5f0ee Mon Sep 17 00:00:00 2001 From: Ghouse Mohamed Date: Sun, 27 Mar 2022 05:15:01 +0530 Subject: [PATCH 600/889] docs: fix typo in casing of HTTP closes #4872 --- Charter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Charter.md b/Charter.md index f9647cb734d..a906e52909a 100644 --- a/Charter.md +++ b/Charter.md @@ -9,7 +9,7 @@ also easily visible to outsiders. ## Section 1: Scope -Express is a http web server framework with a simple and expressive API +Express is a HTTP web server framework with a simple and expressive API which is highly aligned with Node.js core. We aim to be the best in class for writing performant, spec compliant, and powerful web servers in Node.js. As one of the oldest and most popular web frameworks in @@ -24,7 +24,7 @@ Express is made of many modules spread between three GitHub Orgs: libraries - [pillarjs](http://github.com/pillarjs/): Components which make up Express but can also be used for other web frameworks -- [jshttp](http://github.com/jshttp/): Low level http libraries +- [jshttp](http://github.com/jshttp/): Low level HTTP libraries ### 1.2: Out-of-Scope From ecaf67c9305f3bf75a9798e8a2e10b36955df42c Mon Sep 17 00:00:00 2001 From: Eslam Salem Date: Mon, 11 Apr 2022 10:56:45 +0200 Subject: [PATCH 601/889] docs: remove Node Security Project from security policy closes #4890 --- Security.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Security.md b/Security.md index 858dfffc5bc..cdcd7a6e0aa 100644 --- a/Security.md +++ b/Security.md @@ -27,8 +27,7 @@ endeavor to keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. Report security bugs in third-party modules to the person or team maintaining -the module. You can also report a vulnerability through the -[Node Security Project](https://nodesecurity.io/report). +the module. ## Disclosure Policy From b91c7ffb289af1753b9d1d84e16fbfcd34954124 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 11 Apr 2022 19:28:50 -0400 Subject: [PATCH 602/889] examples: use http-errors to create errors --- examples/params/index.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/examples/params/index.js b/examples/params/index.js index b153b93b988..b6fc483c8b7 100644 --- a/examples/params/index.js +++ b/examples/params/index.js @@ -4,6 +4,7 @@ * Module dependencies. */ +var createError = require('http-errors') var express = require('../../'); var app = module.exports = express(); @@ -17,14 +18,6 @@ var users = [ , { name: 'bandit' } ]; -// Create HTTP error - -function createError(status, message) { - var err = new Error(message); - err.status = status; - return err; -} - // Convert :to and :from to integers app.param(['to', 'from'], function(req, res, next, num, name){ From 8880ddad1c0f00612b53f5f686f55e7566b16562 Mon Sep 17 00:00:00 2001 From: Hashen <37979557+Hashen110@users.noreply.github.com> Date: Thu, 7 Apr 2022 21:34:47 +0530 Subject: [PATCH 603/889] examples: add missing html label associations closes #4884 --- examples/auth/views/login.ejs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/auth/views/login.ejs b/examples/auth/views/login.ejs index 8a20411a2ca..181c36caf7a 100644 --- a/examples/auth/views/login.ejs +++ b/examples/auth/views/login.ejs @@ -6,12 +6,12 @@ Try accessing /restricted, then authenticate with "tj" and "foobar".

        - - + +

        - - + +

        From 92c5ce59f51cce4b3598fd040117772fac42dce8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 11 Apr 2022 22:51:13 -0400 Subject: [PATCH 604/889] deps: cookie@0.5.0 --- History.md | 3 ++ package.json | 2 +- test/res.cookie.js | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 84efe9b4d8a..4f43ad92550 100644 --- a/History.md +++ b/History.md @@ -19,6 +19,9 @@ unreleased - deps: on-finished@2.4.1 - deps: qs@6.10.3 - deps: raw-body@2.5.1 + * deps: cookie@0.5.0 + - Add `priority` option + - Fix `expires` option to reject invalid dates * deps: depd@2.0.0 - Replace internal `eval` usage with `Function` constructor - Use instance methods on `process` to check for listeners diff --git a/package.json b/package.json index dfce12352ca..ede86798cf6 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "body-parser": "1.20.0", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.2", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", diff --git a/test/res.cookie.js b/test/res.cookie.js index e3a921301f4..93deb769887 100644 --- a/test/res.cookie.js +++ b/test/res.cookie.js @@ -67,6 +67,21 @@ describe('res', function(){ .expect(200, done) }) + describe('expires', function () { + it('should throw on invalid date', function (done) { + var app = express() + + app.use(function (req, res) { + res.cookie('name', 'tobi', { expires: new Date(NaN) }) + res.end() + }) + + request(app) + .get('/') + .expect(500, /option expires is invalid/, done) + }) + }) + describe('maxAge', function(){ it('should set relative expires', function(done){ var app = express(); @@ -155,6 +170,63 @@ describe('res', function(){ }) }) + describe('priority', function () { + it('should set low priority', function (done) { + var app = express() + + app.use(function (req, res) { + res.cookie('name', 'tobi', { priority: 'low' }) + res.end() + }) + + request(app) + .get('/') + .expect('Set-Cookie', /Priority=Low/) + .expect(200, done) + }) + + it('should set medium priority', function (done) { + var app = express() + + app.use(function (req, res) { + res.cookie('name', 'tobi', { priority: 'medium' }) + res.end() + }) + + request(app) + .get('/') + .expect('Set-Cookie', /Priority=Medium/) + .expect(200, done) + }) + + it('should set high priority', function (done) { + var app = express() + + app.use(function (req, res) { + res.cookie('name', 'tobi', { priority: 'high' }) + res.end() + }) + + request(app) + .get('/') + .expect('Set-Cookie', /Priority=High/) + .expect(200, done) + }) + + it('should throw with invalid priority', function (done) { + var app = express() + + app.use(function (req, res) { + res.cookie('name', 'tobi', { priority: 'foobar' }) + res.end() + }) + + request(app) + .get('/') + .expect(500, /option priority is invalid/, done) + }) + }) + describe('signed', function(){ it('should generate a signed JSON cookie', function(done){ var app = express(); From 708ac4cdf5cd0a658d62490a9f4d78d3e1ec6612 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 13 Apr 2022 23:29:25 -0400 Subject: [PATCH 605/889] Fix handling very large stacks of sync middleware closes #4891 --- History.md | 1 + lib/router/index.js | 8 ++++++++ lib/router/route.js | 9 +++++++++ test/Route.js | 22 ++++++++++++++++++++++ test/Router.js | 16 ++++++++++++++++ 5 files changed, 56 insertions(+) diff --git a/History.md b/History.md index 4f43ad92550..3f7851ba578 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ unreleased * Allow `options` without `filename` in `res.download` * Deprecate string and non-integer arguments to `res.status` * Fix behavior of `null`/`undefined` as `maxAge` in `res.cookie` + * Fix handling very large stacks of sync middleware * Ignore `Object.prototype` values in settings through `app.set`/`app.get` * Invoke `default` with same arguments as types in `res.format` * Support proper 205 responses using `res.send` diff --git a/lib/router/index.js b/lib/router/index.js index 791a600f86a..f4c8c0a79ef 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -142,6 +142,7 @@ proto.handle = function handle(req, res, out) { var protohost = getProtohost(req.url) || '' var removed = ''; var slashAdded = false; + var sync = 0 var paramcalled = {}; // store options for OPTIONS request @@ -203,6 +204,11 @@ proto.handle = function handle(req, res, out) { return; } + // max sync stack + if (++sync > 100) { + return setImmediate(next, err) + } + // get pathname of request var path = getPathname(req); @@ -321,6 +327,8 @@ proto.handle = function handle(req, res, out) { } else { layer.handle_request(req, res, next); } + + sync = 0 } }; diff --git a/lib/router/route.js b/lib/router/route.js index 178df0d5160..5adaa125e27 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -98,6 +98,8 @@ Route.prototype._options = function _options() { Route.prototype.dispatch = function dispatch(req, res, done) { var idx = 0; var stack = this.stack; + var sync = 0 + if (stack.length === 0) { return done(); } @@ -127,6 +129,11 @@ Route.prototype.dispatch = function dispatch(req, res, done) { return done(err); } + // max sync stack + if (++sync > 100) { + return setImmediate(next, err) + } + if (layer.method && layer.method !== method) { return next(err); } @@ -136,6 +143,8 @@ Route.prototype.dispatch = function dispatch(req, res, done) { } else { layer.handle_request(req, res, next); } + + sync = 0 } }; diff --git a/test/Route.js b/test/Route.js index 8e7ddbdbcc1..3bdc8d7df2f 100644 --- a/test/Route.js +++ b/test/Route.js @@ -13,6 +13,28 @@ describe('Route', function(){ route.dispatch(req, {}, done) }) + it('should not stack overflow with a large sync stack', function (done) { + this.timeout(5000) // long-running test + + var req = { method: 'GET', url: '/' } + var route = new Route('/foo') + + for (var i = 0; i < 6000; i++) { + route.all(function (req, res, next) { next() }) + } + + route.get(function (req, res, next) { + req.called = true + next() + }) + + route.dispatch(req, {}, function (err) { + if (err) return done(err) + assert.ok(req.called) + done() + }) + }) + describe('.all', function(){ it('should add handler', function(done){ var req = { method: 'GET', url: '/' }; diff --git a/test/Router.js b/test/Router.js index 907b9726361..8a0654bca3c 100644 --- a/test/Router.js +++ b/test/Router.js @@ -76,6 +76,22 @@ describe('Router', function(){ router.handle({ url: '/', method: 'GET' }, { end: done }); }); + it('should not stack overflow with a large sync stack', function (done) { + this.timeout(5000) // long-running test + + var router = new Router() + + for (var i = 0; i < 6000; i++) { + router.use(function (req, res, next) { next() }) + } + + router.use(function (req, res) { + res.end() + }) + + router.handle({ url: '/', method: 'GET' }, { end: done }) + }) + describe('.handle', function(){ it('should dispatch', function(done){ var router = new Router(); From fd8e45c344325a4a91c1b916f3617a3574018976 Mon Sep 17 00:00:00 2001 From: phoenix Date: Fri, 8 Apr 2022 10:31:27 +0200 Subject: [PATCH 606/889] tests: mark stack overflow as long running closes #4887 --- test/Router.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Router.js b/test/Router.js index 8a0654bca3c..bf5a31ffddb 100644 --- a/test/Router.js +++ b/test/Router.js @@ -62,6 +62,8 @@ describe('Router', function(){ }) it('should not stack overflow with many registered routes', function(done){ + this.timeout(5000) // long-running test + var handler = function(req, res){ res.end(new Error('wrong handler')) }; var router = new Router(); From 11a209e4b7e229bf5041e1ab76ba0ac4e0cad324 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 20 Apr 2022 22:02:37 -0400 Subject: [PATCH 607/889] build: support Node.js 17.x --- .github/workflows/ci.yml | 4 ++++ appveyor.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83a8edee87d..f4a5902ac95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,7 @@ jobs: - Node.js 14.x - Node.js 15.x - Node.js 16.x + - Node.js 17.x include: - name: Node.js 0.10 @@ -98,6 +99,9 @@ jobs: - name: Node.js 16.x node-version: "16.14" + - name: Node.js 17.x + node-version: "17.9" + steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index 93ea2c81616..f97addec1cb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,6 +18,7 @@ environment: - nodejs_version: "14.19" - nodejs_version: "15.14" - nodejs_version: "16.14" + - nodejs_version: "17.9" cache: - node_modules install: From 29ea1b2f74c5e76e79e329ef425e5fbbcd6a71c3 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Apr 2022 01:38:59 -0400 Subject: [PATCH 608/889] build: use 64-bit Node.js in AppVeyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f97addec1cb..faf31abf12f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,7 +25,7 @@ install: # Install Node.js - ps: >- try { Install-Product node $env:nodejs_version -ErrorAction Stop } - catch { Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) } + catch { Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) x64 } # Configure npm - ps: | npm config set loglevel error From 158a17031a2668269aedb31ea07b58d6b700272b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Apr 2022 02:09:08 -0400 Subject: [PATCH 609/889] build: support Node.js 18.x --- .github/workflows/ci.yml | 4 ++++ appveyor.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4a5902ac95..9d3663762c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,7 @@ jobs: - Node.js 15.x - Node.js 16.x - Node.js 17.x + - Node.js 18.x include: - name: Node.js 0.10 @@ -102,6 +103,9 @@ jobs: - name: Node.js 17.x node-version: "17.9" + - name: Node.js 18.x + node-version: "18.0" + steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index faf31abf12f..8804cfd398c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,6 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.14" - nodejs_version: "17.9" + - nodejs_version: "18.0" cache: - node_modules install: From 0b330ef57c0801313251c95a461d93f8d3afa7f7 Mon Sep 17 00:00:00 2001 From: Deniz Date: Mon, 4 Apr 2022 01:31:32 +0200 Subject: [PATCH 610/889] bench: print latency and vary connections closes #4880 --- benchmarks/Makefile | 20 ++++++++++++-------- benchmarks/run | 8 +++++--- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/benchmarks/Makefile b/benchmarks/Makefile index baf0d6fce92..ed1ddfc4f34 100644 --- a/benchmarks/Makefile +++ b/benchmarks/Makefile @@ -1,13 +1,17 @@ all: - @./run 1 middleware - @./run 5 middleware - @./run 10 middleware - @./run 15 middleware - @./run 20 middleware - @./run 30 middleware - @./run 50 middleware - @./run 100 middleware + @./run 1 middleware 50 + @./run 5 middleware 50 + @./run 10 middleware 50 + @./run 15 middleware 50 + @./run 20 middleware 50 + @./run 30 middleware 50 + @./run 50 middleware 50 + @./run 100 middleware 50 + @./run 10 middleware 100 + @./run 10 middleware 250 + @./run 10 middleware 500 + @./run 10 middleware 1000 @echo .PHONY: all diff --git a/benchmarks/run b/benchmarks/run index 93b5bc52ff2..ec8f55d5643 100755 --- a/benchmarks/run +++ b/benchmarks/run @@ -4,13 +4,15 @@ echo MW=$1 node $2 & pid=$! +echo " $3 connections" + sleep 2 wrk 'http://localhost:3333/?foo[bar]=baz' \ -d 3 \ - -c 50 \ + -c $3 \ -t 8 \ - | grep 'Requests/sec' \ - | awk '{ print " " $2 }' + | grep 'Requests/sec\|Latency' \ + | awk '{ print " " $2 }' kill $pid From 547fdd41dca9ae9c49956748cc0bd1f011310fb6 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Apr 2022 14:53:28 -0400 Subject: [PATCH 611/889] 4.18.0 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 3f7851ba578..32e75b391e4 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.18.0 / 2022-04-25 +=================== * Add "root" option to `res.download` * Allow `options` without `filename` in `res.download` diff --git a/package.json b/package.json index ede86798cf6..d07cdf82b98 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.17.3", + "version": "4.18.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From a38fae126a9d5681d075c1a5c44fd7357eae843b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Apr 2022 13:04:11 -0400 Subject: [PATCH 612/889] build: mocha@9.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d07cdf82b98..da94b92fd4d 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "hbs": "4.2.0", "marked": "0.7.0", "method-override": "3.0.0", - "mocha": "9.2.1", + "mocha": "9.2.2", "morgan": "1.10.0", "multiparty": "4.2.3", "nyc": "15.1.0", From 2df96e349f49bbcf51126c1f3b93b3b7fe8c16d2 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Apr 2022 13:04:38 -0400 Subject: [PATCH 613/889] build: supertest@6.2.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da94b92fd4d..0499571ed4a 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "multiparty": "4.2.3", "nyc": "15.1.0", "pbkdf2-password": "1.2.1", - "supertest": "6.2.2", + "supertest": "6.2.3", "vhost": "~3.0.2" }, "engines": { From e2482b7e36e39fd9875508a297c2db4a80a33635 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 28 Apr 2022 21:59:32 -0400 Subject: [PATCH 614/889] build: ejs@3.1.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0499571ed4a..f0781ddfd48 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "connect-redis": "3.4.2", "cookie-parser": "1.4.6", "cookie-session": "2.0.0", - "ejs": "3.1.6", + "ejs": "3.1.7", "eslint": "7.32.0", "express-session": "1.17.2", "hbs": "4.2.0", From 75e0c7a2c91665f44d053d83be15f8ecd0177f41 Mon Sep 17 00:00:00 2001 From: Hashen <37979557+Hashen110@users.noreply.github.com> Date: Tue, 26 Apr 2022 23:23:14 +0530 Subject: [PATCH 615/889] bench: remove unused parameter closes #4898 --- benchmarks/middleware.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/middleware.js b/benchmarks/middleware.js index df4df2c5ac5..fed97ba8ce4 100644 --- a/benchmarks/middleware.js +++ b/benchmarks/middleware.js @@ -13,7 +13,7 @@ while (n--) { }); } -app.use(function(req, res, next){ +app.use(function(req, res){ res.send('Hello World') }); From 631ada0c645dc84c6df8788f5a7eb2b8100acea5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 29 Apr 2022 13:34:47 -0400 Subject: [PATCH 616/889] Fix hanging on large stack of sync routes fixes #4899 --- History.md | 5 +++++ lib/router/index.js | 14 ++++++-------- test/Router.js | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/History.md b/History.md index 32e75b391e4..b052c577f78 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Fix hanging on large stack of sync routes + 4.18.0 / 2022-04-25 =================== diff --git a/lib/router/index.js b/lib/router/index.js index f4c8c0a79ef..5174c34f455 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -279,14 +279,14 @@ proto.handle = function handle(req, res, out) { // this should be done for the layer self.process_params(layer, paramcalled, req, res, function (err) { if (err) { - return next(layerError || err); + next(layerError || err) + } else if (route) { + layer.handle_request(req, res, next) + } else { + trim_prefix(layer, layerError, layerPath, path) } - if (route) { - return layer.handle_request(req, res, next); - } - - trim_prefix(layer, layerError, layerPath, path); + sync = 0 }); } @@ -327,8 +327,6 @@ proto.handle = function handle(req, res, out) { } else { layer.handle_request(req, res, next); } - - sync = 0 } }; diff --git a/test/Router.js b/test/Router.js index bf5a31ffddb..fcfee80625c 100644 --- a/test/Router.js +++ b/test/Router.js @@ -78,7 +78,23 @@ describe('Router', function(){ router.handle({ url: '/', method: 'GET' }, { end: done }); }); - it('should not stack overflow with a large sync stack', function (done) { + it('should not stack overflow with a large sync route stack', function (done) { + this.timeout(5000) // long-running test + + var router = new Router() + + for (var i = 0; i < 6000; i++) { + router.get('/foo', function (req, res, next) { next() }) + } + + router.get('/foo', function (req, res) { + res.end() + }) + + router.handle({ url: '/foo', method: 'GET' }, { end: done }) + }) + + it('should not stack overflow with a large sync middleware stack', function (done) { this.timeout(5000) // long-running test var router = new Router() From b02a95c6937e3b7e0b85a51c7e1a7366e1699dce Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 29 Apr 2022 14:52:20 -0400 Subject: [PATCH 617/889] build: Node.js@16.15 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d3663762c6..a4b40dc982f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,7 +98,7 @@ jobs: node-version: "15.14" - name: Node.js 16.x - node-version: "16.14" + node-version: "16.15" - name: Node.js 17.x node-version: "17.9" diff --git a/appveyor.yml b/appveyor.yml index 8804cfd398c..80802e180e6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ environment: - nodejs_version: "13.14" - nodejs_version: "14.19" - nodejs_version: "15.14" - - nodejs_version: "16.14" + - nodejs_version: "16.15" - nodejs_version: "17.9" - nodejs_version: "18.0" cache: From d854c43ea177d1faeea56189249fff8c24a764bd Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 29 Apr 2022 15:32:26 -0400 Subject: [PATCH 618/889] 4.18.1 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index b052c577f78..4c12ec97355 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.18.1 / 2022-04-29 +=================== * Fix hanging on large stack of sync routes diff --git a/package.json b/package.json index f0781ddfd48..f5872a53336 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.18.0", + "version": "4.18.1", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From a2dfc56a4982e0a33c67d6d0c22e087e95bff79e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 20 May 2022 09:33:19 -0400 Subject: [PATCH 619/889] build: mocha@10.0.0 --- .github/workflows/ci.yml | 2 ++ appveyor.yml | 3 +++ package.json | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4b40dc982f..6df74b37f8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,9 +87,11 @@ jobs: - name: Node.js 12.x node-version: "12.22" + npm-i: mocha@9.2.2 - name: Node.js 13.x node-version: "13.14" + npm-i: mocha@9.2.2 - name: Node.js 14.x node-version: "14.19" diff --git a/appveyor.yml b/appveyor.yml index 80802e180e6..e9b28e7d0fa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -47,6 +47,7 @@ install: # - use 6.x for Node.js < 8 # - use 7.x for Node.js < 10 # - use 8.x for Node.js < 12 + # - use 9.x for Node.js < 14 if ([int]$env:nodejs_version.split(".")[0] -lt 4) { npm install --silent --save-dev mocha@3.5.3 } elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) { @@ -57,6 +58,8 @@ install: npm install --silent --save-dev mocha@7.2.0 } elseif ([int]$env:nodejs_version.split(".")[0] -lt 12) { npm install --silent --save-dev mocha@8.4.0 + } elseif ([int]$env:nodejs_version.split(".")[0] -lt 14) { + npm install --silent --save-dev mocha@9.2.2 } - ps: | # nyc for test coverage diff --git a/package.json b/package.json index f5872a53336..6880db25241 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "hbs": "4.2.0", "marked": "0.7.0", "method-override": "3.0.0", - "mocha": "9.2.2", + "mocha": "10.0.0", "morgan": "1.10.0", "multiparty": "4.2.3", "nyc": "15.1.0", From 745a63f8256828a061e1b2f0a5f8e52eb9538da1 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 20 May 2022 09:34:47 -0400 Subject: [PATCH 620/889] build: ejs@3.1.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6880db25241..3430f770972 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "connect-redis": "3.4.2", "cookie-parser": "1.4.6", "cookie-session": "2.0.0", - "ejs": "3.1.7", + "ejs": "3.1.8", "eslint": "7.32.0", "express-session": "1.17.2", "hbs": "4.2.0", From ab2c70b954ac2ceb3aaf466b0f59089999952dd0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 20 May 2022 09:35:20 -0400 Subject: [PATCH 621/889] build: Node.js@18.1 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6df74b37f8f..b7ad4578297 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: node-version: "17.9" - name: Node.js 18.x - node-version: "18.0" + node-version: "18.1" steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index e9b28e7d0fa..b78a0b1550d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.15" - nodejs_version: "17.9" - - nodejs_version: "18.0" + - nodejs_version: "18.1" cache: - node_modules install: From 7ec5dd2b3c5e7379f68086dae72859f5573c8b9b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 20 May 2022 09:37:20 -0400 Subject: [PATCH 622/889] Fix regression routing a large stack in a single route fixes #4913 --- History.md | 5 +++++ lib/router/route.js | 16 ++++++++-------- test/Route.js | 11 ++++++++++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/History.md b/History.md index 4c12ec97355..cbf4b5249fa 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Fix regression routing a large stack in a single route + 4.18.1 / 2022-04-29 =================== diff --git a/lib/router/route.js b/lib/router/route.js index 5adaa125e27..cc643ac8bdb 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -124,21 +124,21 @@ Route.prototype.dispatch = function dispatch(req, res, done) { return done(err) } - var layer = stack[idx++]; - if (!layer) { - return done(err); - } - // max sync stack if (++sync > 100) { return setImmediate(next, err) } - if (layer.method && layer.method !== method) { - return next(err); + var layer = stack[idx++] + + // end of layers + if (!layer) { + return done(err) } - if (err) { + if (layer.method && layer.method !== method) { + next(err) + } else if (err) { layer.handle_error(err, req, res, next); } else { layer.handle_request(req, res, next); diff --git a/test/Route.js b/test/Route.js index 3bdc8d7df2f..64dbad60ce9 100644 --- a/test/Route.js +++ b/test/Route.js @@ -19,8 +19,16 @@ describe('Route', function(){ var req = { method: 'GET', url: '/' } var route = new Route('/foo') + route.get(function (req, res, next) { + req.counter = 0 + next() + }) + for (var i = 0; i < 6000; i++) { - route.all(function (req, res, next) { next() }) + route.all(function (req, res, next) { + req.counter++ + next() + }) } route.get(function (req, res, next) { @@ -31,6 +39,7 @@ describe('Route', function(){ route.dispatch(req, {}, function (err) { if (err) return done(err) assert.ok(req.called) + assert.strictEqual(req.counter, 6000) done() }) }) From 97f0a518d8d697e310abf293a71383cf9d04d749 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 20 May 2022 11:54:35 -0400 Subject: [PATCH 623/889] tests: verify all handlers called in stack tests --- test/Router.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/Router.js b/test/Router.js index fcfee80625c..0d0502ab40d 100644 --- a/test/Router.js +++ b/test/Router.js @@ -83,11 +83,20 @@ describe('Router', function(){ var router = new Router() + router.get('/foo', function (req, res, next) { + req.counter = 0 + next() + }) + for (var i = 0; i < 6000; i++) { - router.get('/foo', function (req, res, next) { next() }) + router.get('/foo', function (req, res, next) { + req.counter++ + next() + }) } router.get('/foo', function (req, res) { + assert.strictEqual(req.counter, 6000) res.end() }) @@ -99,11 +108,20 @@ describe('Router', function(){ var router = new Router() + router.use(function (req, res, next) { + req.counter = 0 + next() + }) + for (var i = 0; i < 6000; i++) { - router.use(function (req, res, next) { next() }) + router.use(function (req, res, next) { + req.counter++ + next() + }) } router.use(function (req, res) { + assert.strictEqual(req.counter, 6000) res.end() }) From 2c47827053233e707536019a15499ccf5496dc9d Mon Sep 17 00:00:00 2001 From: Alexandru Dragomir Date: Fri, 20 May 2022 18:49:44 +0300 Subject: [PATCH 624/889] examples: remove unused function arguments in params closes #4914 --- examples/params/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/params/index.js b/examples/params/index.js index b6fc483c8b7..f3cd8457eb5 100644 --- a/examples/params/index.js +++ b/examples/params/index.js @@ -51,7 +51,7 @@ app.get('/', function(req, res){ * GET :user. */ -app.get('/user/:user', function(req, res, next){ +app.get('/user/:user', function (req, res) { res.send('user ' + req.user.name); }); @@ -59,7 +59,7 @@ app.get('/user/:user', function(req, res, next){ * GET users :from - :to. */ -app.get('/users/:from-:to', function(req, res, next){ +app.get('/users/:from-:to', function (req, res) { var from = req.params.from; var to = req.params.to; var names = users.map(function(user){ return user.name; }); From 8d98e86d7fe4e4dd50e42e73301b0bb7b7132758 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Aug 2022 23:00:36 -0400 Subject: [PATCH 625/889] build: Node.js@16.17 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b7ad4578297..5be813b2fed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,7 +100,7 @@ jobs: node-version: "15.14" - name: Node.js 16.x - node-version: "16.15" + node-version: "16.17" - name: Node.js 17.x node-version: "17.9" diff --git a/appveyor.yml b/appveyor.yml index b78a0b1550d..ef183ed7d75 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ environment: - nodejs_version: "13.14" - nodejs_version: "14.19" - nodejs_version: "15.14" - - nodejs_version: "16.15" + - nodejs_version: "16.17" - nodejs_version: "17.9" - nodejs_version: "18.1" cache: From 97131bcda8bd3cdbe53ef14fbd08dcc23a53e758 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Aug 2022 23:01:25 -0400 Subject: [PATCH 626/889] build: Node.js@18.7 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5be813b2fed..1ad8d117668 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: node-version: "17.9" - name: Node.js 18.x - node-version: "18.1" + node-version: "18.7" steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index ef183ed7d75..071f0de0924 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.17" - nodejs_version: "17.9" - - nodejs_version: "18.1" + - nodejs_version: "18.7" cache: - node_modules install: From ecd7572f1e920b7a512452b8d9806ae617a99c54 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Aug 2022 23:41:10 -0400 Subject: [PATCH 627/889] build: Node.js@14.20 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ad8d117668..5d2cef5a4d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: npm-i: mocha@9.2.2 - name: Node.js 14.x - node-version: "14.19" + node-version: "14.20" - name: Node.js 15.x node-version: "15.14" diff --git a/appveyor.yml b/appveyor.yml index 071f0de0924..7bf0141b380 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,7 +15,7 @@ environment: - nodejs_version: "11.15" - nodejs_version: "12.22" - nodejs_version: "13.14" - - nodejs_version: "14.19" + - nodejs_version: "14.20" - nodejs_version: "15.14" - nodejs_version: "16.17" - nodejs_version: "17.9" From 644f6464b9f61cbafa8f880636b1aa5237d95bad Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 18 Aug 2022 23:42:39 -0400 Subject: [PATCH 628/889] build: supertest@6.2.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3430f770972..cbfa910ff09 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "multiparty": "4.2.3", "nyc": "15.1.0", "pbkdf2-password": "1.2.1", - "supertest": "6.2.3", + "supertest": "6.2.4", "vhost": "~3.0.2" }, "engines": { From 33e8dc303af9277f8a7e4f46abfdcb5e72f6797b Mon Sep 17 00:00:00 2001 From: REALSTEVEIG <101066723+REALSTEVEIG@users.noreply.github.com> Date: Sat, 11 Jun 2022 21:26:10 +0100 Subject: [PATCH 629/889] docs: use Node.js name style closes #4926 --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 720bf389224..9b8bc34a0ce 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ [![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/) - Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). + Fast, unopinionated, minimalist web framework for [Node.js](http://nodejs.org). [![NPM Version][npm-version-image]][npm-url] [![NPM Install Size][npm-install-size-image]][npm-install-size-url] From 340be0f79afb9b3176afb76235aa7f92acbd5050 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 5 Oct 2022 22:40:51 -0400 Subject: [PATCH 630/889] build: eslint@8.24.0 --- .github/workflows/ci.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d2cef5a4d1..6125da491ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -133,8 +133,8 @@ jobs: shell: bash run: | # eslint for linting - # - remove on Node.js < 10 - if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then + # - remove on Node.js < 12 + if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ grep -E '^eslint(-|$)' | \ sort -r | \ diff --git a/package.json b/package.json index cbfa910ff09..defab0eec0d 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "cookie-parser": "1.4.6", "cookie-session": "2.0.0", "ejs": "3.1.8", - "eslint": "7.32.0", + "eslint": "8.24.0", "express-session": "1.17.2", "hbs": "4.2.0", "marked": "0.7.0", From 689d175b8b39d8860b81d723233fb83d15201827 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Oct 2022 10:26:18 -0400 Subject: [PATCH 631/889] deps: body-parser@1.20.1 --- History.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index cbf4b5249fa..389c837b089 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,9 @@ unreleased ========== * Fix regression routing a large stack in a single route + * deps: body-parser@1.20.1 + - deps: qs@6.11.0 + - perf: remove unnecessary object clone 4.18.1 / 2022-04-29 =================== diff --git a/package.json b/package.json index defab0eec0d..2c2d40a73f7 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.0", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", From 24b3dc551670ac4fb0cd5a2bd5ef643c9525e60f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Oct 2022 10:27:01 -0400 Subject: [PATCH 632/889] deps: qs@6.11.0 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 389c837b089..a05baee6179 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ unreleased * deps: body-parser@1.20.1 - deps: qs@6.11.0 - perf: remove unnecessary object clone + * deps: qs@6.11.0 4.18.1 / 2022-04-29 =================== diff --git a/package.json b/package.json index 2c2d40a73f7..a7815d9fbee 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.10.3", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", From f56ce73186e885a938bfdb3d3d1005a58e6ae12b Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Oct 2022 10:28:13 -0400 Subject: [PATCH 633/889] build: supertest@6.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a7815d9fbee..6a11013c72c 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "multiparty": "4.2.3", "nyc": "15.1.0", "pbkdf2-password": "1.2.1", - "supertest": "6.2.4", + "supertest": "6.3.0", "vhost": "~3.0.2" }, "engines": { From bb7907b932afe3a19236a642f6054b6c8f7349a0 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 7 Oct 2022 17:48:59 -0400 Subject: [PATCH 634/889] build: Node.js@18.10 closes #5014 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- test/res.sendFile.js | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6125da491ad..cd93ab223d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: node-version: "17.9" - name: Node.js 18.x - node-version: "18.7" + node-version: "18.10" steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index 7bf0141b380..1fca21801e8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.17" - nodejs_version: "17.9" - - nodejs_version: "18.7" + - nodejs_version: "18.10" cache: - node_modules install: diff --git a/test/res.sendFile.js b/test/res.sendFile.js index eb71adeb6a8..4db0a3b6a4e 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -1050,12 +1050,13 @@ describe('res', function(){ app.use(function(req, res){ res.sendfile('test/fixtures/user.html', function(err){ - assert(!res.headersSent); - assert.strictEqual(req.socket.listeners('error').length, 1) // node's original handler + assert.ok(err) + assert.ok(!res.headersSent) + assert.strictEqual(err.message, 'broken!') done(); }); - req.socket.emit('error', new Error('broken!')); + req.socket.destroy(new Error('broken!')) }); request(app) From 61f40491222dbede653b9938e6a4676f187aab44 Mon Sep 17 00:00:00 2001 From: Abhinav Das Date: Sat, 8 Oct 2022 00:32:42 +0530 Subject: [PATCH 635/889] docs: replace Freenode with Libera Chat closes #5013 --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 9b8bc34a0ce..0936816bedb 100644 --- a/Readme.md +++ b/Readme.md @@ -51,7 +51,7 @@ for more information. ## Docs & Community * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)] - * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC + * [#express](https://web.libera.chat/#express) on [Libera Chat](https://libera.chat) IRC * [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules * Visit the [Wiki](https://github.com/expressjs/express/wiki) * [Google Group](https://groups.google.com/group/express-js) for discussion From 8368dc178af16b91b576c4c1d135f701a0007e5d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 8 Oct 2022 16:11:42 -0400 Subject: [PATCH 636/889] 4.18.2 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index a05baee6179..e49870fed0b 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -unreleased -========== +4.18.2 / 2022-10-08 +=================== * Fix regression routing a large stack in a single route * deps: body-parser@1.20.1 diff --git a/package.json b/package.json index 6a11013c72c..0996637deaa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.18.1", + "version": "4.18.2", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 06b2b1416d07698b8a6eed467f90d0b3ceb380c8 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 31 Oct 2022 16:39:42 -0400 Subject: [PATCH 637/889] docs: update git clone to https protocol closes #5032 --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 0936816bedb..d0f3cf56e6d 100644 --- a/Readme.md +++ b/Readme.md @@ -104,7 +104,7 @@ $ npm start To view the examples, clone the Express repo and install the dependencies: ```console -$ git clone git://github.com/expressjs/express.git --depth 1 +$ git clone https://github.com/expressjs/express.git --depth 1 $ cd express $ npm install ``` From 29e117e676901a804031896f95f0eba317b05099 Mon Sep 17 00:00:00 2001 From: Arnaud Benhamdine Date: Tue, 1 Nov 2022 22:34:11 +0100 Subject: [PATCH 638/889] build: Node.js@16.18 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd93ab223d2..33da666df3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,7 +100,7 @@ jobs: node-version: "15.14" - name: Node.js 16.x - node-version: "16.17" + node-version: "16.18" - name: Node.js 17.x node-version: "17.9" diff --git a/appveyor.yml b/appveyor.yml index 1fca21801e8..5c55ace4a05 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ environment: - nodejs_version: "13.14" - nodejs_version: "14.20" - nodejs_version: "15.14" - - nodejs_version: "16.17" + - nodejs_version: "16.18" - nodejs_version: "17.9" - nodejs_version: "18.10" cache: From 723b67766fb864424a59ebe46b6516bb484f6a23 Mon Sep 17 00:00:00 2001 From: Arnaud Benhamdine Date: Tue, 1 Nov 2022 22:34:11 +0100 Subject: [PATCH 639/889] build: Node.js@18.12 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33da666df3f..868525a4b1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: node-version: "17.9" - name: Node.js 18.x - node-version: "18.10" + node-version: "18.12" steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index 5c55ace4a05..02a5c1169d5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.18" - nodejs_version: "17.9" - - nodejs_version: "18.10" + - nodejs_version: "18.12" cache: - node_modules install: From 442fd467992992558806da8da07e945838712587 Mon Sep 17 00:00:00 2001 From: Abdul Rauf Date: Wed, 19 Oct 2022 18:05:06 +0500 Subject: [PATCH 640/889] build: actions/checkout@v3 closes #5027 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 868525a4b1b..b6a2879603d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,7 +109,7 @@ jobs: node-version: "18.12" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install Node.js ${{ matrix.node-version }} shell: bash -eo pipefail -l {0} From c6ee8d6e7f11c3ac6bdda8e1bd4c1e38445f2d22 Mon Sep 17 00:00:00 2001 From: Rakesh Bisht Date: Fri, 10 Feb 2023 11:50:16 +0530 Subject: [PATCH 641/889] lint: remove unused function arguments in tests closes #5124 --- test/Router.js | 2 +- test/app.param.js | 6 +++--- test/app.router.js | 22 +++++++++++----------- test/res.format.js | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/test/Router.js b/test/Router.js index 0d0502ab40d..620c60278a1 100644 --- a/test/Router.js +++ b/test/Router.js @@ -201,7 +201,7 @@ describe('Router', function(){ it('should handle throwing inside routes with params', function(done) { var router = new Router(); - router.get('/foo/:id', function(req, res, next){ + router.get('/foo/:id', function () { throw new Error('foo'); }); diff --git a/test/app.param.js b/test/app.param.js index 8893851f9d5..b4ccc8a2d12 100644 --- a/test/app.param.js +++ b/test/app.param.js @@ -166,7 +166,7 @@ describe('app', function(){ app.get('/:user', function(req, res, next) { next('route'); }); - app.get('/:user', function(req, res, next) { + app.get('/:user', function (req, res) { res.send(req.params.user); }); @@ -187,11 +187,11 @@ describe('app', function(){ next(new Error('invalid invocation')) }); - app.post('/:user', function(req, res, next) { + app.post('/:user', function (req, res) { res.send(req.params.user); }); - app.get('/:thing', function(req, res, next) { + app.get('/:thing', function (req, res) { res.send(req.thing); }); diff --git a/test/app.router.js b/test/app.router.js index 3069a22c772..4fde03105c6 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -90,7 +90,7 @@ describe('app.router', function(){ it('should decode correct params', function(done){ var app = express(); - app.get('/:name', function(req, res, next){ + app.get('/:name', function (req, res) { res.send(req.params.name); }); @@ -102,7 +102,7 @@ describe('app.router', function(){ it('should not accept params in malformed paths', function(done) { var app = express(); - app.get('/:name', function(req, res, next){ + app.get('/:name', function (req, res) { res.send(req.params.name); }); @@ -114,7 +114,7 @@ describe('app.router', function(){ it('should not decode spaces', function(done) { var app = express(); - app.get('/:name', function(req, res, next){ + app.get('/:name', function (req, res) { res.send(req.params.name); }); @@ -126,7 +126,7 @@ describe('app.router', function(){ it('should work with unicode', function(done) { var app = express(); - app.get('/:name', function(req, res, next){ + app.get('/:name', function (req, res) { res.send(req.params.name); }); @@ -910,7 +910,7 @@ describe('app.router', function(){ next(); }); - app.get('/bar', function(req, res){ + app.get('/bar', function () { assert(0); }); @@ -919,7 +919,7 @@ describe('app.router', function(){ next(); }); - app.get('/foo', function(req, res, next){ + app.get('/foo', function (req, res) { calls.push('/foo 2'); res.json(calls) }); @@ -939,7 +939,7 @@ describe('app.router', function(){ next('route') } - app.get('/foo', fn, function(req, res, next){ + app.get('/foo', fn, function (req, res) { res.end('failure') }); @@ -964,11 +964,11 @@ describe('app.router', function(){ next('router') } - router.get('/foo', fn, function (req, res, next) { + router.get('/foo', fn, function (req, res) { res.end('failure') }) - router.get('/foo', function (req, res, next) { + router.get('/foo', function (req, res) { res.end('failure') }) @@ -995,7 +995,7 @@ describe('app.router', function(){ next(); }); - app.get('/bar', function(req, res){ + app.get('/bar', function () { assert(0); }); @@ -1004,7 +1004,7 @@ describe('app.router', function(){ next(new Error('fail')); }); - app.get('/foo', function(req, res, next){ + app.get('/foo', function () { assert(0); }); diff --git a/test/res.format.js b/test/res.format.js index 45243d17a1b..cba6fe136b1 100644 --- a/test/res.format.js +++ b/test/res.format.js @@ -61,7 +61,7 @@ app3.use(function(req, res, next){ var app4 = express(); -app4.get('/', function(req, res, next){ +app4.get('/', function (req, res) { res.format({ text: function(){ res.send('hey') }, html: function(){ res.send('

        hey

        ') }, @@ -155,7 +155,7 @@ describe('res', function(){ var app = express(); var router = express.Router(); - router.get('/', function(req, res, next){ + router.get('/', function (req, res) { res.format({ text: function(){ res.send('hey') }, html: function(){ res.send('

        hey

        ') }, From a1efd9d6cf968a9e863f3fdd3fef63d06ff039c4 Mon Sep 17 00:00:00 2001 From: Rakesh Bisht Date: Wed, 8 Feb 2023 16:13:20 +0530 Subject: [PATCH 642/889] lint: remove unused parameter from internal function coses #5119 --- lib/utils.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 799a6a2b4ee..ab22f61e966 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -117,17 +117,15 @@ exports.contentDisposition = deprecate.function(contentDisposition, /** * Parse accept params `str` returning an * object with `.value`, `.quality` and `.params`. - * also includes `.originalIndex` for stable sorting * * @param {String} str - * @param {Number} index * @return {Object} * @api private */ -function acceptParams(str, index) { +function acceptParams (str) { var parts = str.split(/ *; */); - var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index }; + var ret = { value: parts[0], quality: 1, params: {} } for (var i = 1; i < parts.length; ++i) { var pms = parts[i].split(/ *= */); From 6b4c4f5426fb5de23fb7174fd6e3bf53048e06ca Mon Sep 17 00:00:00 2001 From: Rakesh Bisht Date: Wed, 8 Feb 2023 15:56:13 +0530 Subject: [PATCH 643/889] docs: fix typos in JSDoc comments closes #5117 --- examples/markdown/index.js | 2 +- lib/router/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/markdown/index.js b/examples/markdown/index.js index 74ac05e77f3..23d645e66b2 100644 --- a/examples/markdown/index.js +++ b/examples/markdown/index.js @@ -26,7 +26,7 @@ app.engine('md', function(path, options, fn){ app.set('views', path.join(__dirname, 'views')); -// make it the default so we dont need .md +// make it the default, so we don't need .md app.set('view engine', 'md'); app.get('/', function(req, res){ diff --git a/lib/router/index.js b/lib/router/index.js index 5174c34f455..abb3a6f589e 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -36,7 +36,7 @@ var toString = Object.prototype.toString; * Initialize a new `Router` with the given `options`. * * @param {Object} [options] - * @return {Router} which is an callable function + * @return {Router} which is a callable function * @public */ From 3c1d605da76a6c25dbe423a42d58871803c3e328 Mon Sep 17 00:00:00 2001 From: Rakesh Bisht Date: Fri, 3 Feb 2023 20:34:39 +0530 Subject: [PATCH 644/889] lint: remove unused parameters in examples closes #5113 --- examples/error/index.js | 2 +- examples/view-locals/index.js | 4 ++-- examples/web-service/index.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/error/index.js b/examples/error/index.js index d922de06cc4..d733a81172d 100644 --- a/examples/error/index.js +++ b/examples/error/index.js @@ -26,7 +26,7 @@ function error(err, req, res, next) { res.send('Internal Server Error'); } -app.get('/', function(req, res){ +app.get('/', function () { // Caught and passed down to the errorHandler middleware throw new Error('something broke!'); }); diff --git a/examples/view-locals/index.js b/examples/view-locals/index.js index bf52d2a85ad..a2af24f3553 100644 --- a/examples/view-locals/index.js +++ b/examples/view-locals/index.js @@ -61,7 +61,7 @@ function users(req, res, next) { }) } -app.get('/middleware', count, users, function(req, res, next){ +app.get('/middleware', count, users, function (req, res) { res.render('index', { title: 'Users', count: req.count, @@ -99,7 +99,7 @@ function users2(req, res, next) { }) } -app.get('/middleware-locals', count2, users2, function(req, res, next){ +app.get('/middleware-locals', count2, users2, function (req, res) { // you can see now how we have much less // to pass to res.render(). If we have // several routes related to users this diff --git a/examples/web-service/index.js b/examples/web-service/index.js index a2cd2cb7f90..d1a90362153 100644 --- a/examples/web-service/index.js +++ b/examples/web-service/index.js @@ -72,12 +72,12 @@ var userRepos = { // and simply expose the data // example: http://localhost:3000/api/users/?api-key=foo -app.get('/api/users', function(req, res, next){ +app.get('/api/users', function (req, res) { res.send(users); }); // example: http://localhost:3000/api/repos/?api-key=foo -app.get('/api/repos', function(req, res, next){ +app.get('/api/repos', function (req, res) { res.send(repos); }); From f05b5d0e9c43625e5677b427c33b2f950eb5bea8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Feb 2023 11:59:40 -0500 Subject: [PATCH 645/889] build: Node.js@16.19 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6a2879603d..332ce4394ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,7 +100,7 @@ jobs: node-version: "15.14" - name: Node.js 16.x - node-version: "16.18" + node-version: "16.19" - name: Node.js 17.x node-version: "17.9" diff --git a/appveyor.yml b/appveyor.yml index 02a5c1169d5..4c8722ed9f0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ environment: - nodejs_version: "13.14" - nodejs_version: "14.20" - nodejs_version: "15.14" - - nodejs_version: "16.18" + - nodejs_version: "16.19" - nodejs_version: "17.9" - nodejs_version: "18.12" cache: From 546969d1989d00fda460ccb23fabb943650dac51 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Feb 2023 12:07:48 -0500 Subject: [PATCH 646/889] build: Node.js@18.14 --- .github/workflows/ci.yml | 8 ++++++-- appveyor.yml | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 332ce4394ca..64538c290c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: node-version: "17.9" - name: Node.js 18.x - node-version: "18.12" + node-version: "18.14" steps: - uses: actions/checkout@v3 @@ -120,7 +120,11 @@ jobs: - name: Configure npm run: | npm config set loglevel error - npm config set shrinkwrap false + if [[ "$(npm config get package-lock)" == "true" ]]; then + npm config set package-lock false + else + npm config set shrinkwrap false + fi - name: Install npm module(s) ${{ matrix.npm-i }} run: npm install --save-dev ${{ matrix.npm-i }} diff --git a/appveyor.yml b/appveyor.yml index 4c8722ed9f0..47941052bfb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.19" - nodejs_version: "17.9" - - nodejs_version: "18.12" + - nodejs_version: "18.14" cache: - node_modules install: @@ -30,7 +30,11 @@ install: # Configure npm - ps: | npm config set loglevel error - npm config set shrinkwrap false + if ((npm config get package-lock) -eq "true") { + npm config set package-lock false + } else { + npm config set shrinkwrap false + } # Remove all non-test dependencies - ps: | # Remove example dependencies From b9f7a97fe164d2a64279105abe375c69eaab9ebb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 22 Feb 2023 18:10:59 -0500 Subject: [PATCH 647/889] build: use $GITHUB_OUTPUT for environment list --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64538c290c3..a4bf538948f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -155,7 +155,7 @@ jobs: echo "node@$(node -v)" echo "npm@$(npm -v)" npm -s ls ||: - (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print "::set-output name=" $2 "::" $3 }' + (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT" - name: Run tests shell: bash From 506fbd63befe810783dba49d11159c7ad46c239a Mon Sep 17 00:00:00 2001 From: Rakesh Bisht Date: Wed, 22 Feb 2023 18:30:50 +0530 Subject: [PATCH 648/889] docs: add missing JSDoc param for parseExtendedQueryString closes #5130 --- lib/utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utils.js b/lib/utils.js index ab22f61e966..56e12b9b541 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -280,6 +280,7 @@ function createETagGenerator (options) { /** * Parse an extended query string with qs. * + * @param {String} str * @return {Object} * @private */ From 1e42a98db6708e5a3609d0f7c09bcc176b481ea7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 23 Feb 2023 00:24:20 -0500 Subject: [PATCH 649/889] deps: body-parser@1.20.2 --- History.md | 8 ++++++++ package.json | 2 +- test/express.json.js | 8 ++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index e49870fed0b..7b0cc4abf78 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +unreleased +========== + + * deps: body-parser@1.20.2 + - Fix strict json error message on Node.js 19+ + - deps: content-type@~1.0.5 + - deps: raw-body@2.5.2 + 4.18.2 / 2022-10-08 =================== diff --git a/package.json b/package.json index 0996637deaa..adf479dfce6 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", diff --git a/test/express.json.js b/test/express.json.js index a8cfebc41e2..f6f536b15e5 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -262,7 +262,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send('true') - .expect(400, '[entity.parse.failed] ' + parseError('#rue').replace('#', 't'), done) + .expect(400, '[entity.parse.failed] ' + parseError('#rue').replace(/#/g, 't'), done) }) }) @@ -290,7 +290,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send('true') - .expect(400, '[entity.parse.failed] ' + parseError('#rue').replace('#', 't'), done) + .expect(400, '[entity.parse.failed] ' + parseError('#rue').replace(/#/g, 't'), done) }) it('should not parse primitives with leading whitespaces', function (done) { @@ -298,7 +298,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send(' true') - .expect(400, '[entity.parse.failed] ' + parseError(' #rue').replace('#', 't'), done) + .expect(400, '[entity.parse.failed] ' + parseError(' #rue').replace(/#/g, 't'), done) }) it('should allow leading whitespaces in JSON', function (done) { @@ -316,7 +316,7 @@ describe('express.json()', function () { .set('X-Error-Property', 'stack') .send('true') .expect(400) - .expect(shouldContainInBody(parseError('#rue').replace('#', 't'))) + .expect(shouldContainInBody(parseError('#rue').replace(/#/g, 't'))) .end(done) }) }) From 60b7c672c19ba6b96cc7e5383eee00f8bf99a45a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 23 Feb 2023 00:27:06 -0500 Subject: [PATCH 650/889] build: mocha@10.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index adf479dfce6..c3641a02c82 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "hbs": "4.2.0", "marked": "0.7.0", "method-override": "3.0.0", - "mocha": "10.0.0", + "mocha": "10.2.0", "morgan": "1.10.0", "multiparty": "4.2.3", "nyc": "15.1.0", From 8a76f39d9844f36797cd794fb74b47c635798ae5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 23 Feb 2023 00:28:41 -0500 Subject: [PATCH 651/889] build: eslint@8.34.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3641a02c82..e4ed037cfa7 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "cookie-parser": "1.4.6", "cookie-session": "2.0.0", "ejs": "3.1.8", - "eslint": "8.24.0", + "eslint": "8.34.0", "express-session": "1.17.2", "hbs": "4.2.0", "marked": "0.7.0", From 5ad95419bac1cb5bcc1f09fd1872f2b2af4aed1a Mon Sep 17 00:00:00 2001 From: Rakesh Bisht Date: Thu, 23 Feb 2023 11:36:40 +0530 Subject: [PATCH 652/889] docs: fix typos in history closes #5131 --- History.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index 7b0cc4abf78..17b03705df4 100644 --- a/History.md +++ b/History.md @@ -2119,7 +2119,7 @@ unreleased * deps: connect@2.21.0 - deprecate `connect(middleware)` -- use `app.use(middleware)` instead - deprecate `connect.createServer()` -- use `connect()` instead - - fix `res.setHeader()` patch to work with with get -> append -> set pattern + - fix `res.setHeader()` patch to work with get -> append -> set pattern - deps: compression@~1.0.8 - deps: errorhandler@~1.1.1 - deps: express-session@~1.5.0 @@ -3330,8 +3330,8 @@ Shaw] * Added node v0.1.97 compatibility * Added support for deleting cookies via Request#cookie('key', null) * Updated haml submodule - * Fixed not-found page, now using using charset utf-8 - * Fixed show-exceptions page, now using using charset utf-8 + * Fixed not-found page, now using charset utf-8 + * Fixed show-exceptions page, now using charset utf-8 * Fixed view support due to fs.readFile Buffers * Changed; mime.type() no longer accepts ".type" due to node extname() changes @@ -3366,7 +3366,7 @@ Shaw] ================== * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s - encoding is set to 'utf8' or 'utf-8'. + encoding is set to 'utf8' or 'utf-8'). * Added "encoding" option to Request#render(). Closes #299 * Added "dump exceptions" setting, which is enabled by default. * Added simple ejs template engine support @@ -3405,7 +3405,7 @@ Shaw] * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js * Added callback function support to Request#halt() as 3rd/4th arg * Added preprocessing of route param wildcards using param(). Closes #251 - * Added view partial support (with collections etc) + * Added view partial support (with collections etc.) * Fixed bug preventing falsey params (such as ?page=0). Closes #286 * Fixed setting of multiple cookies. Closes #199 * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml) From 9bc1742937253825d2dc1e9a48c8e8424f0a315b Mon Sep 17 00:00:00 2001 From: Arnaud Benhamdine Date: Thu, 23 Feb 2023 14:18:57 +0100 Subject: [PATCH 653/889] build: support Node.js 19.x --- .github/workflows/ci.yml | 4 ++++ appveyor.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4bf538948f..c6fb81de93f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,7 @@ jobs: - Node.js 16.x - Node.js 17.x - Node.js 18.x + - Node.js 19.x include: - name: Node.js 0.10 @@ -108,6 +109,9 @@ jobs: - name: Node.js 18.x node-version: "18.14" + - name: Node.js 19.x + node-version: "19.7" + steps: - uses: actions/checkout@v3 diff --git a/appveyor.yml b/appveyor.yml index 47941052bfb..ac671ef47bc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,6 +20,7 @@ environment: - nodejs_version: "16.19" - nodejs_version: "17.9" - nodejs_version: "18.14" + - nodejs_version: "19.7" cache: - node_modules install: From 74beeac0718c928b4ba249aba3652c52fbe32ca8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 23 Feb 2023 17:23:22 -0500 Subject: [PATCH 654/889] Fix routing requests without method --- History.md | 1 + lib/router/route.js | 9 +++++++-- test/Router.js | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 17b03705df4..9e85df3ceb2 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ========== + * Fix routing requests without method * deps: body-parser@1.20.2 - Fix strict json error message on Node.js 19+ - deps: content-type@~1.0.5 diff --git a/lib/router/route.js b/lib/router/route.js index cc643ac8bdb..a65756d6de6 100644 --- a/lib/router/route.js +++ b/lib/router/route.js @@ -60,7 +60,10 @@ Route.prototype._handles_method = function _handles_method(method) { return true; } - var name = method.toLowerCase(); + // normalize name + var name = typeof method === 'string' + ? method.toLowerCase() + : method if (name === 'head' && !this.methods['head']) { name = 'get'; @@ -103,8 +106,10 @@ Route.prototype.dispatch = function dispatch(req, res, done) { if (stack.length === 0) { return done(); } + var method = typeof req.method === 'string' + ? req.method.toLowerCase() + : req.method - var method = req.method.toLowerCase(); if (method === 'head' && !this.methods['head']) { method = 'get'; } diff --git a/test/Router.js b/test/Router.js index 620c60278a1..cf5b5c1f0d3 100644 --- a/test/Router.js +++ b/test/Router.js @@ -61,6 +61,33 @@ describe('Router', function(){ router.handle({ method: 'GET' }, {}, done) }) + it('handle missing method', function (done) { + var all = false + var router = new Router() + var route = router.route('/foo') + var use = false + + route.post(function (req, res, next) { next(new Error('should not run')) }) + route.all(function (req, res, next) { + all = true + next() + }) + route.get(function (req, res, next) { next(new Error('should not run')) }) + + router.get('/foo', function (req, res, next) { next(new Error('should not run')) }) + router.use(function (req, res, next) { + use = true + next() + }) + + router.handle({ url: '/foo' }, {}, function (err) { + if (err) return done(err) + assert.ok(all) + assert.ok(use) + done() + }) + }) + it('should not stack overflow with many registered routes', function(done){ this.timeout(5000) // long-running test From 0debedf4f31bb20203da0534719b9b10d6ac9a29 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 26 Feb 2023 13:34:32 -0500 Subject: [PATCH 655/889] build: fix code coverage aggregate upload --- .github/workflows/ci.yml | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6fb81de93f..b30c56c2f12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -163,25 +163,48 @@ jobs: - name: Run tests shell: bash - run: npm run test-ci + run: | + npm run test-ci + cp coverage/lcov.info "coverage/${{ matrix.name }}.lcov" - name: Lint code if: steps.list_env.outputs.eslint != '' run: npm run lint - name: Collect code coverage - uses: coverallsapp/github-action@master + run: | + mv ./coverage "./${{ matrix.name }}" + mkdir ./coverage + mv "./${{ matrix.name }}" "./coverage/${{ matrix.name }}" + + - name: Upload code coverage + uses: actions/upload-artifact@v3 with: - github-token: ${{ secrets.GITHUB_TOKEN }} - flag-name: run-${{ matrix.test_number }} - parallel: true + name: coverage + path: ./coverage + retention-days: 1 coverage: needs: test runs-on: ubuntu-latest steps: - - name: Upload code coverage + - uses: actions/checkout@v3 + + - name: Install lcov + shell: bash + run: sudo apt-get -y install lcov + + - name: Collect coverage reports + uses: actions/download-artifact@v3 + with: + name: coverage + path: ./coverage + + - name: Merge coverage reports + shell: bash + run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./coverage/lcov.info + + - name: Upload coverage report uses: coverallsapp/github-action@master with: - github-token: ${{ secrets.github_token }} - parallel-finished: true + github-token: ${{ secrets.GITHUB_TOKEN }} From 8c24fa8f7b6d443869c655166c93869d8b299627 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Mar 2023 22:43:19 -0400 Subject: [PATCH 656/889] tests: wait for server close in app.listen() --- test/app.listen.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/app.listen.js b/test/app.listen.js index 08eeaaa63c2..0eec582e69a 100644 --- a/test/app.listen.js +++ b/test/app.listen.js @@ -7,8 +7,7 @@ describe('app.listen()', function(){ var app = express(); var server = app.listen(9999, function(){ - server.close(); - done(); + server.close(done) }); }) }) From f4e48bc43eece928f005a4458c87a16ce089e8e5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Mar 2023 22:49:54 -0400 Subject: [PATCH 657/889] build: ejs@3.1.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e4ed037cfa7..8a7548aff5d 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "connect-redis": "3.4.2", "cookie-parser": "1.4.6", "cookie-session": "2.0.0", - "ejs": "3.1.8", + "ejs": "3.1.9", "eslint": "8.34.0", "express-session": "1.17.2", "hbs": "4.2.0", From b8b2eff3c3eac6a1df3919a87f7c7316d40ae97a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Mar 2023 22:52:34 -0400 Subject: [PATCH 658/889] build: eslint@8.36.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8a7548aff5d..b77937d439f 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "cookie-parser": "1.4.6", "cookie-session": "2.0.0", "ejs": "3.1.9", - "eslint": "8.34.0", + "eslint": "8.36.0", "express-session": "1.17.2", "hbs": "4.2.0", "marked": "0.7.0", From f540c3b0195393974d4875a410f4c00a07a2ab60 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 13 Mar 2023 22:59:15 -0400 Subject: [PATCH 659/889] build: Node.js@18.15 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b30c56c2f12..20c37976a43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: node-version: "17.9" - name: Node.js 18.x - node-version: "18.14" + node-version: "18.15" - name: Node.js 19.x node-version: "19.7" diff --git a/appveyor.yml b/appveyor.yml index ac671ef47bc..e9a6e6d57ef 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.19" - nodejs_version: "17.9" - - nodejs_version: "18.14" + - nodejs_version: "18.15" - nodejs_version: "19.7" cache: - node_modules From 3531987844e533742f1159b0c3f1e07fad2e4597 Mon Sep 17 00:00:00 2001 From: Rakesh Bisht Date: Sat, 4 Mar 2023 13:48:00 +0530 Subject: [PATCH 660/889] lint: remove unused function arguments in Route tests closes #5137 --- test/Route.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Route.js b/test/Route.js index 64dbad60ce9..2a37b9a4839 100644 --- a/test/Route.js +++ b/test/Route.js @@ -124,7 +124,7 @@ describe('Route', function(){ var req = { method: 'POST', url: '/' }; var route = new Route(''); - route.get(function(req, res, next) { + route.get(function () { throw new Error('not me!'); }) @@ -198,7 +198,7 @@ describe('Route', function(){ var req = { order: '', method: 'GET', url: '/' }; var route = new Route(''); - route.all(function(req, res, next){ + route.all(function () { throw new Error('foobar'); }); @@ -224,7 +224,7 @@ describe('Route', function(){ var req = { method: 'GET', url: '/' }; var route = new Route(''); - route.get(function(req, res, next){ + route.get(function () { throw new Error('boom!'); }); From 91b6fb83b4cf30ec626c0582f0b3a0a98d8afcb4 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Apr 2023 20:40:27 -0400 Subject: [PATCH 661/889] build: use nyc@14.1.1 for Node.js < 10 --- .github/workflows/ci.yml | 4 ++-- appveyor.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20c37976a43..856c6314e8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,11 +72,11 @@ jobs: - name: Node.js 8.x node-version: "8.17" - npm-i: mocha@7.2.0 + npm-i: mocha@7.2.0 nyc@14.1.1 - name: Node.js 9.x node-version: "9.11" - npm-i: mocha@7.2.0 + npm-i: mocha@7.2.0 nyc@14.1.1 - name: Node.js 10.x node-version: "10.24" diff --git a/appveyor.yml b/appveyor.yml index e9a6e6d57ef..88e81dfeee4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -70,12 +70,12 @@ install: # nyc for test coverage # - use 10.3.2 for Node.js < 4 # - use 11.9.0 for Node.js < 6 - # - use 14.1.1 for Node.js < 8 + # - use 14.1.1 for Node.js < 10 if ([int]$env:nodejs_version.split(".")[0] -lt 4) { npm install --silent --save-dev nyc@10.3.2 } elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) { npm install --silent --save-dev nyc@11.9.0 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 8) { + } elseif ([int]$env:nodejs_version.split(".")[0] -lt 10) { npm install --silent --save-dev nyc@14.1.1 } - ps: | From 24e4a2570d15d6cca53023410f754929c5391c6f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 6 Apr 2023 20:43:53 -0400 Subject: [PATCH 662/889] build: Node.js@16.20 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 856c6314e8b..30767d98962 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,7 @@ jobs: node-version: "15.14" - name: Node.js 16.x - node-version: "16.19" + node-version: "16.20" - name: Node.js 17.x node-version: "17.9" diff --git a/appveyor.yml b/appveyor.yml index 88e81dfeee4..1412811ff46 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ environment: - nodejs_version: "13.14" - nodejs_version: "14.20" - nodejs_version: "15.14" - - nodejs_version: "16.19" + - nodejs_version: "16.20" - nodejs_version: "17.9" - nodejs_version: "18.15" - nodejs_version: "19.7" From 2a00da2067b7017f769c9100205a2a5f267a884b Mon Sep 17 00:00:00 2001 From: Raz Luvaton <16746759+rluvaton@users.noreply.github.com> Date: Tue, 11 Apr 2023 15:31:47 +0300 Subject: [PATCH 663/889] tests: use random port in listen test closes #5162 --- test/app.listen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/app.listen.js b/test/app.listen.js index 0eec582e69a..5b150063b9e 100644 --- a/test/app.listen.js +++ b/test/app.listen.js @@ -6,7 +6,7 @@ describe('app.listen()', function(){ it('should wrap with an HTTP server', function(done){ var app = express(); - var server = app.listen(9999, function(){ + var server = app.listen(0, function () { server.close(done) }); }) From 13df1de857688057f3c7e6d315321b19f8e4259e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 23 Aug 2023 19:49:36 -0400 Subject: [PATCH 664/889] build: eslint@8.47.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b77937d439f..fdf81725b4f 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "cookie-parser": "1.4.6", "cookie-session": "2.0.0", "ejs": "3.1.9", - "eslint": "8.36.0", + "eslint": "8.47.0", "express-session": "1.17.2", "hbs": "4.2.0", "marked": "0.7.0", From 8d8bfaac7be5d06c0a8fcc069b1ee5b0ec398cd9 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 23 Aug 2023 19:58:41 -0400 Subject: [PATCH 665/889] build: Node.js@18.17 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30767d98962..3d14976a9b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: node-version: "17.9" - name: Node.js 18.x - node-version: "18.15" + node-version: "18.17" - name: Node.js 19.x node-version: "19.7" diff --git a/appveyor.yml b/appveyor.yml index 1412811ff46..63adc423c8f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.20" - nodejs_version: "17.9" - - nodejs_version: "18.15" + - nodejs_version: "18.17" - nodejs_version: "19.7" cache: - node_modules From 02d1c3916ebaec776b4d754be54aa1500e2e9563 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 23 Aug 2023 20:07:50 -0400 Subject: [PATCH 666/889] build: Node.js@19.9 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d14976a9b2..35017785332 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -110,7 +110,7 @@ jobs: node-version: "18.17" - name: Node.js 19.x - node-version: "19.7" + node-version: "19.9" steps: - uses: actions/checkout@v3 diff --git a/appveyor.yml b/appveyor.yml index 63adc423c8f..44af842e858 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,7 +20,7 @@ environment: - nodejs_version: "16.20" - nodejs_version: "17.9" - nodejs_version: "18.17" - - nodejs_version: "19.7" + - nodejs_version: "19.9" cache: - node_modules install: From a22920707bfd30e083e5b8e076841d226266cb06 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 1 Nov 2023 22:08:37 -0400 Subject: [PATCH 667/889] build: actions/checkout@v4 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35017785332..b545e8bd0d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,7 +113,7 @@ jobs: node-version: "19.9" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Node.js ${{ matrix.node-version }} shell: bash -eo pipefail -l {0} @@ -188,7 +188,7 @@ jobs: needs: test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install lcov shell: bash From c4fe7de7bcb7ce241dfa7137fad96d48b75e86f3 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Fri, 16 Feb 2024 08:52:09 -0600 Subject: [PATCH 668/889] docs: update TC governance rules closes #5483 --- Contributing.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Contributing.md b/Contributing.md index 485dee597e1..89f92806328 100644 --- a/Contributing.md +++ b/Contributing.md @@ -107,7 +107,22 @@ move forward towards a consensus. It is not expected that a meeting of the TC will resolve all issues on its agenda during that meeting and may prefer to continue the discussion happening among the committers. -Members can be added to the TC at any time. Any committer can nominate another committer +Members can be added to the TC at any time. Any TC member can nominate another committer to the TC and the TC uses its standard consensus seeking process to evaluate whether or -not to add this new member. Members who do not participate consistently at the level of -a majority of the other members are expected to resign. +not to add this new member. The TC will consist of a minimum of 3 active members and a +maximum of 10. If the TC should drop below 5 members the active TC members should nominate +someone new. If a TC member is stepping down, they are encouraged (but not required) to +nominate someone to take their place. + +TC members will be added as admin's on the Github orgs, npm orgs, and other resources as +necessary to be effective in the role. + +To remain "active" a TC member should have participation within the last 6 months and miss +no more than three consecutive TC meetings. Members who do not meet this are expected to step down. +If A TC member does not step down, an issue can be opened in the discussions repo to move them +to inactive status. TC members who step down or are removed due to inactivity will be moved +into inactive status. + +Inactive status members can become active members by self nomination if the TC is not already +larger than the maximum of 10. They will also be given preference if, while at max size, an +active member steps down. From 59aae7686b995186a71da48abd4af5be72ff4ef5 Mon Sep 17 00:00:00 2001 From: Gireesh Punathil Date: Mon, 9 Mar 2020 14:12:29 +0530 Subject: [PATCH 669/889] docs: add project captains to contribution closes #4210 closes #5484 --- Contributing.md | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/Contributing.md b/Contributing.md index 89f92806328..dfe5f13833b 100644 --- a/Contributing.md +++ b/Contributing.md @@ -12,6 +12,7 @@ contributors can be involved in decision making. * A **Contributor** is any individual creating or commenting on an issue or pull request. * A **Committer** is a subset of contributors who have been given write access to the repository. +* A **Project Captain** is the lead maintainer of a repository. * A **TC (Technical Committee)** is a group of committers representing the required technical expertise to resolve rare disputes. * A **Triager** is a subset of contributors who have been given triage access to the repository. @@ -102,10 +103,10 @@ If a consensus cannot be reached that has no objections then a majority wins vot is called. It is also expected that the majority of decisions made by the TC are via a consensus seeking process and that voting is only used as a last-resort. -Resolution may involve returning the issue to committers with suggestions on how to -move forward towards a consensus. It is not expected that a meeting of the TC +Resolution may involve returning the issue to project captains with suggestions on +how to move forward towards a consensus. It is not expected that a meeting of the TC will resolve all issues on its agenda during that meeting and may prefer to continue -the discussion happening among the committers. +the discussion happening among the project captains. Members can be added to the TC at any time. Any TC member can nominate another committer to the TC and the TC uses its standard consensus seeking process to evaluate whether or @@ -126,3 +127,34 @@ into inactive status. Inactive status members can become active members by self nomination if the TC is not already larger than the maximum of 10. They will also be given preference if, while at max size, an active member steps down. + +## Project Captains + +The Express TC can designate captains for individual projects/repos in the +organizations. These captains are responsible for being the primary +day-to-day maintainers of the repo on a technical and community front. +Repo captains are empowered with repo ownership and package publication rights. +When there are conflicts, especially on topics that effect the Express project +at large, captains are responsible to raise it up to the TC and drive +those conflicts to resolution. Captains are also responsible for making sure +community members follow the community guidelines, maintaining the repo +and the published package, as well as in providing user support. + +Like TC members, Repo captains are a subset of committers. + +To become a captain for a project the candidate is expected to participate in that +project for at least 6 months as a committer prior to the request. They should have +helped with code contributions as well as triaging issues. They are also required to +have 2FA enabled on both their GitHub and npm accounts. Any TC member or existing +captain on the repo can nominate another committer to the captain role, submit a PR to +this doc, under `Current Project Captains` section (maintaining the sort order) with +the project, their GitHub handle and npm username (if different). The PR will require +at least 2 approvals from TC members and 2 weeks hold time to allow for comment and/or +dissent. When the PR is merged, a TC member will add them to the proper GitHub/npm groups. + +### Current Project Captains + +- `expressjs.com`: @crandmck +- `multer`: @LinusU +- `path-to-regexp`: @blakeembrey +- `router`: @dougwilson From 2a89eb5c749a168820d6ea96723ad8a7e979a58b Mon Sep 17 00:00:00 2001 From: christof louw Date: Thu, 27 Jul 2023 11:06:18 +0200 Subject: [PATCH 670/889] tests: fix handling multiple callbacks closes #5233 --- test/Router.js | 6 +++--- test/app.router.js | 2 +- test/app.use.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/Router.js b/test/Router.js index cf5b5c1f0d3..b22001a9ff2 100644 --- a/test/Router.js +++ b/test/Router.js @@ -606,8 +606,8 @@ describe('Router', function(){ var req2 = { url: '/foo/10/bar', method: 'get' }; var router = new Router(); var sub = new Router(); + var cb = after(2, done) - done = after(2, done); sub.get('/bar', function(req, res, next) { next(); @@ -626,14 +626,14 @@ describe('Router', function(){ assert.ifError(err); assert.equal(req1.ms, 50); assert.equal(req1.originalUrl, '/foo/50/bar'); - done(); + cb() }); router.handle(req2, {}, function(err) { assert.ifError(err); assert.equal(req2.ms, 10); assert.equal(req2.originalUrl, '/foo/10/bar'); - done(); + cb() }); }); }); diff --git a/test/app.router.js b/test/app.router.js index 4fde03105c6..12b6c1fa519 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -896,7 +896,7 @@ describe('app.router', function(){ request(app) .get('/foo.json') - .expect(200, 'foo as json', done) + .expect(200, 'foo as json', cb) }) }) diff --git a/test/app.use.js b/test/app.use.js index fd9b1751a31..1de3275c8e2 100644 --- a/test/app.use.js +++ b/test/app.use.js @@ -57,7 +57,7 @@ describe('app', function(){ request(app) .get('/forum') - .expect(200, 'forum', done) + .expect(200, 'forum', cb) }) it('should set the child\'s .parent', function(){ From 3abea7f8189c73f7f219d8878343d961eb9a4910 Mon Sep 17 00:00:00 2001 From: riddlew Date: Thu, 18 May 2023 09:26:47 -0400 Subject: [PATCH 671/889] examples: remove multipart example Closes #5193 closes #5195 --- examples/README.md | 1 - examples/multipart/index.js | 62 ------------------------------------- package.json | 1 - 3 files changed, 64 deletions(-) delete mode 100644 examples/multipart/index.js diff --git a/examples/README.md b/examples/README.md index c19ed30a25c..bd1f1f6310f 100644 --- a/examples/README.md +++ b/examples/README.md @@ -13,7 +13,6 @@ This page contains list of examples using Express. - [hello-world](./hello-world) - Simple request handler - [markdown](./markdown) - Markdown as template engine - [multi-router](./multi-router) - Working with multiple Express routers -- [multipart](./multipart) - Accepting multipart-encoded forms - [mvc](./mvc) - MVC-style controllers - [online](./online) - Tracking online user activity with `online` and `redis` packages - [params](./params) - Working with route parameters diff --git a/examples/multipart/index.js b/examples/multipart/index.js deleted file mode 100644 index ea7b86e0c94..00000000000 --- a/examples/multipart/index.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict' - -/** - * Module dependencies. - */ - -var express = require('../..'); -var multiparty = require('multiparty'); -var format = require('util').format; - -var app = module.exports = express(); - -app.get('/', function(req, res){ - res.send('' - + '

        Title:

        ' - + '

        Image:

        ' - + '

        ' - + ''); -}); - -app.post('/', function(req, res, next){ - // create a form to begin parsing - var form = new multiparty.Form(); - var image; - var title; - - form.on('error', next); - form.on('close', function(){ - res.send(format('\nuploaded %s (%d Kb) as %s' - , image.filename - , image.size / 1024 | 0 - , title)); - }); - - // listen on field event for title - form.on('field', function(name, val){ - if (name !== 'title') return; - title = val; - }); - - // listen on part event for image file - form.on('part', function(part){ - if (!part.filename) return; - if (part.name !== 'image') return part.resume(); - image = {}; - image.filename = part.filename; - image.size = 0; - part.on('data', function(buf){ - image.size += buf.length; - }); - }); - - - // parse the form - form.parse(req); -}); - -/* istanbul ignore next */ -if (!module.parent) { - app.listen(4000); - console.log('Express started on port 4000'); -} diff --git a/package.json b/package.json index fdf81725b4f..cf367736434 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "method-override": "3.0.0", "mocha": "10.2.0", "morgan": "1.10.0", - "multiparty": "4.2.3", "nyc": "15.1.0", "pbkdf2-password": "1.2.1", "supertest": "6.3.0", From e720c5a21bfed5a9c73b2407797023bacad6980e Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Sat, 11 Nov 2023 20:02:47 +0100 Subject: [PATCH 672/889] docs: add documentation for benchmarks closes #5312 --- benchmarks/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 benchmarks/README.md diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 00000000000..1894c527d63 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,34 @@ +# Express Benchmarks + +## Installation + +You will need to install [wrk](https://github.com/wg/wrk/blob/master/INSTALL) in order to run the benchmarks. + +## Running + +To run the benchmarks, first install the dependencies `npm i`, then run `make` + +The output will look something like this: + +``` + 50 connections + 1 middleware + 7.15ms + 6784.01 + + [...redacted...] + + 1000 connections + 10 middleware + 139.21ms + 6155.19 + +``` + +### Tip: Include Node.js version in output + +You can use `make && node -v` to include the node.js version in the output. + +### Tip: Save the results to a file + +You can use `make > results.log` to save the results to a file `results.log`. From 59af63ac2e6aea6a9cefb6fe27705ccf024d8373 Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Sat, 17 Feb 2024 18:26:40 +0100 Subject: [PATCH 673/889] build: Node.js@18.19 closes #5490 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b545e8bd0d1..5bef1f67edf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: node-version: "17.9" - name: Node.js 18.x - node-version: "18.17" + node-version: "18.19" - name: Node.js 19.x node-version: "19.9" diff --git a/appveyor.yml b/appveyor.yml index 44af842e858..b865082930f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - nodejs_version: "15.14" - nodejs_version: "16.20" - nodejs_version: "17.9" - - nodejs_version: "18.17" + - nodejs_version: "18.19" - nodejs_version: "19.9" cache: - node_modules From 0e3ab6ec215fc297473323fb1e8d0df03033e774 Mon Sep 17 00:00:00 2001 From: Dmitry Kondar Date: Sat, 27 Jan 2024 20:29:09 +0200 Subject: [PATCH 674/889] examples: improve view count in cookie-sessions closes #5414 --- examples/cookie-sessions/index.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/cookie-sessions/index.js b/examples/cookie-sessions/index.js index 01c731c1c8f..83b6faee82b 100644 --- a/examples/cookie-sessions/index.js +++ b/examples/cookie-sessions/index.js @@ -13,13 +13,10 @@ var app = module.exports = express(); app.use(cookieSession({ secret: 'manny is cool' })); // do something with the session -app.use(count); - -// custom middleware -function count(req, res) { +app.get('/', function (req, res) { req.session.count = (req.session.count || 0) + 1 res.send('viewed ' + req.session.count + ' times\n') -} +}) /* istanbul ignore next */ if (!module.parent) { From 734b28190085c052e3ecd9c7d0b9595d9edb1b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Fri, 2 Feb 2024 15:35:20 +0100 Subject: [PATCH 675/889] build: support Node.js 20.x --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bef1f67edf..df123370d9e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,7 @@ jobs: - Node.js 17.x - Node.js 18.x - Node.js 19.x + - Node.js 20.x include: - name: Node.js 0.10 @@ -112,6 +113,8 @@ jobs: - name: Node.js 19.x node-version: "19.9" + - name: Node.js 20.x + node-version: "20.11" steps: - uses: actions/checkout@v4 From fdeb1d3176d11506557388ecaa2fe6a250e17efc Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Fri, 2 Feb 2024 16:31:12 +0100 Subject: [PATCH 676/889] build: support Node.js 20.x in appveyor closes #5429 --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index b865082930f..cb3e835a89e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,6 +21,7 @@ environment: - nodejs_version: "17.9" - nodejs_version: "18.19" - nodejs_version: "19.9" + - nodejs_version: "20.11" cache: - node_modules install: From c259c3407f8c503c83d95fb1f30b132b73bb6388 Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Fri, 2 Feb 2024 15:38:07 +0100 Subject: [PATCH 677/889] build: support Node.js 21.x --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df123370d9e..e880f74dab6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,7 @@ jobs: - Node.js 18.x - Node.js 19.x - Node.js 20.x + - Node.js 21.x include: - name: Node.js 0.10 @@ -115,6 +116,10 @@ jobs: - name: Node.js 20.x node-version: "20.11" + + - name: Node.js 21.x + node-version: "21.6.1" + steps: - uses: actions/checkout@v4 From b9fea1224516e372f6f63480cc1830e5f6ee63e6 Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Fri, 2 Feb 2024 16:31:54 +0100 Subject: [PATCH 678/889] build: support Node.js 21.x in appveyor --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index cb3e835a89e..5c01a8d02ad 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,6 +22,7 @@ environment: - nodejs_version: "18.19" - nodejs_version: "19.9" - nodejs_version: "20.11" + - nodejs_version: "21.6.1" cache: - node_modules install: From 23b44b3ddd45bc68487cc34cd576b117ba9d2609 Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Sat, 17 Feb 2024 18:23:09 +0100 Subject: [PATCH 679/889] build: support Node.js 21.6.2 --- .github/workflows/ci.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e880f74dab6..aa231b74d24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,7 +118,7 @@ jobs: node-version: "20.11" - name: Node.js 21.x - node-version: "21.6.1" + node-version: "21.6.2" steps: - uses: actions/checkout@v4 diff --git a/appveyor.yml b/appveyor.yml index 5c01a8d02ad..8ece802a7fc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ environment: - nodejs_version: "18.19" - nodejs_version: "19.9" - nodejs_version: "20.11" - - nodejs_version: "21.6.1" + - nodejs_version: "21.6.2" cache: - node_modules install: From e3eca805847e0057ab1c83e7d61a6cc1c1ca47f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 20 Feb 2024 08:44:27 +0100 Subject: [PATCH 680/889] build: pin Node 21.x to minor Co-authored-by: Aravind Nair <22199259+aravindvnair99@users.noreply.github.com> --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 8ece802a7fc..ce26523b3aa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ environment: - nodejs_version: "18.19" - nodejs_version: "19.9" - nodejs_version: "20.11" - - nodejs_version: "21.6.2" + - nodejs_version: "21.6" cache: - node_modules install: From b625132864ef40b1fb119ff7c7b984573a7974c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 20 Feb 2024 08:44:34 +0100 Subject: [PATCH 681/889] build: pin Node 21.x to minor Co-authored-by: Aravind Nair <22199259+aravindvnair99@users.noreply.github.com> closes #5430 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa231b74d24..01c82f81960 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,7 +118,7 @@ jobs: node-version: "20.11" - name: Node.js 21.x - node-version: "21.6.2" + node-version: "21.6" steps: - uses: actions/checkout@v4 From 1b51edac7c5f2844e23602164a52643bb625993a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Mon, 26 Feb 2024 20:20:53 +0100 Subject: [PATCH 682/889] 4.18.3 --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 9e85df3ceb2..07840455573 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -unreleased +4.18.3 / 2024-02-26 ========== * Fix routing requests without method diff --git a/package.json b/package.json index cf367736434..c3845d2d4bf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.18.2", + "version": "4.18.3", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 06c6b88808f6d836afc58296812235a96d708b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Sun, 10 Mar 2024 20:04:02 +0100 Subject: [PATCH 683/889] docs: update release date --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 07840455573..b674cab4b0a 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -4.18.3 / 2024-02-26 +4.18.3 / 2024-02-29 ========== * Fix routing requests without method From 414854b82ea4312f50641ddf7668c9194c3c209c Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 29 Feb 2024 08:49:34 -0600 Subject: [PATCH 684/889] docs: nominating @wesleytodd to be project captian --- Contributing.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Contributing.md b/Contributing.md index dfe5f13833b..7311454dd89 100644 --- a/Contributing.md +++ b/Contributing.md @@ -154,7 +154,21 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ ### Current Project Captains -- `expressjs.com`: @crandmck -- `multer`: @LinusU -- `path-to-regexp`: @blakeembrey -- `router`: @dougwilson +- `expressjs/express`: @wesleytodd +- `expressjs/discussions`: @wesleytodd +- `expressjs/expressjs.com`: @crandmck +- `expressjs/body-parser`: @wesleytodd +- `expressjs/multer`: @LinusU +- `expressjs/cookie-parser`: @wesleytodd +- `expressjs/generator`: @wesleytodd +- `expressjs/statusboard`: @wesleytodd +- `pillarjs/path-to-regexp`: @blakeembrey +- `pillarjs/router`: @dougwilson, @wesleytodd +- `pillarjs/finalhandler`: @wesleytodd +- `pillarjs/request`: @wesleytodd +- `jshttp/http-errors`: @wesleytodd +- `jshttp/cookie`: @wesleytodd +- `jshttp/on-finished`: @wesleytodd +- `jshttp/forwarded`: @wesleytodd +- `jshttp/proxy-addr`: @wesleytodd + From 4ee853e837dcc6c6c9f93c52278abe775c717fa1 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 28 Feb 2024 14:49:11 -0600 Subject: [PATCH 685/889] docs: loosen TC activity rules --- Contributing.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Contributing.md b/Contributing.md index 7311454dd89..a9ba84690cb 100644 --- a/Contributing.md +++ b/Contributing.md @@ -118,11 +118,13 @@ nominate someone to take their place. TC members will be added as admin's on the Github orgs, npm orgs, and other resources as necessary to be effective in the role. -To remain "active" a TC member should have participation within the last 6 months and miss -no more than three consecutive TC meetings. Members who do not meet this are expected to step down. -If A TC member does not step down, an issue can be opened in the discussions repo to move them -to inactive status. TC members who step down or are removed due to inactivity will be moved -into inactive status. +To remain "active" a TC member should have participation within the last 12 months and miss +no more than six consecutive TC meetings. Our goal is to increase participation, not punish +people for any lack of participation, this guideline should be only be used as such +(replace an inactive member with a new active one, for example). Members who do not meet this +are expected to step down. If A TC member does not step down, an issue can be opened in the +discussions repo to move them to inactive status. TC members who step down or are removed due +to inactivity will be moved into inactive status. Inactive status members can become active members by self nomination if the TC is not already larger than the maximum of 10. They will also be given preference if, while at max size, an From 69a4cf2819c4449ec6ea45649691fb43a528d5d1 Mon Sep 17 00:00:00 2001 From: Rich Hodgkins Date: Thu, 11 Jan 2024 11:36:11 +0000 Subject: [PATCH 686/889] deps: cookie@0.6.0 closes #5404 --- History.md | 7 +++++++ package.json | 2 +- test/res.cookie.js | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index b674cab4b0a..0559bb012c5 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * deps: cookie@0.6.0 + 4.18.3 / 2024-02-29 ========== @@ -6,6 +11,8 @@ - Fix strict json error message on Node.js 19+ - deps: content-type@~1.0.5 - deps: raw-body@2.5.2 + * deps: cookie@0.6.0 + - Add `partitioned` option 4.18.2 / 2022-10-08 =================== diff --git a/package.json b/package.json index c3845d2d4bf..990e98dc1aa 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", diff --git a/test/res.cookie.js b/test/res.cookie.js index 93deb769887..c837820605c 100644 --- a/test/res.cookie.js +++ b/test/res.cookie.js @@ -82,6 +82,22 @@ describe('res', function(){ }) }) + describe('partitioned', function () { + it('should set partitioned', function (done) { + var app = express(); + + app.use(function (req, res) { + res.cookie('name', 'tobi', { partitioned: true }); + res.end(); + }); + + request(app) + .get('/') + .expect('Set-Cookie', 'name=tobi; Path=/; Partitioned') + .expect(200, done) + }) + }) + describe('maxAge', function(){ it('should set relative expires', function(done){ var app = express(); From 567c9c665d0de4c344b8e160146050770233783c Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Sat, 16 Mar 2024 11:57:42 -0600 Subject: [PATCH 687/889] Add note on how to update docs for new release (#5541) * Update Release-Process.md Add note about updating docs. * Update Release-Process.md * Update Release-Process.md --- Release-Process.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Release-Process.md b/Release-Process.md index ae740972f77..55e62189250 100644 --- a/Release-Process.md +++ b/Release-Process.md @@ -184,3 +184,9 @@ $ npm publish **NOTE:** The version number to publish will be picked up automatically from package.json. + +### Step 7. Update documentation website + +The documentation website https://expressjs.com/ documents the current release version in various places. For a new release: +1. Change the value of `current_version` in https://github.com/expressjs/expressjs.com/blob/gh-pages/_data/express.yml to match the latest version number. +2. Add a new section to the change log. For example, for a 4.x release, https://github.com/expressjs/expressjs.com/blob/gh-pages/en/changelog/4x.md, From 0867302ddbde0e9463d0564fea5861feb708c2dd Mon Sep 17 00:00:00 2001 From: FDrag0n <34733637+FDrag0n@users.noreply.github.com> Date: Fri, 15 Mar 2024 15:49:01 +0800 Subject: [PATCH 688/889] Prevent open redirect allow list bypass due to encodeurl Co-authored-by: Jon Church --- lib/response.js | 20 ++++++++++++++++++- test/res.location.js | 46 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/lib/response.js b/lib/response.js index fede486c06d..f7c94d10e78 100644 --- a/lib/response.js +++ b/lib/response.js @@ -34,6 +34,7 @@ var extname = path.extname; var mime = send.mime; var resolve = path.resolve; var vary = require('vary'); +var urlParse = require('url').parse; /** * Response prototype. @@ -911,8 +912,25 @@ res.location = function location(url) { loc = this.req.get('Referrer') || '/'; } + var lowerLoc = loc.toLowerCase(); + var encodedUrl = encodeUrl(loc); + if (lowerLoc.indexOf('https://') === 0 || lowerLoc.indexOf('http://') === 0) { + try { + var parsedUrl = urlParse(loc); + var parsedEncodedUrl = urlParse(encodedUrl); + // Because this can encode the host, check that we did not change the host + if (parsedUrl.host !== parsedEncodedUrl.host) { + // If the host changes after encodeUrl, return the original url + return this.set('Location', loc); + } + } catch (e) { + // If parse fails, return the original url + return this.set('Location', loc); + } + } + // set location - return this.set('Location', encodeUrl(loc)); + return this.set('Location', encodedUrl); }; /** diff --git a/test/res.location.js b/test/res.location.js index 158afac01e7..38cab027a83 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -1,13 +1,27 @@ 'use strict' var express = require('../') - , request = require('supertest'); + , request = require('supertest') + , url = require('url'); describe('res', function(){ describe('.location(url)', function(){ it('should set the header', function(done){ var app = express(); + app.use(function(req, res){ + res.location('http://google.com/').end(); + }); + + request(app) + .get('/') + .expect('Location', 'http://google.com/') + .expect(200, done) + }) + + it('should preserve trailing slashes when not present', function(done){ + var app = express(); + app.use(function(req, res){ res.location('http://google.com/').end(); }); @@ -31,6 +45,36 @@ describe('res', function(){ .expect(200, done) }) + it('should not encode bad "url"', function (done) { + var app = express() + + app.use(function (req, res) { + // This is here to show a basic check one might do which + // would pass but then the location header would still be bad + if (url.parse(req.query.q).host !== 'google.com') { + res.status(400).end('Bad url'); + } + res.location(req.query.q).end(); + }); + + request(app) + .get('/?q=http://google.com\\@apple.com') + .expect(200) + .expect('Location', 'http://google.com//@apple.com') + .end(function (err) { + if (err) { + throw err; + } + + // This ensures that our protocol check is case insensitive + request(app) + .get('/?q=HTTP://google.com\\@apple.com') + .expect(200) + .expect('Location', 'HTTP://google.com\\@apple.com') + .end(done) + }); + }); + it('should not touch already-encoded sequences in "url"', function (done) { var app = express() From 084e36506a18774f85206a65d8da04dc1107fc1b Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 20 Mar 2024 10:09:10 -0500 Subject: [PATCH 689/889] 4.19.0 --- History.md | 3 ++- package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 0559bb012c5..877f1c56fbe 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ -unreleased +4.18.3 / 2024-03-20 ========== + * Prevent open redirect allow list bypass due to encodeurl * deps: cookie@0.6.0 4.18.3 / 2024-02-29 diff --git a/package.json b/package.json index 990e98dc1aa..eca07b57c8b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.18.3", + "version": "4.19.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 11f2b1db227fd42c2508c427032c1ec671b306be Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 20 Mar 2024 11:33:31 -0500 Subject: [PATCH 690/889] build: fix build due to inconsistent supertest behavior in older versions --- test/res.location.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/res.location.js b/test/res.location.js index 38cab027a83..71fbaec03d4 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -58,7 +58,7 @@ describe('res', function(){ }); request(app) - .get('/?q=http://google.com\\@apple.com') + .get('/?q=http://google.com' + encodeURIComponent('\\@apple.com')) .expect(200) .expect('Location', 'http://google.com//@apple.com') .end(function (err) { @@ -68,7 +68,7 @@ describe('res', function(){ // This ensures that our protocol check is case insensitive request(app) - .get('/?q=HTTP://google.com\\@apple.com') + .get('/?q=HTTP://google.com' + encodeURIComponent('\\@apple.com')) .expect(200) .expect('Location', 'HTTP://google.com\\@apple.com') .end(done) From a1fa90fcea7d8e844e1c9938ad095d62669c3abd Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 20 Mar 2024 16:39:46 -0500 Subject: [PATCH 691/889] fixed un-edited version in history.md for 4.19.0 --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 877f1c56fbe..b6208ea7e32 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -4.18.3 / 2024-03-20 +4.19.0 / 2024-03-20 ========== * Prevent open redirect allow list bypass due to encodeurl From a003cfab034fbadb1c78ae337ee8ab389adda217 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 20 Mar 2024 16:39:46 -0500 Subject: [PATCH 692/889] Allow passing non-strings to res.location with new encoding handling checks fixes #5554 #5555 --- History.md | 5 +++++ lib/response.js | 2 +- test/res.location.js | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index b6208ea7e32..2fda95c1551 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased changes +========== + + * Allow passing non-strings to res.location with new encoding handling checks + 4.19.0 / 2024-03-20 ========== diff --git a/lib/response.js b/lib/response.js index f7c94d10e78..6fddbf35165 100644 --- a/lib/response.js +++ b/lib/response.js @@ -905,7 +905,7 @@ res.cookie = function (name, value, options) { */ res.location = function location(url) { - var loc = url; + var loc = String(url); // "back" is an alias for the referrer if (url === 'back') { diff --git a/test/res.location.js b/test/res.location.js index 71fbaec03d4..d1bbf4b6879 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -145,5 +145,20 @@ describe('res', function(){ .expect(200, done) }) }) + + if (typeof URL !== 'undefined') { + it('should accept an instance of URL', function (done) { + var app = express(); + + app.use(function(req, res){ + res.location(new URL('http://google.com/')).end(); + }); + + request(app) + .get('/') + .expect('Location', 'http://google.com/') + .expect(200, done); + }); + } }) }) From 4f0f6cc67d531431c096ea006c2191b92931bbc3 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 20 Mar 2024 17:17:59 -0500 Subject: [PATCH 693/889] 4.19.1 --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 2fda95c1551..c4cdd94dacf 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -unreleased changes +4.19.1 / 2024-03-20 ========== * Allow passing non-strings to res.location with new encoding handling checks diff --git a/package.json b/package.json index eca07b57c8b..51c6aba2127 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.19.0", + "version": "4.19.1", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 416ba025a1fb77f0762eb25ae0d6fc79035a2fbd Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 20 Mar 2024 21:47:11 -0500 Subject: [PATCH 694/889] build: disable test for 4.x which is failing in v5 --- test/res.status.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test/res.status.js b/test/res.status.js index 1fe08344eaa..d2fc6a28c13 100644 --- a/test/res.status.js +++ b/test/res.status.js @@ -9,7 +9,11 @@ var isIoJs = process.release describe('res', function () { describe('.status(code)', function () { - describe('when "code" is undefined', function () { + // This test fails in node 4.0.0 + // https://github.com/expressjs/express/pull/2237/checks + // As this will all be removed when https://github.com/expressjs/express/pull/4212 + // lands I am skipping for now and we can delete with that PR + describe.skip('when "code" is undefined', function () { it('should raise error for invalid status code', function (done) { var app = express() @@ -29,7 +33,7 @@ describe('res', function () { }) }) - describe('when "code" is null', function () { + describe.skip('when "code" is null', function () { it('should raise error for invalid status code', function (done) { var app = express() @@ -119,7 +123,7 @@ describe('res', function () { }) }) - describe('when "code" is 410.1', function () { + describe.skip('when "code" is 410.1', function () { it('should set the response status code to 410', function (done) { var app = express() @@ -139,7 +143,7 @@ describe('res', function () { }) }) - describe('when "code" is 1000', function () { + describe.skip('when "code" is 1000', function () { it('should raise error for invalid status code', function (done) { var app = express() @@ -159,7 +163,7 @@ describe('res', function () { }) }) - describe('when "code" is 99', function () { + describe.skip('when "code" is 99', function () { it('should raise error for invalid status code', function (done) { var app = express() @@ -179,7 +183,7 @@ describe('res', function () { }) }) - describe('when "code" is -401', function () { + describe.skip('when "code" is -401', function () { it('should raise error for invalid status code', function (done) { var app = express() From 7091ec17f046a12a294155e6584f8da699fa160d Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 20 Mar 2024 22:00:19 -0500 Subject: [PATCH 695/889] 5.0.0-beta.2 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 640156d78b3..67280ae1653 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ -5.x -=== +5.0.0-beta.2 / 2024-03-20 +========================= This incorporates all changes after 4.17.2 up to 4.19.1. diff --git a/package.json b/package.json index c12c755c968..e5f602cd25f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-beta.1", + "version": "5.0.0-beta.2", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From da4d763ff6ba9df6dbd8f1f0b1d05412dda934d5 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 21 Mar 2024 12:13:56 -0500 Subject: [PATCH 696/889] Improved fix for open redirect allow list bypass Co-authored-by: Jon Church Co-authored-by: Blake Embrey --- History.md | 5 + lib/response.js | 31 ++--- test/res.location.js | 307 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 280 insertions(+), 63 deletions(-) diff --git a/History.md b/History.md index c4cdd94dacf..f62574a7ee1 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Improved fix for open redirect allow list bypass + 4.19.1 / 2024-03-20 ========== diff --git a/lib/response.js b/lib/response.js index 6fddbf35165..dd7b3c8201d 100644 --- a/lib/response.js +++ b/lib/response.js @@ -34,7 +34,6 @@ var extname = path.extname; var mime = send.mime; var resolve = path.resolve; var vary = require('vary'); -var urlParse = require('url').parse; /** * Response prototype. @@ -56,6 +55,7 @@ module.exports = res */ var charsetRegExp = /;\s*charset\s*=/; +var schemaAndHostRegExp = /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?\/\/[^\\\/\?]+/; /** * Set status `code`. @@ -905,32 +905,23 @@ res.cookie = function (name, value, options) { */ res.location = function location(url) { - var loc = String(url); + var loc; // "back" is an alias for the referrer if (url === 'back') { loc = this.req.get('Referrer') || '/'; + } else { + loc = String(url); } - var lowerLoc = loc.toLowerCase(); - var encodedUrl = encodeUrl(loc); - if (lowerLoc.indexOf('https://') === 0 || lowerLoc.indexOf('http://') === 0) { - try { - var parsedUrl = urlParse(loc); - var parsedEncodedUrl = urlParse(encodedUrl); - // Because this can encode the host, check that we did not change the host - if (parsedUrl.host !== parsedEncodedUrl.host) { - // If the host changes after encodeUrl, return the original url - return this.set('Location', loc); - } - } catch (e) { - // If parse fails, return the original url - return this.set('Location', loc); - } - } + var m = schemaAndHostRegExp.exec(loc); + var pos = m ? m[0].length + 1 : 0; + + // Only encode after host to avoid invalid encoding which can introduce + // vulnerabilities (e.g. `\\` to `%5C`). + loc = loc.slice(0, pos) + encodeUrl(loc.slice(pos)); - // set location - return this.set('Location', encodedUrl); + return this.set('Location', loc); }; /** diff --git a/test/res.location.js b/test/res.location.js index d1bbf4b6879..c80b38de6b8 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -2,6 +2,7 @@ var express = require('../') , request = require('supertest') + , assert = require('assert') , url = require('url'); describe('res', function(){ @@ -45,49 +46,6 @@ describe('res', function(){ .expect(200, done) }) - it('should not encode bad "url"', function (done) { - var app = express() - - app.use(function (req, res) { - // This is here to show a basic check one might do which - // would pass but then the location header would still be bad - if (url.parse(req.query.q).host !== 'google.com') { - res.status(400).end('Bad url'); - } - res.location(req.query.q).end(); - }); - - request(app) - .get('/?q=http://google.com' + encodeURIComponent('\\@apple.com')) - .expect(200) - .expect('Location', 'http://google.com//@apple.com') - .end(function (err) { - if (err) { - throw err; - } - - // This ensures that our protocol check is case insensitive - request(app) - .get('/?q=HTTP://google.com' + encodeURIComponent('\\@apple.com')) - .expect(200) - .expect('Location', 'HTTP://google.com\\@apple.com') - .end(done) - }); - }); - - it('should not touch already-encoded sequences in "url"', function (done) { - var app = express() - - app.use(function (req, res) { - res.location('https://google.com/?q=%A710').end() - }) - - request(app) - .get('/') - .expect('Location', 'https://google.com/?q=%A710') - .expect(200, done) - }) - describe('when url is "back"', function () { it('should set location from "Referer" header', function (done) { var app = express() @@ -146,6 +104,79 @@ describe('res', function(){ }) }) + it('should encode data uri', function (done) { + var app = express() + app.use(function (req, res) { + res.location('data:text/javascript,export default () => { }').end(); + }); + + request(app) + .get('/') + .expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D') + .expect(200, done) + }) + + it('should encode data uri', function (done) { + var app = express() + app.use(function (req, res) { + res.location('data:text/javascript,export default () => { }').end(); + }); + + request(app) + .get('/') + .expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D') + .expect(200, done) + }) + + it('should consistently handle non-string input: boolean', function (done) { + var app = express() + app.use(function (req, res) { + res.location(true).end(); + }); + + request(app) + .get('/') + .expect('Location', 'true') + .expect(200, done) + }); + + it('should consistently handle non-string inputs: object', function (done) { + var app = express() + app.use(function (req, res) { + res.location({}).end(); + }); + + request(app) + .get('/') + .expect('Location', '[object%20Object]') + .expect(200, done) + }); + + it('should consistently handle non-string inputs: array', function (done) { + var app = express() + app.use(function (req, res) { + res.location([]).end(); + }); + + request(app) + .get('/') + .expect('Location', '') + .expect(200, done) + }); + + it('should consistently handle empty string input', function (done) { + var app = express() + app.use(function (req, res) { + res.location('').end(); + }); + + request(app) + .get('/') + .expect('Location', '') + .expect(200, done) + }); + + if (typeof URL !== 'undefined') { it('should accept an instance of URL', function (done) { var app = express(); @@ -161,4 +192,194 @@ describe('res', function(){ }); } }) + + describe('location header encoding', function() { + function createRedirectServerForDomain (domain) { + var app = express(); + app.use(function (req, res) { + var host = url.parse(req.query.q, false, true).host; + // This is here to show a basic check one might do which + // would pass but then the location header would still be bad + if (host !== domain) { + res.status(400).end('Bad host: ' + host + ' !== ' + domain); + } + res.location(req.query.q).end(); + }); + return app; + } + + function testRequestedRedirect (app, inputUrl, expected, expectedHost, done) { + return request(app) + // Encode uri because old supertest does not and is required + // to test older node versions. New supertest doesn't re-encode + // so this works in both. + .get('/?q=' + encodeURIComponent(inputUrl)) + .expect('') // No body. + .expect(200) + .expect('Location', expected) + .end(function (err, res) { + if (err) { + console.log('headers:', res.headers) + console.error('error', res.error, err); + return done(err, res); + } + + // Parse the hosts from the input URL and the Location header + var inputHost = url.parse(inputUrl, false, true).host; + var locationHost = url.parse(res.headers['location'], false, true).host; + + assert.strictEqual(locationHost, expectedHost); + + // Assert that the hosts are the same + if (inputHost !== locationHost) { + return done(new Error('Hosts do not match: ' + inputHost + " !== " + locationHost)); + } + + return done(null, res); + }); + } + + it('should not touch already-encoded sequences in "url"', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com/?q=%A710', + 'https://google.com/?q=%A710', + 'google.com', + done + ); + }); + + it('should consistently handle relative urls', function (done) { + var app = createRedirectServerForDomain(null); + testRequestedRedirect( + app, + '/foo/bar', + '/foo/bar', + null, + done + ); + }); + + it('should not encode urls in such a way that they can bypass redirect allow lists', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'http://google.com//@apple.com', + 'http://google.com//@apple.com', + 'google.com', + done + ); + }); + + it('should not be case sensitive', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'HTTP://google.com\\@apple.com', + 'HTTP://google.com\\@apple.com', + 'google.com', + done + ); + }); + + it('should work with https', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com//@apple.com', + 'https://google.com//@apple.com', + 'google.com', + done + ); + }); + + it('should correctly encode schemaless paths', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + '//google.com\\@apple.com/', + '//google.com\\@apple.com/', + 'google.com', + done + ); + }); + + it('should percent encode backslashes in the path', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com/foo//bar//baz', + 'https://google.com/foo%5Cbar%5Cbaz', + 'google.com', + done + ); + }); + + it('should encode backslashes in the path after the first backslash that triggered path parsing', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com//@app//l//e.com', + 'https://google.com//@app%5Cl%5Ce.com', + 'google.com', + done + ); + }); + + it('should escape header splitting for old node versions', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'http://google.com//@apple.com/%0d%0afoo:%20bar', + 'http://google.com//@apple.com/%0d%0afoo:%20bar', + 'google.com', + done + ); + }); + + it('should encode unicode correctly', function (done) { + var app = createRedirectServerForDomain(null); + testRequestedRedirect( + app, + '/%e2%98%83', + '/%e2%98%83', + null, + done + ); + }); + + it('should encode unicode correctly even with a bad host', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'http://google.com//@apple.com/%e2%98%83', + 'http://google.com//@apple.com/%e2%98%83', + 'google.com', + done + ); + }); + + it('should work correctly despite using deprecated url.parse', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com/'.bb.com/1.html', + 'https://google.com/'.bb.com/1.html', + 'google.com', + done + ); + }); + + it('should encode file uri path', function (done) { + var app = createRedirectServerForDomain(''); + testRequestedRedirect( + app, + 'file:///etc\\passwd', + 'file:///etc%5Cpasswd', + '', + done + ); + }); + }); }) From 04bc62787be974874bc1467b23606c36bc9779ba Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 25 Mar 2024 09:26:03 -0500 Subject: [PATCH 697/889] 4.19.2 --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index f62574a7ee1..ac2e7cf719d 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -unreleased +4.19.2 / 2024-03-25 ========== * Improved fix for open redirect allow list bypass diff --git a/package.json b/package.json index 51c6aba2127..f299d882b0d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.19.1", + "version": "4.19.2", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 0b746953c4bd8e377123527db11f9cd866e39f94 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 21 Mar 2024 12:13:56 -0500 Subject: [PATCH 698/889] Improved fix for open redirect allow list bypass Co-authored-by: Jon Church Co-authored-by: Blake Embrey --- History.md | 5 + lib/response.js | 31 ++--- test/res.location.js | 307 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 280 insertions(+), 63 deletions(-) diff --git a/History.md b/History.md index c4cdd94dacf..f62574a7ee1 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Improved fix for open redirect allow list bypass + 4.19.1 / 2024-03-20 ========== diff --git a/lib/response.js b/lib/response.js index 6fddbf35165..dd7b3c8201d 100644 --- a/lib/response.js +++ b/lib/response.js @@ -34,7 +34,6 @@ var extname = path.extname; var mime = send.mime; var resolve = path.resolve; var vary = require('vary'); -var urlParse = require('url').parse; /** * Response prototype. @@ -56,6 +55,7 @@ module.exports = res */ var charsetRegExp = /;\s*charset\s*=/; +var schemaAndHostRegExp = /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?\/\/[^\\\/\?]+/; /** * Set status `code`. @@ -905,32 +905,23 @@ res.cookie = function (name, value, options) { */ res.location = function location(url) { - var loc = String(url); + var loc; // "back" is an alias for the referrer if (url === 'back') { loc = this.req.get('Referrer') || '/'; + } else { + loc = String(url); } - var lowerLoc = loc.toLowerCase(); - var encodedUrl = encodeUrl(loc); - if (lowerLoc.indexOf('https://') === 0 || lowerLoc.indexOf('http://') === 0) { - try { - var parsedUrl = urlParse(loc); - var parsedEncodedUrl = urlParse(encodedUrl); - // Because this can encode the host, check that we did not change the host - if (parsedUrl.host !== parsedEncodedUrl.host) { - // If the host changes after encodeUrl, return the original url - return this.set('Location', loc); - } - } catch (e) { - // If parse fails, return the original url - return this.set('Location', loc); - } - } + var m = schemaAndHostRegExp.exec(loc); + var pos = m ? m[0].length + 1 : 0; + + // Only encode after host to avoid invalid encoding which can introduce + // vulnerabilities (e.g. `\\` to `%5C`). + loc = loc.slice(0, pos) + encodeUrl(loc.slice(pos)); - // set location - return this.set('Location', encodedUrl); + return this.set('Location', loc); }; /** diff --git a/test/res.location.js b/test/res.location.js index d1bbf4b6879..c80b38de6b8 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -2,6 +2,7 @@ var express = require('../') , request = require('supertest') + , assert = require('assert') , url = require('url'); describe('res', function(){ @@ -45,49 +46,6 @@ describe('res', function(){ .expect(200, done) }) - it('should not encode bad "url"', function (done) { - var app = express() - - app.use(function (req, res) { - // This is here to show a basic check one might do which - // would pass but then the location header would still be bad - if (url.parse(req.query.q).host !== 'google.com') { - res.status(400).end('Bad url'); - } - res.location(req.query.q).end(); - }); - - request(app) - .get('/?q=http://google.com' + encodeURIComponent('\\@apple.com')) - .expect(200) - .expect('Location', 'http://google.com//@apple.com') - .end(function (err) { - if (err) { - throw err; - } - - // This ensures that our protocol check is case insensitive - request(app) - .get('/?q=HTTP://google.com' + encodeURIComponent('\\@apple.com')) - .expect(200) - .expect('Location', 'HTTP://google.com\\@apple.com') - .end(done) - }); - }); - - it('should not touch already-encoded sequences in "url"', function (done) { - var app = express() - - app.use(function (req, res) { - res.location('https://google.com/?q=%A710').end() - }) - - request(app) - .get('/') - .expect('Location', 'https://google.com/?q=%A710') - .expect(200, done) - }) - describe('when url is "back"', function () { it('should set location from "Referer" header', function (done) { var app = express() @@ -146,6 +104,79 @@ describe('res', function(){ }) }) + it('should encode data uri', function (done) { + var app = express() + app.use(function (req, res) { + res.location('data:text/javascript,export default () => { }').end(); + }); + + request(app) + .get('/') + .expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D') + .expect(200, done) + }) + + it('should encode data uri', function (done) { + var app = express() + app.use(function (req, res) { + res.location('data:text/javascript,export default () => { }').end(); + }); + + request(app) + .get('/') + .expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D') + .expect(200, done) + }) + + it('should consistently handle non-string input: boolean', function (done) { + var app = express() + app.use(function (req, res) { + res.location(true).end(); + }); + + request(app) + .get('/') + .expect('Location', 'true') + .expect(200, done) + }); + + it('should consistently handle non-string inputs: object', function (done) { + var app = express() + app.use(function (req, res) { + res.location({}).end(); + }); + + request(app) + .get('/') + .expect('Location', '[object%20Object]') + .expect(200, done) + }); + + it('should consistently handle non-string inputs: array', function (done) { + var app = express() + app.use(function (req, res) { + res.location([]).end(); + }); + + request(app) + .get('/') + .expect('Location', '') + .expect(200, done) + }); + + it('should consistently handle empty string input', function (done) { + var app = express() + app.use(function (req, res) { + res.location('').end(); + }); + + request(app) + .get('/') + .expect('Location', '') + .expect(200, done) + }); + + if (typeof URL !== 'undefined') { it('should accept an instance of URL', function (done) { var app = express(); @@ -161,4 +192,194 @@ describe('res', function(){ }); } }) + + describe('location header encoding', function() { + function createRedirectServerForDomain (domain) { + var app = express(); + app.use(function (req, res) { + var host = url.parse(req.query.q, false, true).host; + // This is here to show a basic check one might do which + // would pass but then the location header would still be bad + if (host !== domain) { + res.status(400).end('Bad host: ' + host + ' !== ' + domain); + } + res.location(req.query.q).end(); + }); + return app; + } + + function testRequestedRedirect (app, inputUrl, expected, expectedHost, done) { + return request(app) + // Encode uri because old supertest does not and is required + // to test older node versions. New supertest doesn't re-encode + // so this works in both. + .get('/?q=' + encodeURIComponent(inputUrl)) + .expect('') // No body. + .expect(200) + .expect('Location', expected) + .end(function (err, res) { + if (err) { + console.log('headers:', res.headers) + console.error('error', res.error, err); + return done(err, res); + } + + // Parse the hosts from the input URL and the Location header + var inputHost = url.parse(inputUrl, false, true).host; + var locationHost = url.parse(res.headers['location'], false, true).host; + + assert.strictEqual(locationHost, expectedHost); + + // Assert that the hosts are the same + if (inputHost !== locationHost) { + return done(new Error('Hosts do not match: ' + inputHost + " !== " + locationHost)); + } + + return done(null, res); + }); + } + + it('should not touch already-encoded sequences in "url"', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com/?q=%A710', + 'https://google.com/?q=%A710', + 'google.com', + done + ); + }); + + it('should consistently handle relative urls', function (done) { + var app = createRedirectServerForDomain(null); + testRequestedRedirect( + app, + '/foo/bar', + '/foo/bar', + null, + done + ); + }); + + it('should not encode urls in such a way that they can bypass redirect allow lists', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'http://google.com//@apple.com', + 'http://google.com//@apple.com', + 'google.com', + done + ); + }); + + it('should not be case sensitive', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'HTTP://google.com\\@apple.com', + 'HTTP://google.com\\@apple.com', + 'google.com', + done + ); + }); + + it('should work with https', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com//@apple.com', + 'https://google.com//@apple.com', + 'google.com', + done + ); + }); + + it('should correctly encode schemaless paths', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + '//google.com\\@apple.com/', + '//google.com\\@apple.com/', + 'google.com', + done + ); + }); + + it('should percent encode backslashes in the path', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com/foo//bar//baz', + 'https://google.com/foo%5Cbar%5Cbaz', + 'google.com', + done + ); + }); + + it('should encode backslashes in the path after the first backslash that triggered path parsing', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com//@app//l//e.com', + 'https://google.com//@app%5Cl%5Ce.com', + 'google.com', + done + ); + }); + + it('should escape header splitting for old node versions', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'http://google.com//@apple.com/%0d%0afoo:%20bar', + 'http://google.com//@apple.com/%0d%0afoo:%20bar', + 'google.com', + done + ); + }); + + it('should encode unicode correctly', function (done) { + var app = createRedirectServerForDomain(null); + testRequestedRedirect( + app, + '/%e2%98%83', + '/%e2%98%83', + null, + done + ); + }); + + it('should encode unicode correctly even with a bad host', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'http://google.com//@apple.com/%e2%98%83', + 'http://google.com//@apple.com/%e2%98%83', + 'google.com', + done + ); + }); + + it('should work correctly despite using deprecated url.parse', function (done) { + var app = createRedirectServerForDomain('google.com'); + testRequestedRedirect( + app, + 'https://google.com/'.bb.com/1.html', + 'https://google.com/'.bb.com/1.html', + 'google.com', + done + ); + }); + + it('should encode file uri path', function (done) { + var app = createRedirectServerForDomain(''); + testRequestedRedirect( + app, + 'file:///etc\\passwd', + 'file:///etc%5Cpasswd', + '', + done + ); + }); + }); }) From b28db2c12c3bd9cd763316824446f79bf81e0686 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 25 Mar 2024 09:26:03 -0500 Subject: [PATCH 699/889] 4.19.2 --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index f62574a7ee1..ac2e7cf719d 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -unreleased +4.19.2 / 2024-03-25 ========== * Improved fix for open redirect allow list bypass diff --git a/package.json b/package.json index 51c6aba2127..f299d882b0d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.19.1", + "version": "4.19.2", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From cd7d79f92a7209b09aa9b065b0643c1bec55ed1d Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 25 Mar 2024 09:41:30 -0500 Subject: [PATCH 700/889] v5.0.0-beta.3 --- History.md | 7 ++++++- package.json | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index cd5ccf0a396..73fc46b26fb 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,12 @@ +5.0.0-beta.3 / 2024-03-25 +========================= + +This incorporates all changes after 4.19.1 up to 4.19.2. + 5.0.0-beta.2 / 2024-03-20 ========================= -This incorporates all changes after 4.17.2 up to 4.19.2. +This incorporates all changes after 4.17.2 up to 4.19.1. 5.0.0-beta.1 / 2022-02-14 ========================= diff --git a/package.json b/package.json index e5f602cd25f..5a8f978e1c2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-beta.2", + "version": "5.0.0-beta.3", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 94669f9289fdd1c640b0c35acf4d9f8e996a646c Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 25 Mar 2024 10:03:18 -0500 Subject: [PATCH 701/889] remove duplicate location test for data uri --- test/res.location.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test/res.location.js b/test/res.location.js index c80b38de6b8..141ee901310 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -116,18 +116,6 @@ describe('res', function(){ .expect(200, done) }) - it('should encode data uri', function (done) { - var app = express() - app.use(function (req, res) { - res.location('data:text/javascript,export default () => { }').end(); - }); - - request(app) - .get('/') - .expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D') - .expect(200, done) - }) - it('should consistently handle non-string input: boolean', function (done) { var app = express() app.use(function (req, res) { From 51595d402ba155877e48a2a6c807b956a6d6d376 Mon Sep 17 00:00:00 2001 From: marco-ippolito Date: Tue, 26 Mar 2024 12:37:28 +0100 Subject: [PATCH 702/889] feat: document beta releases expectations --- Release-Process.md | 7 +++++++ Security.md | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/Release-Process.md b/Release-Process.md index 55e62189250..9ea0cf3212e 100644 --- a/Release-Process.md +++ b/Release-Process.md @@ -77,6 +77,13 @@ non-patch flow. - This branch contains the commits accepted so far that implement the proposal in the tracking pull request. +### Beta releases + +Beta releases are made from a proposal branch. The version number should be +incremented to the next minor version with a `-beta` suffix. For example, if the +next release is `5.0.1`, the beta release would be `5.0.1-beta.0`. The beta +release should be considered unstable and not suitable for production use. + ### Patch flow In the patch flow, simple changes are committed to the release branch which diff --git a/Security.md b/Security.md index cdcd7a6e0aa..d1c4bb7f022 100644 --- a/Security.md +++ b/Security.md @@ -29,6 +29,12 @@ announcement, and may ask for additional information or guidance. Report security bugs in third-party modules to the person or team maintaining the module. +## Beta releases + +Beta releases should be considered unstable and **not suitable for production use**. +Vulnerabilities found in beta releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section. +Due to the unstable nature of the branch it is not garanteed that the fix will be released in the next beta release. + ## Disclosure Policy When the security team receives a security bug report, they will assign it to a From 88bd6d8e3a91f2059a89493a32952c5e01a1b40a Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Tue, 26 Mar 2024 15:32:34 +0100 Subject: [PATCH 703/889] Update Release-Process.md Co-authored-by: Wes Todd --- Release-Process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release-Process.md b/Release-Process.md index 9ea0cf3212e..0b95a6f3a7d 100644 --- a/Release-Process.md +++ b/Release-Process.md @@ -77,7 +77,7 @@ non-patch flow. - This branch contains the commits accepted so far that implement the proposal in the tracking pull request. -### Beta releases +### Pre-release Versions Beta releases are made from a proposal branch. The version number should be incremented to the next minor version with a `-beta` suffix. For example, if the From 4e3f95c0ea4ba6b3f116e65dbb5828e918ea25fb Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Tue, 26 Mar 2024 15:41:07 +0100 Subject: [PATCH 704/889] Update Security.md Co-authored-by: Wes Todd --- Security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Security.md b/Security.md index d1c4bb7f022..9a9986d73ca 100644 --- a/Security.md +++ b/Security.md @@ -29,7 +29,7 @@ announcement, and may ask for additional information or guidance. Report security bugs in third-party modules to the person or team maintaining the module. -## Beta releases +## Pre-release Versions Beta releases should be considered unstable and **not suitable for production use**. Vulnerabilities found in beta releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section. From 51a76366e34a9d5ac238c48ebfbd20a020cb635e Mon Sep 17 00:00:00 2001 From: marco-ippolito Date: Tue, 26 Mar 2024 15:44:10 +0100 Subject: [PATCH 705/889] refactor: reword to pre-releases --- Release-Process.md | 8 ++++---- Security.md | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Release-Process.md b/Release-Process.md index 0b95a6f3a7d..c74f16f08b2 100644 --- a/Release-Process.md +++ b/Release-Process.md @@ -79,10 +79,10 @@ non-patch flow. ### Pre-release Versions -Beta releases are made from a proposal branch. The version number should be -incremented to the next minor version with a `-beta` suffix. For example, if the -next release is `5.0.1`, the beta release would be `5.0.1-beta.0`. The beta -release should be considered unstable and not suitable for production use. +Alpha and Beta releases are made from a proposal branch. The version number should be +incremented to the next minor version with a `-beta` or `-alpha` suffix. +For example, if the next beta release is `5.0.1`, the beta release would be `5.0.1-beta.0`. +The pre-releases should be considered unstable and not suitable for production use. ### Patch flow diff --git a/Security.md b/Security.md index 9a9986d73ca..d49ddd75a24 100644 --- a/Security.md +++ b/Security.md @@ -31,9 +31,9 @@ the module. ## Pre-release Versions -Beta releases should be considered unstable and **not suitable for production use**. -Vulnerabilities found in beta releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section. -Due to the unstable nature of the branch it is not garanteed that the fix will be released in the next beta release. +Alpha and Beta releases should be considered unstable and **not suitable for production use**. +Vulnerabilities found in pre-releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section. +Due to the unstable nature of the branch it is not garanteed that the fix will be released in the next pre-release. ## Disclosure Policy From 6d98d2e1103dfe73cb8efc47521d42c269e5bf08 Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Tue, 26 Mar 2024 17:01:11 +0100 Subject: [PATCH 706/889] Update Release-Process.md Co-authored-by: Chris de Almeida --- Release-Process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release-Process.md b/Release-Process.md index c74f16f08b2..9ca0a15ab46 100644 --- a/Release-Process.md +++ b/Release-Process.md @@ -82,7 +82,7 @@ non-patch flow. Alpha and Beta releases are made from a proposal branch. The version number should be incremented to the next minor version with a `-beta` or `-alpha` suffix. For example, if the next beta release is `5.0.1`, the beta release would be `5.0.1-beta.0`. -The pre-releases should be considered unstable and not suitable for production use. +The pre-releases are unstable and not suitable for production use. ### Patch flow From 36b814811079d8d242e69257de46576822d6bb4f Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Tue, 26 Mar 2024 17:01:17 +0100 Subject: [PATCH 707/889] Update Security.md Co-authored-by: Chris de Almeida --- Security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Security.md b/Security.md index d49ddd75a24..99e8d537734 100644 --- a/Security.md +++ b/Security.md @@ -31,7 +31,7 @@ the module. ## Pre-release Versions -Alpha and Beta releases should be considered unstable and **not suitable for production use**. +Alpha and Beta releases are unstable and **not suitable for production use**. Vulnerabilities found in pre-releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section. Due to the unstable nature of the branch it is not garanteed that the fix will be released in the next pre-release. From 8b6d34963d0bf0944d7da2da6fb2b71e36a61421 Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Tue, 26 Mar 2024 17:01:30 +0100 Subject: [PATCH 708/889] Update Security.md Co-authored-by: Chris de Almeida --- Security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Security.md b/Security.md index 99e8d537734..39f055b3b96 100644 --- a/Security.md +++ b/Security.md @@ -33,7 +33,7 @@ the module. Alpha and Beta releases are unstable and **not suitable for production use**. Vulnerabilities found in pre-releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section. -Due to the unstable nature of the branch it is not garanteed that the fix will be released in the next pre-release. +Due to the unstable nature of the branch it is not guaranteed that any fixes will be released in the next pre-release. ## Disclosure Policy From 3ae704f67fbbea3d6ac6aeb9563b5bc48615743f Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 25 Mar 2024 21:43:35 -0400 Subject: [PATCH 709/889] update ci push trigger only to some branches, ignore examples, .md --- .github/workflows/ci.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01c82f81960..a16debdef9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,18 @@ name: ci on: -- pull_request -- push + push: + branches: + - master + - '4.x' + - '5.x' + paths-ignore: + - 'examples/**' + - '*.md' + pull_request: + paths-ignore: + - 'examples/**' + - '*.md' jobs: test: From 4771ba2bc3b5c6c26dd28783f0dc962d008edab8 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 25 Mar 2024 22:12:28 -0400 Subject: [PATCH 710/889] crib fastify's ci concurrency logic https://github.com/fastify/fastify/blob/76674fdf46e4da5f1c18e0c86f615c4b538282cd/.github/workflows/ci.yml#L18 --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a16debdef9a..7fc216da6ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,12 @@ on: - 'examples/**' - '*.md' +# Cancel in progress workflows +# in the scenario where we already had a run going for that PR/branch/tag but then triggered a new run +concurrency: + group: "${{ github.workflow }} ✨ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}" + cancel-in-progress: true + jobs: test: runs-on: ubuntu-latest From d546f93f2f4658c3c03828afacc6dfd26788f7a7 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 25 Mar 2024 22:29:05 -0400 Subject: [PATCH 711/889] add develop to branches --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7fc216da6ce..81e48233738 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - develop - '4.x' - '5.x' paths-ignore: From 6da57c7819dfefa228ab68c884d701a8cf45f39b Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 25 Mar 2024 22:45:13 -0400 Subject: [PATCH 712/889] remove examples from the ignore --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81e48233738..f43deeb5385 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,11 +8,9 @@ on: - '4.x' - '5.x' paths-ignore: - - 'examples/**' - '*.md' pull_request: paths-ignore: - - 'examples/**' - '*.md' # Cancel in progress workflows From 2676a1f281e8f1cc73591d3fa8917344dcc60d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 4 Apr 2024 13:01:35 +0200 Subject: [PATCH 713/889] docs: add reference to the Threat Model * docs: add Threat Model * docs: update reference Co-authored-by: Chris de Almeida * docs: improve readability Co-authored-by: Chris de Almeida * docs: add reference to the Threat Model --------- Co-authored-by: Chris de Almeida --- Security.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Security.md b/Security.md index 39f055b3b96..6b5d2b0686e 100644 --- a/Security.md +++ b/Security.md @@ -46,6 +46,10 @@ involving the following steps: * Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible to npm. +## The Express Threat Model + +We are currently working on a new version of the security model, the most updated version can be found [here](https://github.com/expressjs/security-wg/blob/main/tools/docs/ThreatModel.md) + ## Comments on this Policy If you have suggestions on how this process could be improved please submit a From 93cf646d5c3643b0d14563795eb45aba583b1568 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Sun, 7 Apr 2024 09:40:16 -0700 Subject: [PATCH 714/889] docs: add blakeembrey as captain for encodeurl (#5579) --- Contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index a9ba84690cb..599df10360f 100644 --- a/Contributing.md +++ b/Contributing.md @@ -164,6 +164,7 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - `expressjs/cookie-parser`: @wesleytodd - `expressjs/generator`: @wesleytodd - `expressjs/statusboard`: @wesleytodd +- `pillarjs/encodeurl`: @blakeembrey - `pillarjs/path-to-regexp`: @blakeembrey - `pillarjs/router`: @dougwilson, @wesleytodd - `pillarjs/finalhandler`: @wesleytodd @@ -173,4 +174,3 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - `jshttp/on-finished`: @wesleytodd - `jshttp/forwarded`: @wesleytodd - `jshttp/proxy-addr`: @wesleytodd - From 7f9e5843b9690267cf87efe63b48d45425f9ebc3 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 8 Apr 2024 09:02:12 -0400 Subject: [PATCH 715/889] add jonchurch as repo captain on several packages --- Contributing.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Contributing.md b/Contributing.md index 599df10360f..9baa666b712 100644 --- a/Contributing.md +++ b/Contributing.md @@ -158,10 +158,12 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - `expressjs/express`: @wesleytodd - `expressjs/discussions`: @wesleytodd -- `expressjs/expressjs.com`: @crandmck -- `expressjs/body-parser`: @wesleytodd +- `expressjs/expressjs.com`: @crandmck, @jonchurch +- `expressjs/body-parser`: @wesleytodd, @jonchurch - `expressjs/multer`: @LinusU +- `expressjs/morgan`: @jonchurch - `expressjs/cookie-parser`: @wesleytodd +- `expressjs/cors`: @jonchurch - `expressjs/generator`: @wesleytodd - `expressjs/statusboard`: @wesleytodd - `pillarjs/encodeurl`: @blakeembrey @@ -169,7 +171,7 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - `pillarjs/router`: @dougwilson, @wesleytodd - `pillarjs/finalhandler`: @wesleytodd - `pillarjs/request`: @wesleytodd -- `jshttp/http-errors`: @wesleytodd +- `jshttp/http-errors`: @wesleytodd, @jonchurch - `jshttp/cookie`: @wesleytodd - `jshttp/on-finished`: @wesleytodd - `jshttp/forwarded`: @wesleytodd From 815f799310a5627c000d4a5156c1c958e4947b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Marqu=C3=ADnez=20Prado?= <25435858+inigomarquinez@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:53:52 +0200 Subject: [PATCH 716/889] docs: update reference to the threat model (#5590) PR: https://github.com/expressjs/express/pull/5590 --- Security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Security.md b/Security.md index 6b5d2b0686e..dcfbe88abd4 100644 --- a/Security.md +++ b/Security.md @@ -48,7 +48,7 @@ involving the following steps: ## The Express Threat Model -We are currently working on a new version of the security model, the most updated version can be found [here](https://github.com/expressjs/security-wg/blob/main/tools/docs/ThreatModel.md) +We are currently working on a new version of the security model, the most updated version can be found [here](https://github.com/expressjs/security-wg/blob/main/docs/ThreatModel.md) ## Comments on this Policy From e9bcdd399b244079f4cf77dd5ffa58c5831b8b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 11 Apr 2024 19:16:20 +0200 Subject: [PATCH 717/889] ci: adopt Node@18 as the minimum supported version --- .github/workflows/ci.yml | 83 ---------------------------------------- appveyor.yml | 59 ---------------------------- 2 files changed, 142 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89d95f85d7f..0575f075e73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,83 +11,12 @@ jobs: fail-fast: false matrix: name: - - Node.js 4.0 - - Node.js 4.x - - Node.js 5.x - - Node.js 6.x - - Node.js 7.x - - Node.js 8.x - - Node.js 9.x - - Node.js 10.x - - Node.js 11.x - - Node.js 12.x - - Node.js 13.x - - Node.js 14.x - - Node.js 15.x - - Node.js 16.x - - Node.js 17.x - Node.js 18.x - Node.js 19.x - Node.js 20.x - Node.js 21.x include: - - name: Node.js 4.0 - node-version: "4.0" - npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - - - name: Node.js 4.x - node-version: "4.9" - npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - - - name: Node.js 5.x - node-version: "5.12" - npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - - - name: Node.js 6.x - node-version: "6.17" - npm-i: mocha@6.2.2 nyc@14.1.1 supertest@3.4.2 - - - name: Node.js 7.x - node-version: "7.10" - npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6 - - - name: Node.js 8.x - node-version: "8.17" - npm-i: mocha@7.2.0 nyc@14.1.1 - - - name: Node.js 9.x - node-version: "9.11" - npm-i: mocha@7.2.0 nyc@14.1.1 - - - name: Node.js 10.x - node-version: "10.24" - npm-i: mocha@8.4.0 - - - name: Node.js 11.x - node-version: "11.15" - npm-i: mocha@8.4.0 - - - name: Node.js 12.x - node-version: "12.22" - npm-i: mocha@9.2.2 - - - name: Node.js 13.x - node-version: "13.14" - npm-i: mocha@9.2.2 - - - name: Node.js 14.x - node-version: "14.20" - - - name: Node.js 15.x - node-version: "15.14" - - - name: Node.js 16.x - node-version: "16.20" - - - name: Node.js 17.x - node-version: "17.9" - - name: Node.js 18.x node-version: "18.19" @@ -125,18 +54,6 @@ jobs: - name: Remove non-test dependencies run: npm rm --silent --save-dev connect-redis - - name: Setup Node.js version-specific dependencies - shell: bash - run: | - # eslint for linting - # - remove on Node.js < 12 - if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then - node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ - grep -E '^eslint(-|$)' | \ - sort -r | \ - xargs -n1 npm rm --silent --save-dev - fi - - name: Install Node.js dependencies run: npm install diff --git a/appveyor.yml b/appveyor.yml index 185eccf8cab..5506914898e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,19 +1,5 @@ environment: matrix: - - nodejs_version: "4.9" - - nodejs_version: "5.12" - - nodejs_version: "6.17" - - nodejs_version: "7.10" - - nodejs_version: "8.17" - - nodejs_version: "9.11" - - nodejs_version: "10.24" - - nodejs_version: "11.15" - - nodejs_version: "12.22" - - nodejs_version: "13.14" - - nodejs_version: "14.20" - - nodejs_version: "15.14" - - nodejs_version: "16.20" - - nodejs_version: "17.9" - nodejs_version: "18.19" - nodejs_version: "19.9" - nodejs_version: "20.11" @@ -41,51 +27,6 @@ install: cmd.exe /c "node -pe `"Object.keys(require('./package').devDependencies).join('\n')`"" | ` sls "^eslint(-|$)" | ` %{ npm rm --silent --save-dev $_ } - # Setup Node.js version-specific dependencies - - ps: | - # mocha for testing - # - use 5.x for Node.js < 6 - # - use 6.x for Node.js < 8 - # - use 7.x for Node.js < 10 - # - use 8.x for Node.js < 12 - # - use 9.x for Node.js < 14 - if ([int]$env:nodejs_version.split(".")[0] -lt 4) { - npm install --silent --save-dev mocha@3.5.3 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) { - npm install --silent --save-dev mocha@5.2.0 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 8) { - npm install --silent --save-dev mocha@6.2.2 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 10) { - npm install --silent --save-dev mocha@7.2.0 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 12) { - npm install --silent --save-dev mocha@8.4.0 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 14) { - npm install --silent --save-dev mocha@9.2.2 - } - - ps: | - # nyc for test coverage - # - use 10.3.2 for Node.js < 4 - # - use 11.9.0 for Node.js < 6 - # - use 14.1.1 for Node.js < 10 - if ([int]$env:nodejs_version.split(".")[0] -lt 4) { - npm install --silent --save-dev nyc@10.3.2 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) { - npm install --silent --save-dev nyc@11.9.0 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 10) { - npm install --silent --save-dev nyc@14.1.1 - } - - ps: | - # supertest for http calls - # - use 2.0.0 for Node.js < 4 - # - use 3.4.2 for Node.js < 7 - # - use 6.1.6 for Node.js < 8 - if ([int]$env:nodejs_version.split(".")[0] -lt 4) { - npm install --silent --save-dev supertest@2.0.0 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 7) { - npm install --silent --save-dev supertest@3.4.2 - } elseif ([int]$env:nodejs_version.split(".")[0] -lt 8) { - npm install --silent --save-dev supertest@6.1.6 - } # Update Node.js modules - ps: | # Prune & rebuild node_modules From 4b3b8cc231381fe9357d7d98f6afd3e8e9f9d63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 11 Apr 2024 19:19:47 +0200 Subject: [PATCH 718/889] feat: adopt Node@18 as the minimum supported version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a8f978e1c2..06e67892dd3 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "vhost": "~3.0.2" }, "engines": { - "node": ">= 4" + "node": ">= 18" }, "files": [ "LICENSE", From 6abec204c0a6dc0b2a7adcd6f118ca5fb757e4aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Wed, 17 Apr 2024 13:53:16 +0200 Subject: [PATCH 719/889] docs: update triage nomination policy (#5600) PR-URL: https://github.com/expressjs/express/pull/5600 --- Contributing.md | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/Contributing.md b/Contributing.md index 9baa666b712..f2ffe4935a2 100644 --- a/Contributing.md +++ b/Contributing.md @@ -63,29 +63,14 @@ compromise among committers be the default resolution mechanism. Anyone can become a triager! Read more about the process of being a triager in [the triage process document](Triager-Guide.md). -[Open an issue in `expressjs/express` repo](https://github.com/expressjs/express/issues/new) -to request the triage role. State that you have read and agree to the -[Code of Conduct](Code-Of-Conduct.md) and details of the role. - -Here is an example issue content you can copy and paste: - -``` -Title: Request triager role for - -I have read and understood the project's Code of Conduct. -I also have read and understood the process and best practices around Express triaging. - -I request for a triager role for the following GitHub organizations: - -jshttp -pillarjs -express -``` - -Once you have opened your issue, a member of the TC will add you to the `triage` team in -the organizations requested. They will then close the issue. - -Happy triaging! +Currently, any existing [organization member](https://github.com/orgs/expressjs/people) can nominate +a new triager. If you are interested in becoming a triager, our best advice is to actively participate +in the community by helping triaging issues and pull requests. As well we recommend +to engage in other community activities like attending the TC meetings, and participating in the Slack +discussions. + +You can also reach out to any of the [organization members](https://github.com/orgs/expressjs/people) +if you have questions or need guidance. ## Becoming a Committer From 26e53f0fbcaf1fa71a68a42dcd6c17af05fe6ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Wed, 17 Apr 2024 15:13:07 +0200 Subject: [PATCH 720/889] ci: add CodeQL (SAST) (#5433) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/expressjs/express/pull/5433 --------- Co-authored-by: Íñigo Marquínez Prado <25435858+inigomarquinez@users.noreply.github.com> --- .github/workflows/codeql.yml | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..db4e01aff56 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,66 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: ["master"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["master"] + schedule: + - cron: "0 0 * * 1" + +permissions: + contents: read + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 + with: + languages: javascript + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + # - name: Autobuild + # uses: github/codeql-action/autobuild@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 + with: + category: "/language:javascript" From d97d79ed9a25099ec4f0537ad8bf2a9378350a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Wed, 17 Apr 2024 14:25:38 +0200 Subject: [PATCH 721/889] docs: add UlisesGascon as triage initiative captain --- Contributing.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Contributing.md b/Contributing.md index f2ffe4935a2..4262b0f20db 100644 --- a/Contributing.md +++ b/Contributing.md @@ -161,3 +161,7 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - `jshttp/on-finished`: @wesleytodd - `jshttp/forwarded`: @wesleytodd - `jshttp/proxy-addr`: @wesleytodd + +### Current Initiative Captains + +- Triage team [ref](https://github.com/expressjs/discussions/issues/227): @UlisesGascon From 14439731f968c1ec6015227d747ede32d3fbf676 Mon Sep 17 00:00:00 2001 From: Evan Hahn Date: Thu, 17 Mar 2022 12:34:13 -0500 Subject: [PATCH 722/889] Use object with null prototype for various app properties `app.cache`, `app.engines`, and `app.settings` are now created with `Object.create(null)` instead of `{}`. This also updates a test to ensure that `app.locals` is created the same way. --- lib/application.js | 6 +++--- test/app.locals.js | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/application.js b/lib/application.js index 4d98425adc6..2a370aa3106 100644 --- a/lib/application.js +++ b/lib/application.js @@ -61,9 +61,9 @@ var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default'; app.init = function init() { var router = null; - this.cache = {}; - this.engines = {}; - this.settings = {}; + this.cache = Object.create(null); + this.engines = Object.create(null); + this.settings = Object.create(null); this.defaultConfiguration(); diff --git a/test/app.locals.js b/test/app.locals.js index 657b4b75c79..a4f804fe2a2 100644 --- a/test/app.locals.js +++ b/test/app.locals.js @@ -5,10 +5,11 @@ var express = require('../') describe('app', function(){ describe('.locals', function () { - it('should default object', function () { + it('should default object with null prototype', function () { var app = express() assert.ok(app.locals) assert.strictEqual(typeof app.locals, 'object') + assert.strictEqual(Object.getPrototypeOf(app.locals), null) }) describe('.settings', function () { From 26801a0afdd73258ee3c3685e30d5d4040c1558d Mon Sep 17 00:00:00 2001 From: Evan Hahn Date: Mon, 21 Feb 2022 12:17:50 -0600 Subject: [PATCH 723/889] Use object with null prototype for settings closes #4835 --- lib/application.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/lib/application.js b/lib/application.js index 2a370aa3106..f07cc12a411 100644 --- a/lib/application.js +++ b/lib/application.js @@ -32,7 +32,6 @@ var setPrototypeOf = require('setprototypeof') * @private */ -var hasOwnProperty = Object.prototype.hasOwnProperty var slice = Array.prototype.slice; /** @@ -353,17 +352,7 @@ app.param = function param(name, fn) { app.set = function set(setting, val) { if (arguments.length === 1) { // app.get(setting) - var settings = this.settings - - while (settings && settings !== Object.prototype) { - if (hasOwnProperty.call(settings, setting)) { - return settings[setting] - } - - settings = Object.getPrototypeOf(settings) - } - - return undefined + return this.settings[setting]; } debug('set "%s" to %o', setting, val); From bf91946bd406b0c6f045fe81331de1725e9cee43 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Sat, 4 May 2024 13:53:09 -0700 Subject: [PATCH 724/889] deps: encodeurl@~2.0.0 (#5569) --- History.md | 6 ++++++ lib/response.js | 10 +--------- package.json | 2 +- test/res.location.js | 17 +++-------------- 4 files changed, 11 insertions(+), 24 deletions(-) diff --git a/History.md b/History.md index ac2e7cf719d..1aefd4b9686 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +unreleased +========== + + * deps: encodeurl@~2.0.0 + - Removes encoding of `\`, `|`, and `^` to align better with URL spec + 4.19.2 / 2024-03-25 ========== diff --git a/lib/response.js b/lib/response.js index dd7b3c8201d..29845a7d830 100644 --- a/lib/response.js +++ b/lib/response.js @@ -55,7 +55,6 @@ module.exports = res */ var charsetRegExp = /;\s*charset\s*=/; -var schemaAndHostRegExp = /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?\/\/[^\\\/\?]+/; /** * Set status `code`. @@ -914,14 +913,7 @@ res.location = function location(url) { loc = String(url); } - var m = schemaAndHostRegExp.exec(loc); - var pos = m ? m[0].length + 1 : 0; - - // Only encode after host to avoid invalid encoding which can introduce - // vulnerabilities (e.g. `\\` to `%5C`). - loc = loc.slice(0, pos) + encodeUrl(loc.slice(pos)); - - return this.set('Location', loc); + return this.set('Location', encodeUrl(loc)); }; /** diff --git a/package.json b/package.json index f299d882b0d..88e4206fe67 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.2.0", diff --git a/test/res.location.js b/test/res.location.js index 141ee901310..2e88002625f 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -293,23 +293,12 @@ describe('res', function(){ ); }); - it('should percent encode backslashes in the path', function (done) { + it('should keep backslashes in the path', function (done) { var app = createRedirectServerForDomain('google.com'); testRequestedRedirect( app, 'https://google.com/foo//bar//baz', - 'https://google.com/foo%5Cbar%5Cbaz', - 'google.com', - done - ); - }); - - it('should encode backslashes in the path after the first backslash that triggered path parsing', function (done) { - var app = createRedirectServerForDomain('google.com'); - testRequestedRedirect( - app, - 'https://google.com//@app//l//e.com', - 'https://google.com//@app%5Cl%5Ce.com', + 'https://google.com/foo//bar//baz', 'google.com', done ); @@ -364,7 +353,7 @@ describe('res', function(){ testRequestedRedirect( app, 'file:///etc\\passwd', - 'file:///etc%5Cpasswd', + 'file:///etc\\passwd', '', done ); From 8417c60fcfd7a9523e8783fd3f489d771df1ce44 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Sat, 4 May 2024 17:09:52 -0400 Subject: [PATCH 725/889] skip QUERY method test (#5628) --- test/app.router.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/app.router.js b/test/app.router.js index 12b6c1fa519..d9ddc69afc5 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -35,8 +35,25 @@ describe('app.router', function(){ }) describe('methods', function(){ + function getMajorVersion(versionString) { + return versionString.split('.')[0]; + } + + function shouldSkipQuery(versionString) { + // Temporarily skipping this test on 21 and 22 + // update this implementation to run on those release lines on supported versions once they exist + // upstream tracking https://github.com/nodejs/node/pull/51719 + // express tracking issue: https://github.com/expressjs/express/issues/5615 + var majorsToSkip = { + "21": true, + "22": true + } + return majorsToSkip[getMajorVersion(versionString)] + } + methods.concat('del').forEach(function(method){ if (method === 'connect') return; + if (method === 'query' && shouldSkipQuery(process.versions.node)) return it('should include ' + method.toUpperCase(), function(done){ var app = express(); From b44191eb3de5fcc94b384d7d6028b8c9a0144231 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Sat, 4 May 2024 18:01:42 -0400 Subject: [PATCH 726/889] ignore ETAG query test as well, reuse skip util (#5639) --- test/app.router.js | 18 ++---------------- test/res.send.js | 3 +++ test/support/utils.js | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/test/app.router.js b/test/app.router.js index d9ddc69afc5..ae87092f00f 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -6,6 +6,8 @@ var express = require('../') , assert = require('assert') , methods = require('methods'); +var shouldSkipQuery = require('./support/utils').shouldSkipQuery + describe('app.router', function(){ it('should restore req.params after leaving router', function(done){ var app = express(); @@ -35,22 +37,6 @@ describe('app.router', function(){ }) describe('methods', function(){ - function getMajorVersion(versionString) { - return versionString.split('.')[0]; - } - - function shouldSkipQuery(versionString) { - // Temporarily skipping this test on 21 and 22 - // update this implementation to run on those release lines on supported versions once they exist - // upstream tracking https://github.com/nodejs/node/pull/51719 - // express tracking issue: https://github.com/expressjs/express/issues/5615 - var majorsToSkip = { - "21": true, - "22": true - } - return majorsToSkip[getMajorVersion(versionString)] - } - methods.concat('del').forEach(function(method){ if (method === 'connect') return; if (method === 'query' && shouldSkipQuery(process.versions.node)) return diff --git a/test/res.send.js b/test/res.send.js index c92568db6ad..1e1835f8238 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -7,6 +7,8 @@ var methods = require('methods'); var request = require('supertest'); var utils = require('./support/utils'); +var shouldSkipQuery = require('./support/utils').shouldSkipQuery + describe('res', function(){ describe('.send()', function(){ it('should set body to ""', function(done){ @@ -407,6 +409,7 @@ describe('res', function(){ methods.forEach(function (method) { if (method === 'connect') return; + if (method === 'query' && shouldSkipQuery(process.versions.node)) return it('should send ETag in response to ' + method.toUpperCase() + ' request', function (done) { var app = express(); diff --git a/test/support/utils.js b/test/support/utils.js index 5b4062e0b2a..440a0269bc1 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -16,6 +16,7 @@ exports.shouldHaveBody = shouldHaveBody exports.shouldHaveHeader = shouldHaveHeader exports.shouldNotHaveBody = shouldNotHaveBody exports.shouldNotHaveHeader = shouldNotHaveHeader; +exports.shouldSkipQuery = shouldSkipQuery /** * Assert that a supertest response has a specific body. @@ -70,3 +71,20 @@ function shouldNotHaveHeader(header) { assert.ok(!(header.toLowerCase() in res.headers), 'should not have header ' + header); }; } + +function getMajorVersion(versionString) { + return versionString.split('.')[0]; +} + +function shouldSkipQuery(versionString) { + // Temporarily skipping this test on 21 and 22 + // update this implementation to run on those release lines on supported versions once they exist + // upstream tracking https://github.com/nodejs/node/pull/51719 + // express tracking issue: https://github.com/expressjs/express/issues/5615 + var majorsToSkip = { + "21": true, + "22": true + } + return majorsToSkip[getMajorVersion(versionString)] +} + From 4b9cd2fd0e13519a16bc36e8b4212e7924698b2e Mon Sep 17 00:00:00 2001 From: Mert Can Altin Date: Sun, 5 May 2024 01:15:53 +0300 Subject: [PATCH 727/889] add support Node.js@22 in the CI (#5627) Co-authored-by: Mert Can Altin --- .github/workflows/ci.yml | 4 ++++ appveyor.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f43deeb5385..488d394f622 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,6 +49,7 @@ jobs: - Node.js 19.x - Node.js 20.x - Node.js 21.x + - Node.js 22.x include: - name: Node.js 0.10 @@ -134,6 +135,9 @@ jobs: - name: Node.js 21.x node-version: "21.6" + + - name: Node.js 22.x + node-version: "22.0" steps: - uses: actions/checkout@v4 diff --git a/appveyor.yml b/appveyor.yml index ce26523b3aa..629499bf37c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,6 +23,7 @@ environment: - nodejs_version: "19.9" - nodejs_version: "20.11" - nodejs_version: "21.6" + - nodejs_version: "22.0" cache: - node_modules install: From 700349ffaf6140195a2d5f8173dd732c90c5aacc Mon Sep 17 00:00:00 2001 From: Mert Can Altin Date: Thu, 9 May 2024 00:02:11 +0300 Subject: [PATCH 728/889] doc: add table of contents, tc/triager lists to readme (#5619) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc: updated readme file * doc: updated readme file for doc lint * Update Readme.md Co-authored-by: krzysdz * Update Readme.md Co-authored-by: Ulises Gascón * Update Readme.md Co-authored-by: Ulises Gascón * Update Readme.md Co-authored-by: Christine Belzie <105683440+CBID2@users.noreply.github.com> * repair readme * added Emeritus area * Add @carpasse to the triager team * removed old collaborators * add missing triagers * lint * Update Readme.md Co-authored-by: Jon Church * Update Readme.md Co-authored-by: Jon Church * dedent to fix ToC spacing * fixup! dedent to fix ToC spacing * us @ for jonchurch * format names to use github handles first, single line * added emeritus triagers * edited title * added emeritus team members * added menu head * edited emeritus * Update Readme.md Co-authored-by: Jon Church * Update Readme.md Co-authored-by: Jon Church * edits to TC and anchors * Update Readme.md Co-authored-by: Jon Church * Update Readme.md Co-authored-by: Jon Church * Update Readme.md Co-authored-by: Jon Church * Update Readme.md Co-authored-by: Jon Church * Update Readme.md Co-authored-by: Jon Church * Update Readme.md Co-authored-by: Ulises Gascón * Update Readme.md Co-authored-by: Ulises Gascón * Update Readme.md Co-authored-by: Ulises Gascón * Update Readme.md Co-authored-by: Ulises Gascón * Update Readme.md Co-authored-by: Ulises Gascón --------- Co-authored-by: Mert Can Altin Co-authored-by: krzysdz Co-authored-by: Ulises Gascón Co-authored-by: Christine Belzie <105683440+CBID2@users.noreply.github.com> Co-authored-by: Jon Church --- Readme.md | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index d0f3cf56e6d..01acf9e2f19 100644 --- a/Readme.md +++ b/Readme.md @@ -1,10 +1,27 @@ [![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/) - Fast, unopinionated, minimalist web framework for [Node.js](http://nodejs.org). +**Fast, unopinionated, minimalist web framework for [Node.js](http://nodejs.org).** - [![NPM Version][npm-version-image]][npm-url] - [![NPM Install Size][npm-install-size-image]][npm-install-size-url] - [![NPM Downloads][npm-downloads-image]][npm-downloads-url] +**This project has a [Code of Conduct][].** + +## Table of contents + +* [Installation](#Installation) +* [Features](#Features) +* [Docs & Community](#docs--community) +* [Quick Start](#Quick-Start) +* [Running Tests](#Running-Tests) +* [Philosophy](#Philosophy) +* [Examples](#Examples) +* [Contributing to Express](#Contributing) +* [TC (Technical Committee)](#tc-technical-committee) +* [Triagers](#triagers) +* [License](#license) + + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Install Size][npm-install-size-image]][npm-install-size-url] +[![NPM Downloads][npm-downloads-image]][npm-downloads-url] ```js const express = require('express') @@ -148,6 +165,78 @@ The current lead maintainer is [Douglas Christopher Wilson](https://github.com/d [List of all contributors](https://github.com/expressjs/express/graphs/contributors) +### TC (Technical Committee) + +* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him) +* [jonchurch](https://github.com/jonchurch) - **Jon Church** +* [wesleytodd](https://github.com/wesleytodd) - **Wes Todd** +* [LinusU](https://github.com/LinusU) - **Linus Unnebäck** +* [blakeembrey](https://github.com/blakeembrey) - **Blake Embrey** +* [sheplu](https://github.com/sheplu) - **Jean Burellier** +* [crandmck](https://github.com/crandmck) - **Rand McKinney** + +
        +TC emeriti members + +#### TC emeriti members + + * [dougwilson](https://github.com/dougwilson) - **Douglas Wilson** + * [hacksparrow](https://github.com/hacksparrow) - **Hage Yaapa** + * [jonathanong](https://github.com/jonathanong) - **jongleberry** + * [niftylettuce](https://github.com/niftylettuce) - **niftylettuce** + * [troygoode](https://github.com/troygoode) - **Troy Goode** +
        + + +### Triagers + +* [aravindvnair99](https://github.com/aravindvnair99) - **Aravind Nair** +* [carpasse](https://github.com/carpasse) - **Carlos Serrano** +* [CBID2](https://github.com/CBID2) - **Christine Belzie** +* [enyoghasim](https://github.com/enyoghasim) - **David Enyoghasim** +* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him) +* [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin** +* [0ss](https://github.com/0ss) - **Salah** +* [import-brain](https://github.com/import-brain) - **Eric Cheng** (he/him) +* [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi** +* [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him) +* [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego** +* [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger** + +
        +Triagers emeriti members + +#### Emeritus Triagers + + * [AuggieH](https://github.com/AuggieH) - **Auggie Hudak** + * [G-Rath](https://github.com/G-Rath) - **Gareth Jones** + * [MohammadXroid](https://github.com/MohammadXroid) - **Mohammad Ayashi** + * [NawafSwe](https://github.com/NawafSwe) - **Nawaf Alsharqi** + * [NotMoni](https://github.com/NotMoni) - **Moni** + * [VigneshMurugan](https://github.com/VigneshMurugan) - **Vignesh Murugan** + * [davidmashe](https://github.com/davidmashe) - **David Ashe** + * [digitaIfabric](https://github.com/digitaIfabric) - **David** + * [e-l-i-s-e](https://github.com/e-l-i-s-e) - **Elise Bonner** + * [fed135](https://github.com/fed135) - **Frederic Charette** + * [firmanJS](https://github.com/firmanJS) - **Firman Abdul Hakim** + * [getspooky](https://github.com/getspooky) - **Yasser Ameur** + * [ghinks](https://github.com/ghinks) - **Glenn** + * [ghousemohamed](https://github.com/ghousemohamed) - **Ghouse Mohamed** + * [gireeshpunathil](https://github.com/gireeshpunathil) - **Gireesh Punathil** + * [jake32321](https://github.com/jake32321) - **Jake Reed** + * [jonchurch](https://github.com/jonchurch) - **Jon Church** + * [lekanikotun](https://github.com/lekanikotun) - **Troy Goode** + * [marsonya](https://github.com/marsonya) - **Lekan Ikotun** + * [mastermatt](https://github.com/mastermatt) - **Matt R. Wilson** + * [maxakuru](https://github.com/maxakuru) - **Max Edell** + * [mlrawlings](https://github.com/mlrawlings) - **Michael Rawlings** + * [rodion-arr](https://github.com/rodion-arr) - **Rodion Abdurakhimov** + * [sheplu](https://github.com/sheplu) - **Jean Burellier** + * [tarunyadav1](https://github.com/tarunyadav1) - **Tarun yadav** + * [tunniclm](https://github.com/tunniclm) - **Mike Tunnicliffe** +
        + + ## License [MIT](LICENSE) @@ -164,3 +253,4 @@ The current lead maintainer is [Douglas Christopher Wilson](https://github.com/d [npm-install-size-url]: https://packagephobia.com/result?p=express [npm-url]: https://npmjs.org/package/express [npm-version-image]: https://badgen.net/npm/v/express +[Code of Conduct]: https://github.com/expressjs/express/blob/master/Code-Of-Conduct.md From 897290b68549034fb12f7bbb2cf6dae6c6f36096 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Fri, 10 May 2024 16:09:39 -0700 Subject: [PATCH 729/889] List and sort all projects, add captains --- Contributing.md | 76 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/Contributing.md b/Contributing.md index 4262b0f20db..46289af6137 100644 --- a/Contributing.md +++ b/Contributing.md @@ -63,13 +63,13 @@ compromise among committers be the default resolution mechanism. Anyone can become a triager! Read more about the process of being a triager in [the triage process document](Triager-Guide.md). -Currently, any existing [organization member](https://github.com/orgs/expressjs/people) can nominate -a new triager. If you are interested in becoming a triager, our best advice is to actively participate +Currently, any existing [organization member](https://github.com/orgs/expressjs/people) can nominate +a new triager. If you are interested in becoming a triager, our best advice is to actively participate in the community by helping triaging issues and pull requests. As well we recommend -to engage in other community activities like attending the TC meetings, and participating in the Slack +to engage in other community activities like attending the TC meetings, and participating in the Slack discussions. -You can also reach out to any of the [organization members](https://github.com/orgs/expressjs/people) +You can also reach out to any of the [organization members](https://github.com/orgs/expressjs/people) if you have questions or need guidance. ## Becoming a Committer @@ -139,28 +139,70 @@ the project, their GitHub handle and npm username (if different). The PR will re at least 2 approvals from TC members and 2 weeks hold time to allow for comment and/or dissent. When the PR is merged, a TC member will add them to the proper GitHub/npm groups. -### Current Project Captains +### Active Projects and Captains -- `expressjs/express`: @wesleytodd -- `expressjs/discussions`: @wesleytodd -- `expressjs/expressjs.com`: @crandmck, @jonchurch +- `expressjs/badgeboard`: @wesleytodd +- `expressjs/basic-auth-connect`: N/A - `expressjs/body-parser`: @wesleytodd, @jonchurch -- `expressjs/multer`: @LinusU -- `expressjs/morgan`: @jonchurch +- `expressjs/compression`: N/A +- `expressjs/connect-multiparty`: N/A - `expressjs/cookie-parser`: @wesleytodd +- `expressjs/cookie-session`: N/A - `expressjs/cors`: @jonchurch +- `expressjs/discussions`: @wesleytodd +- `expressjs/errorhandler`: N/A +- `expressjs/express-paginate`: N/A +- `expressjs/express`: @wesleytodd +- `expressjs/expressjs.com`: @crandmck, @jonchurch +- `expressjs/flash`: N/A - `expressjs/generator`: @wesleytodd +- `expressjs/method-override`: N/A +- `expressjs/morgan`: @jonchurch +- `expressjs/multer`: @LinusU +- `expressjs/response-time`: @blakeembrey +- `expressjs/serve-favicon`: N/A +- `expressjs/serve-index`: N/A +- `expressjs/serve-static`: N/A +- `expressjs/session`: N/A - `expressjs/statusboard`: @wesleytodd -- `pillarjs/encodeurl`: @blakeembrey -- `pillarjs/path-to-regexp`: @blakeembrey -- `pillarjs/router`: @dougwilson, @wesleytodd -- `pillarjs/finalhandler`: @wesleytodd -- `pillarjs/request`: @wesleytodd -- `jshttp/http-errors`: @wesleytodd, @jonchurch +- `expressjs/timeout`: N/A +- `expressjs/vhost`: N/A +- `jshttp/accepts`: @blakeembrey +- `jshttp/basic-auth`: @blakeembrey +- `jshttp/compressible`: @blakeembrey +- `jshttp/content-disposition`: @blakeembrey +- `jshttp/content-type`: @blakeembrey - `jshttp/cookie`: @wesleytodd +- `jshttp/etag`: @blakeembrey +- `jshttp/forwarded`: @blakeembrey +- `jshttp/fresh`: @blakeembrey +- `jshttp/http-assert`: @wesleytodd, @jonchurch +- `jshttp/http-errors`: @wesleytodd, @jonchurch +- `jshttp/media-typer`: @blakeembrey +- `jshttp/methods`: @blakeembrey +- `jshttp/mime-db`: @blakeembrey +- `jshttp/mime-types`: @blakeembrey +- `jshttp/negotiator`: @blakeembrey - `jshttp/on-finished`: @wesleytodd -- `jshttp/forwarded`: @wesleytodd +- `jshttp/on-headers`: @blakeembrey - `jshttp/proxy-addr`: @wesleytodd +- `jshttp/range-parser`: @blakeembrey +- `jshttp/statuses`: @blakeembrey +- `jshttp/type-is`: @blakeembrey +- `jshttp/vary`: @blakeembrey +- `pillarjs/cookies`: @blakeembrey +- `pillarjs/csrf`: N/A +- `pillarjs/encodeurl`: @blakeembrey +- `pillarjs/finalhandler`: @wesleytodd +- `pillarjs/hbs`: N/A +- `pillarjs/multiparty`: @blakeembrey +- `pillarjs/parseurl`: @blakeembrey +- `pillarjs/path-to-regexp`: @blakeembrey +- `pillarjs/request`: @wesleytodd +- `pillarjs/resolve-path`: @blakeembrey +- `pillarjs/router`: @blakeembrey +- `pillarjs/send`: @blakeembrey +- `pillarjs/understanding-csrf`: N/A ### Current Initiative Captains From a7d6d29ed3a8eeb91954447696d1a28b982702a4 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 13 May 2024 16:12:36 -0700 Subject: [PATCH 730/889] Add @UlisesGascon to mime repos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ulises Gascón --- Contributing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Contributing.md b/Contributing.md index 46289af6137..292fdc40b71 100644 --- a/Contributing.md +++ b/Contributing.md @@ -180,8 +180,8 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - `jshttp/http-errors`: @wesleytodd, @jonchurch - `jshttp/media-typer`: @blakeembrey - `jshttp/methods`: @blakeembrey -- `jshttp/mime-db`: @blakeembrey -- `jshttp/mime-types`: @blakeembrey +- `jshttp/mime-db`: @blakeembrey, @UlisesGascon +- `jshttp/mime-types`: @blakeembrey, @UlisesGascon - `jshttp/negotiator`: @blakeembrey - `jshttp/on-finished`: @wesleytodd - `jshttp/on-headers`: @blakeembrey From ee40a881f5d8cb4ce71bc45262fde8e4b7640d05 Mon Sep 17 00:00:00 2001 From: Wes Date: Mon, 20 Feb 2017 17:36:39 -0600 Subject: [PATCH 731/889] call callback once on listen error --- lib/application.js | 14 ++++++++++---- package.json | 1 + test/app.listen.js | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/application.js b/lib/application.js index f07cc12a411..43c9f34b062 100644 --- a/lib/application.js +++ b/lib/application.js @@ -24,6 +24,7 @@ var compileTrust = require('./utils').compileTrust; var flatten = require('array-flatten').flatten var merge = require('utils-merge'); var resolve = require('path').resolve; +var once = require('once') var Router = require('router'); var setPrototypeOf = require('setprototypeof') @@ -605,10 +606,15 @@ app.render = function render(name, options, callback) { * @public */ -app.listen = function listen() { - var server = http.createServer(this); - return server.listen.apply(server, arguments); -}; +app.listen = function listen () { + var server = http.createServer(this) + var args = Array.prototype.slice.call(arguments) + if (typeof args[args.length - 1] === 'function') { + var done = args[args.length - 1] = once(args[args.length - 1]) + server.once('error', done) + } + return server.listen.apply(server, args) +} /** * Log error using console.error. diff --git a/package.json b/package.json index 5a8f978e1c2..d3e2f0a1909 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "methods": "~1.1.2", "mime-types": "~2.1.34", "on-finished": "2.4.1", + "once": "1.4.0", "parseurl": "~1.3.3", "path-is-absolute": "1.0.1", "proxy-addr": "~2.0.7", diff --git a/test/app.listen.js b/test/app.listen.js index 5b150063b9e..7e7e731a3b8 100644 --- a/test/app.listen.js +++ b/test/app.listen.js @@ -1,6 +1,7 @@ 'use strict' var express = require('../') +var assert = require('assert') describe('app.listen()', function(){ it('should wrap with an HTTP server', function(done){ @@ -10,4 +11,17 @@ describe('app.listen()', function(){ server.close(done) }); }) + it('should callback on HTTP server errors', function (done) { + var app1 = express() + var app2 = express() + + var server1 = app1.listen(0, function (err) { + assert(!err) + app2.listen(server1.address().port, function (err) { + assert(err.code === 'EADDRINUSE') + server1.close() + done() + }) + }) + }) }) From 2803a2b35ae37209a44a8d3b19c141482fd57437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 23 May 2024 00:29:16 +0200 Subject: [PATCH 732/889] docs: add @UlisesGascon as captain for cookie-parser (#5666) --- Contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index 292fdc40b71..1654cee02f2 100644 --- a/Contributing.md +++ b/Contributing.md @@ -146,7 +146,7 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - `expressjs/body-parser`: @wesleytodd, @jonchurch - `expressjs/compression`: N/A - `expressjs/connect-multiparty`: N/A -- `expressjs/cookie-parser`: @wesleytodd +- `expressjs/cookie-parser`: @wesleytodd, @UlisesGascon - `expressjs/cookie-session`: N/A - `expressjs/cors`: @jonchurch - `expressjs/discussions`: @wesleytodd From 689073d657b646b5d01448a6a69f88016f40761b Mon Sep 17 00:00:00 2001 From: Chris de Almeida Date: Wed, 5 Jun 2024 16:25:58 -0500 Subject: [PATCH 733/889] =?UTF-8?q?=E2=9C=A8=20bring=20back=20query=20test?= =?UTF-8?q?s=20for=20node=2021=20(#5690)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 11 +---------- .npmrc | 1 + test/support/utils.js | 3 +-- 3 files changed, 3 insertions(+), 12 deletions(-) create mode 100644 .npmrc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 488d394f622..02137e595ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -135,7 +135,7 @@ jobs: - name: Node.js 21.x node-version: "21.6" - + - name: Node.js 22.x node-version: "22.0" @@ -148,15 +148,6 @@ jobs: nvm install --default ${{ matrix.node-version }} dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" - - name: Configure npm - run: | - npm config set loglevel error - if [[ "$(npm config get package-lock)" == "true" ]]; then - npm config set package-lock false - else - npm config set shrinkwrap false - fi - - name: Install npm module(s) ${{ matrix.npm-i }} run: npm install --save-dev ${{ matrix.npm-i }} if: matrix.npm-i != '' diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000000..43c97e719a5 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/test/support/utils.js b/test/support/utils.js index 440a0269bc1..a4d9fb8b548 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -77,12 +77,11 @@ function getMajorVersion(versionString) { } function shouldSkipQuery(versionString) { - // Temporarily skipping this test on 21 and 22 + // Temporarily skipping this test on 22 // update this implementation to run on those release lines on supported versions once they exist // upstream tracking https://github.com/nodejs/node/pull/51719 // express tracking issue: https://github.com/expressjs/express/issues/5615 var majorsToSkip = { - "21": true, "22": true } return majorsToSkip[getMajorVersion(versionString)] From f42b160bbc0c391c06cad1c6c37eea5305f78cd2 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Fri, 7 Jun 2024 19:48:48 -0400 Subject: [PATCH 734/889] [v4] Deprecate `res.clearCookie` accepting `options.maxAge` and `options.expires` (#5672) * add deprecation notice for res.clearCookie maxAge/expires * update History.md for clearCookie deprecation change * add tests to codify deprecated behavior Co-authored-by: Chris de Almeida --------- Co-authored-by: Chris de Almeida --- History.md | 2 ++ lib/response.js | 8 ++++++++ test/res.clearCookie.js | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/History.md b/History.md index 1aefd4b9686..c02b24ffba2 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ unreleased * deps: encodeurl@~2.0.0 - Removes encoding of `\`, `|`, and `^` to align better with URL spec + * Deprecate passing `options.maxAge` and `options.expires` to `res.clearCookie` + - Will be ignored in v5, clearCookie will set a cookie with an expires in the past to instruct clients to delete the cookie 4.19.2 / 2024-03-25 ========== diff --git a/lib/response.js b/lib/response.js index 29845a7d830..68d969ff05b 100644 --- a/lib/response.js +++ b/lib/response.js @@ -822,6 +822,14 @@ res.get = function(field){ */ res.clearCookie = function clearCookie(name, options) { + if (options) { + if (options.maxAge) { + deprecate('res.clearCookie: Passing "options.maxAge" is deprecated. In v5.0.0 of Express, this option will be ignored, as res.clearCookie will automatically set cookies to expire immediately. Please update your code to omit this option.'); + } + if (options.expires) { + deprecate('res.clearCookie: Passing "options.expires" is deprecated. In v5.0.0 of Express, this option will be ignored, as res.clearCookie will automatically set cookies to expire immediately. Please update your code to omit this option.'); + } + } var opts = merge({ expires: new Date(1), path: '/' }, options); return this.cookie(name, '', opts); diff --git a/test/res.clearCookie.js b/test/res.clearCookie.js index fc0cfb99a3d..3d8a6a5a81f 100644 --- a/test/res.clearCookie.js +++ b/test/res.clearCookie.js @@ -32,5 +32,37 @@ describe('res', function(){ .expect('Set-Cookie', 'sid=; Path=/admin; Expires=Thu, 01 Jan 1970 00:00:00 GMT') .expect(200, done) }) + + it('should set expires when passed', function(done) { + var expiresAt = new Date() + var app = express(); + + app.use(function(req, res){ + res.clearCookie('sid', { expires: expiresAt }).end(); + }); + + request(app) + .get('/') + .expect('Set-Cookie', 'sid=; Path=/; Expires=' + expiresAt.toUTCString() ) + .expect(200, done) + }) + + it('should set both maxAge and expires when passed', function(done) { + var maxAgeInMs = 10000 + var expiresAt = new Date() + var expectedExpires = new Date(expiresAt.getTime() + maxAgeInMs) + var app = express(); + + app.use(function(req, res){ + res.clearCookie('sid', { expires: expiresAt, maxAge: maxAgeInMs }).end(); + }); + + request(app) + .get('/') + // yes, this is the behavior. When we set a max-age, we also set expires to a date 10 sec ahead of expires + // even if we set max-age only, we will also set an expires 10 sec in the future + .expect('Set-Cookie', 'sid=; Max-Age=10; Path=/; Expires=' + expectedExpires.toUTCString()) + .expect(200, done) + }) }) }) From 61421a8c0c2abf011868d90df93813992e3c7563 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Sat, 8 Jun 2024 23:25:42 -0400 Subject: [PATCH 735/889] skip QUERY tests for Node 21 only, still not supported (#5695) * skip QUERY tests for Node 21 only, still not supported QUERY support has now landed in Node 22.2.0, but is still not supported in 21.7.3 QUERY showed up in http.METHODS in 21.7.2. Only Node versions after that will attempt to run tests for it, based on the way we dynamically test members of the http.METHODS array from Node * update CI to run on 21.7 and 22.2 --- .github/workflows/ci.yml | 4 ++-- test/app.router.js | 4 +++- test/res.send.js | 4 +++- test/support/utils.js | 11 ++++------- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02137e595ec..920db416d61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,10 +134,10 @@ jobs: node-version: "20.11" - name: Node.js 21.x - node-version: "21.6" + node-version: "21.7" - name: Node.js 22.x - node-version: "22.0" + node-version: "22.2" steps: - uses: actions/checkout@v4 diff --git a/test/app.router.js b/test/app.router.js index ae87092f00f..707333f0432 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -39,9 +39,11 @@ describe('app.router', function(){ describe('methods', function(){ methods.concat('del').forEach(function(method){ if (method === 'connect') return; - if (method === 'query' && shouldSkipQuery(process.versions.node)) return it('should include ' + method.toUpperCase(), function(done){ + if (method === 'query' && shouldSkipQuery(process.versions.node)) { + this.skip() + } var app = express(); app[method]('/foo', function(req, res){ diff --git a/test/res.send.js b/test/res.send.js index 1e1835f8238..b4cf68a7df6 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -409,9 +409,11 @@ describe('res', function(){ methods.forEach(function (method) { if (method === 'connect') return; - if (method === 'query' && shouldSkipQuery(process.versions.node)) return it('should send ETag in response to ' + method.toUpperCase() + ' request', function (done) { + if (method === 'query' && shouldSkipQuery(process.versions.node)) { + this.skip() + } var app = express(); app[method]('/', function (req, res) { diff --git a/test/support/utils.js b/test/support/utils.js index a4d9fb8b548..5ad4ca98410 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -77,13 +77,10 @@ function getMajorVersion(versionString) { } function shouldSkipQuery(versionString) { - // Temporarily skipping this test on 22 - // update this implementation to run on those release lines on supported versions once they exist - // upstream tracking https://github.com/nodejs/node/pull/51719 + // Skipping HTTP QUERY tests on Node 21, it is reported in http.METHODS on 21.7.2 but not supported + // update this implementation to run on supported versions of 21 once they exist + // upstream tracking https://github.com/nodejs/node/issues/51562 // express tracking issue: https://github.com/expressjs/express/issues/5615 - var majorsToSkip = { - "22": true - } - return majorsToSkip[getMajorVersion(versionString)] + return Number(getMajorVersion(versionString)) === 21 } From 6d084715ba6ca5301e9ac1efe4309e555973b364 Mon Sep 17 00:00:00 2001 From: Chris de Almeida Date: Mon, 10 Jun 2024 16:19:11 -0500 Subject: [PATCH 736/889] =?UTF-8?q?=F0=9F=93=9D=20update=20people,=20add?= =?UTF-8?q?=20ctcpip=20to=20TC=20(#5683)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 01acf9e2f19..365c7b6104f 100644 --- a/Readme.md +++ b/Readme.md @@ -161,8 +161,6 @@ $ npm test The original author of Express is [TJ Holowaychuk](https://github.com/tj) -The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) - [List of all contributors](https://github.com/expressjs/express/graphs/contributors) ### TC (Technical Committee) @@ -174,6 +172,7 @@ The current lead maintainer is [Douglas Christopher Wilson](https://github.com/d * [blakeembrey](https://github.com/blakeembrey) - **Blake Embrey** * [sheplu](https://github.com/sheplu) - **Jean Burellier** * [crandmck](https://github.com/crandmck) - **Rand McKinney** +* [ctcpip](https://github.com/ctcpip) - **Chris de Almeida**
        TC emeriti members From 4cf7eed927d3ccd3f1d0c9a14d562ec0a1635e86 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Wed, 26 Jun 2024 18:23:19 -0400 Subject: [PATCH 737/889] remove minor version pinning from ci (#5722) --- .github/workflows/ci.yml | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 920db416d61..09004fec751 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,83 +61,83 @@ jobs: npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - name: io.js 1.x - node-version: "1.8" + node-version: "1" npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - name: io.js 2.x - node-version: "2.5" + node-version: "2" npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - name: io.js 3.x - node-version: "3.3" + node-version: "3" npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - name: Node.js 4.x - node-version: "4.9" + node-version: "4" npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - name: Node.js 5.x - node-version: "5.12" + node-version: "5" npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - name: Node.js 6.x - node-version: "6.17" + node-version: "6" npm-i: mocha@6.2.2 nyc@14.1.1 supertest@3.4.2 - name: Node.js 7.x - node-version: "7.10" + node-version: "7" npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6 - name: Node.js 8.x - node-version: "8.17" + node-version: "8" npm-i: mocha@7.2.0 nyc@14.1.1 - name: Node.js 9.x - node-version: "9.11" + node-version: "9" npm-i: mocha@7.2.0 nyc@14.1.1 - name: Node.js 10.x - node-version: "10.24" + node-version: "10" npm-i: mocha@8.4.0 - name: Node.js 11.x - node-version: "11.15" + node-version: "11" npm-i: mocha@8.4.0 - name: Node.js 12.x - node-version: "12.22" + node-version: "12" npm-i: mocha@9.2.2 - name: Node.js 13.x - node-version: "13.14" + node-version: "13" npm-i: mocha@9.2.2 - name: Node.js 14.x - node-version: "14.20" + node-version: "14" - name: Node.js 15.x - node-version: "15.14" + node-version: "15" - name: Node.js 16.x - node-version: "16.20" + node-version: "16" - name: Node.js 17.x - node-version: "17.9" + node-version: "17" - name: Node.js 18.x - node-version: "18.19" + node-version: "18" - name: Node.js 19.x - node-version: "19.9" + node-version: "19" - name: Node.js 20.x - node-version: "20.11" + node-version: "20" - name: Node.js 21.x - node-version: "21.7" + node-version: "21" - name: Node.js 22.x - node-version: "22.2" + node-version: "22" steps: - uses: actions/checkout@v4 From 2ec589c1133e2eec29a951b4976c50db638f7dd5 Mon Sep 17 00:00:00 2001 From: S M Mahmudul Hasan Date: Thu, 18 Jul 2024 02:44:03 +0600 Subject: [PATCH 738/889] Fix Contributor Covenant link definition reference in attribution section (#5762) --- Code-Of-Conduct.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code-Of-Conduct.md b/Code-Of-Conduct.md index bbb8996a659..ca4c6b31468 100644 --- a/Code-Of-Conduct.md +++ b/Code-Of-Conduct.md @@ -127,7 +127,7 @@ project community. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant, version 2.0](cc-20-doc). +This Code of Conduct is adapted from the [Contributor Covenant, version 2.0][cc-20-doc]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). From 088856c3f82d5101d2831db8516e1ec991eb426a Mon Sep 17 00:00:00 2001 From: ctcpip Date: Thu, 25 Jul 2024 12:30:07 -0500 Subject: [PATCH 739/889] =?UTF-8?q?=F0=9F=92=9A=20add=20legacy=20CI,=20cle?= =?UTF-8?q?an=20up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 26 ++--- .github/workflows/legacy.yml | 182 +++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/legacy.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0575f075e73..7718a2fa9e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,24 +10,10 @@ jobs: strategy: fail-fast: false matrix: - name: - - Node.js 18.x - - Node.js 19.x - - Node.js 20.x - - Node.js 21.x + node-version: [18, 19, 20, 21, 22] + # Node.js release schedule: https://nodejs.org/en/about/releases/ - include: - - name: Node.js 18.x - node-version: "18.19" - - - name: Node.js 19.x - node-version: "19.9" - - - name: Node.js 20.x - node-version: "20.11" - - - name: Node.js 21.x - node-version: "21.6" + name: Node.js ${{ matrix.node-version }} steps: - uses: actions/checkout@v4 @@ -70,7 +56,7 @@ jobs: shell: bash run: | npm run test-ci - cp coverage/lcov.info "coverage/${{ matrix.name }}.lcov" + cp coverage/lcov.info "coverage/${{ matrix.node-version }}.lcov" - name: Lint code if: steps.list_env.outputs.eslint != '' @@ -78,9 +64,9 @@ jobs: - name: Collect code coverage run: | - mv ./coverage "./${{ matrix.name }}" + mv ./coverage "./${{ matrix.node-version }}" mkdir ./coverage - mv "./${{ matrix.name }}" "./coverage/${{ matrix.name }}" + mv "./${{ matrix.node-version }}" "./coverage/${{ matrix.node-version }}" - name: Upload code coverage uses: actions/upload-artifact@v3 diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml new file mode 100644 index 00000000000..5bf3b69a9fb --- /dev/null +++ b/.github/workflows/legacy.yml @@ -0,0 +1,182 @@ +name: legacy + +on: +- pull_request +- push + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + name: + - Node.js 4.0 + - Node.js 4.x + - Node.js 5.x + - Node.js 6.x + - Node.js 7.x + - Node.js 8.x + - Node.js 9.x + - Node.js 10.x + - Node.js 11.x + - Node.js 12.x + - Node.js 13.x + - Node.js 14.x + - Node.js 15.x + - Node.js 16.x + - Node.js 17.x + + include: + - name: Node.js 4.0 + node-version: "4.0" + npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 + + - name: Node.js 4.x + node-version: "4.9" + npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 + + - name: Node.js 5.x + node-version: "5.12" + npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 + + - name: Node.js 6.x + node-version: "6.17" + npm-i: mocha@6.2.2 nyc@14.1.1 supertest@3.4.2 + + - name: Node.js 7.x + node-version: "7.10" + npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6 + + - name: Node.js 8.x + node-version: "8.17" + npm-i: mocha@7.2.0 nyc@14.1.1 + + - name: Node.js 9.x + node-version: "9.11" + npm-i: mocha@7.2.0 nyc@14.1.1 + + - name: Node.js 10.x + node-version: "10.24" + npm-i: mocha@8.4.0 + + - name: Node.js 11.x + node-version: "11.15" + npm-i: mocha@8.4.0 + + - name: Node.js 12.x + node-version: "12.22" + npm-i: mocha@9.2.2 + + - name: Node.js 13.x + node-version: "13.14" + npm-i: mocha@9.2.2 + + - name: Node.js 14.x + node-version: "14.20" + + - name: Node.js 15.x + node-version: "15.14" + + - name: Node.js 16.x + node-version: "16.20" + + - name: Node.js 17.x + node-version: "17.9" + + steps: + - uses: actions/checkout@v4 + + - name: Install Node.js ${{ matrix.node-version }} + shell: bash -eo pipefail -l {0} + run: | + nvm install --default ${{ matrix.node-version }} + dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" + + - name: Configure npm + run: | + npm config set loglevel error + if [[ "$(npm config get package-lock)" == "true" ]]; then + npm config set package-lock false + else + npm config set shrinkwrap false + fi + + - name: Install npm module(s) ${{ matrix.npm-i }} + run: npm install --save-dev ${{ matrix.npm-i }} + if: matrix.npm-i != '' + + - name: Remove non-test dependencies + run: npm rm --silent --save-dev connect-redis + + - name: Setup Node.js version-specific dependencies + shell: bash + run: | + # eslint for linting + # - remove on Node.js < 12 + if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then + node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ + grep -E '^eslint(-|$)' | \ + sort -r | \ + xargs -n1 npm rm --silent --save-dev + fi + + - name: Install Node.js dependencies + run: npm install + + - name: List environment + id: list_env + shell: bash + run: | + echo "node@$(node -v)" + echo "npm@$(npm -v)" + npm -s ls ||: + (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT" + + - name: Run tests + shell: bash + run: | + npm run test-ci + cp coverage/lcov.info "coverage/${{ matrix.name }}.lcov" + + - name: Lint code + if: steps.list_env.outputs.eslint != '' + run: npm run lint + + - name: Collect code coverage + run: | + mv ./coverage "./${{ matrix.name }}" + mkdir ./coverage + mv "./${{ matrix.name }}" "./coverage/${{ matrix.name }}" + + - name: Upload code coverage + uses: actions/upload-artifact@v3 + with: + name: coverage + path: ./coverage + retention-days: 1 + + coverage: + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install lcov + shell: bash + run: sudo apt-get -y install lcov + + - name: Collect coverage reports + uses: actions/download-artifact@v3 + with: + name: coverage + path: ./coverage + + - name: Merge coverage reports + shell: bash + run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./coverage/lcov.info + + - name: Upload coverage report + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} From f4bd86ed361ea9710ed0f7b4634e66c8e3b88b40 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Sat, 27 Jul 2024 14:15:55 -0400 Subject: [PATCH 740/889] Replace Appveyor windows testing with GHA (#5599) This PR moves us off of Appveyor for windows testing. We are now doing windows/linux testing on GHA. With the exception of iojs, which we are only testing on Linux and have split out to it's own workflow. We have also added npm-shrinkwrap.json to our gitignore, in order to not have to configure npm in CI to ignore it. If it's never checked in, it shouldn't exist in CI as you need to go out of your way to create it w/ npm. --- .github/workflows/ci.yml | 288 ++++++++++++++++--------------------- .github/workflows/iojs.yml | 69 +++++++++ .gitignore | 1 + package.json | 4 +- 4 files changed, 197 insertions(+), 165 deletions(-) create mode 100644 .github/workflows/iojs.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09004fec751..b3ddd6b23ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,187 +20,149 @@ concurrency: cancel-in-progress: true jobs: - test: + lint: + name: Lint runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js {{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + persist-credentials: false + + - name: Install dependencies + run: npm install --ignore-scripts --only=dev + + - name: Run lint + run: npm run lint + + test: + name: Run tests strategy: fail-fast: false matrix: - name: - - Node.js 0.10 - - Node.js 0.12 - - io.js 1.x - - io.js 2.x - - io.js 3.x - - Node.js 4.x - - Node.js 5.x - - Node.js 6.x - - Node.js 7.x - - Node.js 8.x - - Node.js 9.x - - Node.js 10.x - - Node.js 11.x - - Node.js 12.x - - Node.js 13.x - - Node.js 14.x - - Node.js 15.x - - Node.js 16.x - - Node.js 17.x - - Node.js 18.x - - Node.js 19.x - - Node.js 20.x - - Node.js 21.x - - Node.js 22.x - + os: [ubuntu-latest, windows-latest] + node-version: + - "0.10" + - "0.12" + - "4" + - "5" + - "6" + - "7" + - "8" + - "9" + - "10" + - "11" + - "12" + - "13" + - "14" + - "15" + - "16" + - "17" + - "18" + - "19" + - "20" + - "21" + - "22" + # Use supported versions of our testing tools under older versions of Node + # Install npm in some specific cases where we need to include: - - name: Node.js 0.10 - node-version: "0.10" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: Node.js 0.12 - node-version: "0.12" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: io.js 1.x - node-version: "1" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: io.js 2.x - node-version: "2" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: io.js 3.x - node-version: "3" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: Node.js 4.x - node-version: "4" - npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - - - name: Node.js 5.x - node-version: "5" - npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - - - name: Node.js 6.x - node-version: "6" - npm-i: mocha@6.2.2 nyc@14.1.1 supertest@3.4.2 - - - name: Node.js 7.x - node-version: "7" - npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6 - - - name: Node.js 8.x - node-version: "8" - npm-i: mocha@7.2.0 nyc@14.1.1 + - node-version: "0.10" + npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0" + # Npm isn't being installed on windows w/ setup-node for + # 0.10 and 0.12, which will end up choking when npm uses es6 + npm-version: "npm@2.15.1" - - name: Node.js 9.x - node-version: "9" - npm-i: mocha@7.2.0 nyc@14.1.1 + - node-version: "0.12" + npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0" + npm-version: "npm@2.15.11" - - name: Node.js 10.x - node-version: "10" - npm-i: mocha@8.4.0 + - node-version: "4" + npm-i: "mocha@5.2.0 nyc@11.9.0 supertest@3.4.2" - - name: Node.js 11.x - node-version: "11" - npm-i: mocha@8.4.0 + - node-version: "5" + npm-i: "mocha@5.2.0 nyc@11.9.0 supertest@3.4.2" + # fixes https://github.com/npm/cli/issues/681 + npm-version: "npm@3.10.10" - - name: Node.js 12.x - node-version: "12" - npm-i: mocha@9.2.2 + - node-version: "6" + npm-i: "mocha@6.2.2 nyc@14.1.1 supertest@3.4.2" - - name: Node.js 13.x - node-version: "13" - npm-i: mocha@9.2.2 + - node-version: "7" + npm-i: "mocha@6.2.2 nyc@14.1.1 supertest@6.1.6" - - name: Node.js 14.x - node-version: "14" + - node-version: "8" + npm-i: "mocha@7.2.0 nyc@14.1.1" - - name: Node.js 15.x - node-version: "15" + - node-version: "9" + npm-i: "mocha@7.2.0 nyc@14.1.1" - - name: Node.js 16.x - node-version: "16" + - node-version: "10" + npm-i: "mocha@8.4.0" - - name: Node.js 17.x - node-version: "17" + - node-version: "11" + npm-i: "mocha@8.4.0" - - name: Node.js 18.x - node-version: "18" + - node-version: "12" + npm-i: "mocha@9.2.2" - - name: Node.js 19.x - node-version: "19" - - - name: Node.js 20.x - node-version: "20" - - - name: Node.js 21.x - node-version: "21" - - - name: Node.js 22.x - node-version: "22" + - node-version: "13" + npm-i: "mocha@9.2.2" + runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 - - - name: Install Node.js ${{ matrix.node-version }} - shell: bash -eo pipefail -l {0} - run: | - nvm install --default ${{ matrix.node-version }} - dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" - - - name: Install npm module(s) ${{ matrix.npm-i }} - run: npm install --save-dev ${{ matrix.npm-i }} - if: matrix.npm-i != '' - - - name: Remove non-test dependencies - run: npm rm --silent --save-dev connect-redis - - - name: Setup Node.js version-specific dependencies - shell: bash - run: | - # eslint for linting - # - remove on Node.js < 12 - if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then - node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ - grep -E '^eslint(-|$)' | \ - sort -r | \ - xargs -n1 npm rm --silent --save-dev - fi - - - name: Install Node.js dependencies - run: npm install - - - name: List environment - id: list_env - shell: bash - run: | - echo "node@$(node -v)" - echo "npm@$(npm -v)" - npm -s ls ||: - (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT" - - - name: Run tests - shell: bash - run: | - npm run test-ci - cp coverage/lcov.info "coverage/${{ matrix.name }}.lcov" - - - name: Lint code - if: steps.list_env.outputs.eslint != '' - run: npm run lint - - - name: Collect code coverage - run: | - mv ./coverage "./${{ matrix.name }}" - mkdir ./coverage - mv "./${{ matrix.name }}" "./coverage/${{ matrix.name }}" - - - name: Upload code coverage - uses: actions/upload-artifact@v3 - with: - name: coverage - path: ./coverage - retention-days: 1 + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Npm version fixes + if: ${{matrix.npm-version != ''}} + run: npm install -g ${{ matrix.npm-version }} + + - name: Configure npm loglevel + run: | + npm config set loglevel error + shell: bash + + - name: Install dependencies + run: npm install + + - name: Install Node version specific dev deps + if: ${{ matrix.npm-i != '' }} + run: npm install --save-dev ${{ matrix.npm-i }} + + - name: Remove non-test dependencies + run: npm rm --silent --save-dev connect-redis + + - name: Output Node and NPM versions + run: | + echo "Node.js version: $(node -v)" + echo "NPM version: $(npm -v)" + + - name: Run tests + shell: bash + run: | + npm run test-ci + cp coverage/lcov.info "coverage/${{ matrix.node-version }}.lcov" + + - name: Collect code coverage + run: | + mv ./coverage "./${{ matrix.node-version }}" + mkdir ./coverage + mv "./${{ matrix.node-version }}" "./coverage/${{ matrix.node-version }}" + + - name: Upload code coverage + uses: actions/upload-artifact@v3 + with: + name: coverage + path: ./coverage + retention-days: 1 coverage: needs: test diff --git a/.github/workflows/iojs.yml b/.github/workflows/iojs.yml new file mode 100644 index 00000000000..c1268abd689 --- /dev/null +++ b/.github/workflows/iojs.yml @@ -0,0 +1,69 @@ +name: iojs-ci + +on: + push: + branches: + - master + - '4.x' + paths-ignore: + - '*.md' + pull_request: + paths-ignore: + - '*.md' + +concurrency: + group: "${{ github.workflow }} ✨ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}" + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: ["1.8", "2.5", "3.3"] + include: + - node-version: "1.8" + npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0" + - node-version: "2.5" + npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0" + - node-version: "3.3" + npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0" + + steps: + - uses: actions/checkout@v4 + + - name: Install iojs ${{ matrix.node-version }} + shell: bash -eo pipefail -l {0} + run: | + nvm install --default ${{ matrix.node-version }} + dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" + + - name: Configure npm + run: | + npm config set loglevel error + npm config set shrinkwrap false + + - name: Install npm module(s) ${{ matrix.npm-i }} + run: npm install --save-dev ${{ matrix.npm-i }} + if: matrix.npm-i != '' + + - name: Remove non-test dependencies + run: npm rm --silent --save-dev connect-redis + + - name: Install Node.js dependencies + run: npm install + + - name: List environment + id: list_env + shell: bash + run: | + echo "node@$(node -v)" + echo "npm@$(npm -v)" + npm -s ls ||: + (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT" + + - name: Run tests + shell: bash + run: npm run test + diff --git a/.gitignore b/.gitignore index 3a673d9cc09..1bd5c02b28b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # npm node_modules package-lock.json +npm-shrinkwrap.json *.log *.gz diff --git a/package.json b/package.json index 88e4206fe67..71781e11d64 100644 --- a/package.json +++ b/package.json @@ -91,8 +91,8 @@ "scripts": { "lint": "eslint .", "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/", - "test-ci": "nyc --reporter=lcovonly --reporter=text npm test", - "test-cov": "nyc --reporter=html --reporter=text npm test", + "test-ci": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=lcovonly --reporter=text npm test", + "test-cov": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=html --reporter=text npm test", "test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/" } } From 2177f67f5439494f7a29a8d04f744cc20fb9f201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Sun, 28 Jul 2024 12:55:10 +0200 Subject: [PATCH 741/889] docs: add OSSF Scorecard badge (#5436) PR-URL: https://github.com/expressjs/express/pull/5436 --- Readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Readme.md b/Readme.md index 365c7b6104f..0fa719e237b 100644 --- a/Readme.md +++ b/Readme.md @@ -22,6 +22,8 @@ [![NPM Version][npm-version-image]][npm-url] [![NPM Install Size][npm-install-size-image]][npm-install-size-url] [![NPM Downloads][npm-downloads-image]][npm-downloads-url] +[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer] + ```js const express = require('express') @@ -252,4 +254,6 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) [npm-install-size-url]: https://packagephobia.com/result?p=express [npm-url]: https://npmjs.org/package/express [npm-version-image]: https://badgen.net/npm/v/express +[ossf-scorecard-badge]: https://api.securityscorecards.dev/projects/github.com/expressjs/express/badge +[ossf-scorecard-visualizer]: https://kooltheba.github.io/openssf-scorecard-api-visualizer/#/projects/github.com/expressjs/express [Code of Conduct]: https://github.com/expressjs/express/blob/master/Code-Of-Conduct.md From 723b5451bbcbab69bc8ded50ccd6545a79b8fe64 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Tue, 30 Jul 2024 17:49:13 -0400 Subject: [PATCH 742/889] Throw on invalid status codes (#4212) * check status code is integer, or string integer, in range * fix tests, update jsdoc comment for res.status * throw if number is string * narrow valid range to between 1xx and 5xx * disambiguate the error message * update skipped tests, remove invalid string test * remove invalid float test * fixup! remove invalid float test * fix invalid range tests error assertions * remove unused deprecate function * add test to assert on 200.00 coming through as 200 this is the behavior of node's underlying HTTP module * revert back to throwing only on > 999 and < 100 * update implementation for > 999 * add test for 700 status code * update history with change * update jsdoc * clarify jsdoc comment * one more round of jsdoc * update 501 test * add invalid status code test for res.sendStatus * add test describe block for valid range * fixup! add test describe block for valid range * reduce the describe nesting * switch to testing status 100, to avoid 100-continue behavior * fix 900 test * stringify code in thrown RangeError message * remove accidentally duplicated res.status method * fix error range message Co-authored-by: Chris de Almeida * update sendStatus invalid code test to use sendStatus --------- Co-authored-by: Chris de Almeida --- History.md | 7 ++ lib/response.js | 28 ++++-- test/res.sendStatus.js | 12 +++ test/res.status.js | 206 ++++++++++++++++++++--------------------- 4 files changed, 141 insertions(+), 112 deletions(-) diff --git a/History.md b/History.md index 73fc46b26fb..89d5af3cebe 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,10 @@ +unreleased +========================= +* breaking: + * `res.status()` accepts only integers, and input must be greater than 99 and less than 1000 + * will throw a `RangeError: Invalid status code: ${code}. Status code must be greater than 99 and less than 1000.` for inputs outside this range + * will throw a `TypeError: Invalid status code: ${code}. Status code must be an integer.` for non integer inputs + 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/lib/response.js b/lib/response.js index 14743817a96..6ad54dbfc7e 100644 --- a/lib/response.js +++ b/lib/response.js @@ -15,7 +15,6 @@ var Buffer = require('safe-buffer').Buffer var contentDisposition = require('content-disposition'); var createError = require('http-errors') -var deprecate = require('depd')('express'); var encodeUrl = require('encodeurl'); var escapeHtml = require('escape-html'); var http = require('http'); @@ -57,17 +56,28 @@ module.exports = res var schemaAndHostRegExp = /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?\/\/[^\\\/\?]+/; /** - * Set status `code`. + * Set the HTTP status code for the response. * - * @param {Number} code - * @return {ServerResponse} + * Expects an integer value between 100 and 999 inclusive. + * Throws an error if the provided status code is not an integer or if it's outside the allowable range. + * + * @param {number} code - The HTTP status code to set. + * @return {ServerResponse} - Returns itself for chaining methods. + * @throws {TypeError} If `code` is not an integer. + * @throws {RangeError} If `code` is outside the range 100 to 999. * @public */ res.status = function status(code) { - if ((typeof code === 'string' || Math.floor(code) !== code) && code > 99 && code < 1000) { - deprecate('res.status(' + JSON.stringify(code) + '): use res.status(' + Math.floor(code) + ') instead') + // Check if the status code is not an integer + if (!Number.isInteger(code)) { + throw new TypeError(`Invalid status code: ${JSON.stringify(code)}. Status code must be an integer.`); } + // Check if the status code is outside of Node's valid range + if (code < 100 || code > 999) { + throw new RangeError(`Invalid status code: ${JSON.stringify(code)}. Status code must be greater than 99 and less than 1000.`); + } + this.statusCode = code; return this; }; @@ -182,7 +192,7 @@ res.send = function send(body) { } // freshness - if (req.fresh) this.statusCode = 304; + if (req.fresh) this.status(304); // strip irrelevant headers if (204 === this.statusCode || 304 === this.statusCode) { @@ -314,7 +324,7 @@ res.jsonp = function jsonp(obj) { res.sendStatus = function sendStatus(statusCode) { var body = statuses.message[statusCode] || String(statusCode) - this.statusCode = statusCode; + this.status(statusCode); this.type('txt'); return this.send(body); @@ -847,7 +857,7 @@ res.redirect = function redirect(url) { }); // Respond - this.statusCode = status; + this.status(status); this.set('Content-Length', Buffer.byteLength(body)); if (this.req.method === 'HEAD') { diff --git a/test/res.sendStatus.js b/test/res.sendStatus.js index 9b1de8385cd..b244cf9d173 100644 --- a/test/res.sendStatus.js +++ b/test/res.sendStatus.js @@ -28,5 +28,17 @@ describe('res', function () { .get('/') .expect(599, '599', done); }) + + it('should raise error for invalid status code', function (done) { + var app = express() + + app.use(function (req, res) { + res.sendStatus(undefined).end() + }) + + request(app) + .get('/') + .expect(500, /TypeError: Invalid status code/, done) + }) }) }) diff --git a/test/res.status.js b/test/res.status.js index d2fc6a28c13..59c8a57e702 100644 --- a/test/res.status.js +++ b/test/res.status.js @@ -1,59 +1,36 @@ 'use strict' - -var express = require('../') -var request = require('supertest') - -var isIoJs = process.release - ? process.release.name === 'io.js' - : ['v1.', 'v2.', 'v3.'].indexOf(process.version.slice(0, 3)) !== -1 +const express = require('../.'); +const request = require('supertest'); describe('res', function () { describe('.status(code)', function () { - // This test fails in node 4.0.0 - // https://github.com/expressjs/express/pull/2237/checks - // As this will all be removed when https://github.com/expressjs/express/pull/4212 - // lands I am skipping for now and we can delete with that PR - describe.skip('when "code" is undefined', function () { - it('should raise error for invalid status code', function (done) { - var app = express() - app.use(function (req, res) { - res.status(undefined).end() - }) + it('should set the status code when valid', function (done) { + var app = express(); - request(app) - .get('/') - .expect(500, /Invalid status code/, function (err) { - if (isIoJs) { - done(err ? null : new Error('expected error')) - } else { - done(err) - } - }) - }) - }) + app.use(function (req, res) { + res.status(200).end(); + }); - describe.skip('when "code" is null', function () { - it('should raise error for invalid status code', function (done) { + request(app) + .get('/') + .expect(200, done); + }); + + describe('accept valid ranges', function() { + // not testing w/ 100, because that has specific meaning and behavior in Node as Expect: 100-continue + it('should set the response status code to 101', function (done) { var app = express() app.use(function (req, res) { - res.status(null).end() + res.status(101).end() }) request(app) .get('/') - .expect(500, /Invalid status code/, function (err) { - if (isIoJs) { - done(err ? null : new Error('expected error')) - } else { - done(err) - } - }) + .expect(101, done) }) - }) - describe('when "code" is 201', function () { it('should set the response status code to 201', function (done) { var app = express() @@ -65,9 +42,7 @@ describe('res', function () { .get('/') .expect(201, done) }) - }) - describe('when "code" is 302', function () { it('should set the response status code to 302', function (done) { var app = express() @@ -79,9 +54,7 @@ describe('res', function () { .get('/') .expect(302, done) }) - }) - describe('when "code" is 403', function () { it('should set the response status code to 403', function (done) { var app = express() @@ -93,9 +66,7 @@ describe('res', function () { .get('/') .expect(403, done) }) - }) - describe('when "code" is 501', function () { it('should set the response status code to 501', function (done) { var app = express() @@ -107,100 +78,129 @@ describe('res', function () { .get('/') .expect(501, done) }) - }) - describe('when "code" is "410"', function () { - it('should set the response status code to 410', function (done) { + it('should set the response status code to 700', function (done) { var app = express() app.use(function (req, res) { - res.status('410').end() + res.status(700).end() }) request(app) .get('/') - .expect(410, done) + .expect(700, done) }) - }) - describe.skip('when "code" is 410.1', function () { - it('should set the response status code to 410', function (done) { + it('should set the response status code to 800', function (done) { var app = express() app.use(function (req, res) { - res.status(410.1).end() + res.status(800).end() }) request(app) .get('/') - .expect(410, function (err) { - if (isIoJs) { - done(err ? null : new Error('expected error')) - } else { - done(err) - } - }) + .expect(800, done) }) - }) - describe.skip('when "code" is 1000', function () { - it('should raise error for invalid status code', function (done) { + it('should set the response status code to 900', function (done) { var app = express() app.use(function (req, res) { - res.status(1000).end() + res.status(900).end() }) request(app) .get('/') - .expect(500, /Invalid status code/, function (err) { - if (isIoJs) { - done(err ? null : new Error('expected error')) - } else { - done(err) - } - }) + .expect(900, done) }) }) - describe.skip('when "code" is 99', function () { - it('should raise error for invalid status code', function (done) { - var app = express() + describe('invalid status codes', function () { + it('should raise error for status code below 100', function (done) { + var app = express(); app.use(function (req, res) { - res.status(99).end() - }) + res.status(99).end(); + }); request(app) .get('/') - .expect(500, /Invalid status code/, function (err) { - if (isIoJs) { - done(err ? null : new Error('expected error')) - } else { - done(err) - } - }) - }) - }) + .expect(500, /Invalid status code/, done); + }); - describe.skip('when "code" is -401', function () { - it('should raise error for invalid status code', function (done) { - var app = express() + it('should raise error for status code above 999', function (done) { + var app = express(); app.use(function (req, res) { - res.status(-401).end() - }) + res.status(1000).end(); + }); request(app) .get('/') - .expect(500, /Invalid status code/, function (err) { - if (isIoJs) { - done(err ? null : new Error('expected error')) - } else { - done(err) - } - }) - }) - }) - }) -}) + .expect(500, /Invalid status code/, done); + }); + + it('should raise error for non-integer status codes', function (done) { + var app = express(); + + app.use(function (req, res) { + res.status(200.1).end(); + }); + + request(app) + .get('/') + .expect(500, /Invalid status code/, done); + }); + + it('should raise error for undefined status code', function (done) { + var app = express(); + + app.use(function (req, res) { + res.status(undefined).end(); + }); + + request(app) + .get('/') + .expect(500, /Invalid status code/, done); + }); + + it('should raise error for null status code', function (done) { + var app = express(); + + app.use(function (req, res) { + res.status(null).end(); + }); + + request(app) + .get('/') + .expect(500, /Invalid status code/, done); + }); + + it('should raise error for string status code', function (done) { + var app = express(); + + app.use(function (req, res) { + res.status("200").end(); + }); + + request(app) + .get('/') + .expect(500, /Invalid status code/, done); + }); + + it('should raise error for NaN status code', function (done) { + var app = express(); + + app.use(function (req, res) { + res.status(NaN).end(); + }); + + request(app) + .get('/') + .expect(500, /Invalid status code/, done); + }); + }); + }); +}); + From d106bf53246eb82aeb925c84c8855c54e17741c2 Mon Sep 17 00:00:00 2001 From: "Mick A." Date: Thu, 1 Aug 2024 17:42:07 -0600 Subject: [PATCH 743/889] Use Array.flat instead of array-flatten (#5677) --- lib/application.js | 4 ++-- package.json | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/application.js b/lib/application.js index 43c9f34b062..ecfe2186db7 100644 --- a/lib/application.js +++ b/lib/application.js @@ -21,7 +21,6 @@ var http = require('http'); var compileETag = require('./utils').compileETag; var compileQueryParser = require('./utils').compileQueryParser; var compileTrust = require('./utils').compileTrust; -var flatten = require('array-flatten').flatten var merge = require('utils-merge'); var resolve = require('path').resolve; var once = require('once') @@ -34,6 +33,7 @@ var setPrototypeOf = require('setprototypeof') */ var slice = Array.prototype.slice; +var flatten = Array.prototype.flat; /** * Application prototype. @@ -209,7 +209,7 @@ app.use = function use(fn) { } } - var fns = flatten(slice.call(arguments, offset)); + var fns = flatten.call(slice.call(arguments, offset), Infinity); if (fns.length === 0) { throw new TypeError('app.use() requires a middleware function') diff --git a/package.json b/package.json index d3e2f0a1909..5ec37a8f773 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ ], "dependencies": { "accepts": "~1.3.8", - "array-flatten": "3.0.0", "body-parser": "2.0.0-beta.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", From 160b91cbf79b595712b694c3513c347551d17fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Fri, 2 Aug 2024 16:07:36 +0200 Subject: [PATCH 744/889] feat: adopt Node@18 as the minimum supported version (#5803) - PR-URL: https://github.com/expressjs/express/pull/5803 - This is a BREAKING CHANGE --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ec37a8f773..37b0a63ed4b 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "vhost": "~3.0.2" }, "engines": { - "node": ">= 4" + "node": ">= 18" }, "files": [ "LICENSE", From 9c756b01050de1d0a52eca507093862fb1cf2fe1 Mon Sep 17 00:00:00 2001 From: ctcpip Date: Fri, 2 Aug 2024 13:15:51 -0500 Subject: [PATCH 745/889] =?UTF-8?q?=F0=9F=92=9A=20remove=20node=20<11,=20a?= =?UTF-8?q?ll=20failing=20permanently=20now?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/legacy.yml | 40 ------------------------------------ 1 file changed, 40 deletions(-) diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 5bf3b69a9fb..2d9d50440de 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -11,14 +11,6 @@ jobs: fail-fast: false matrix: name: - - Node.js 4.0 - - Node.js 4.x - - Node.js 5.x - - Node.js 6.x - - Node.js 7.x - - Node.js 8.x - - Node.js 9.x - - Node.js 10.x - Node.js 11.x - Node.js 12.x - Node.js 13.x @@ -28,38 +20,6 @@ jobs: - Node.js 17.x include: - - name: Node.js 4.0 - node-version: "4.0" - npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - - - name: Node.js 4.x - node-version: "4.9" - npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - - - name: Node.js 5.x - node-version: "5.12" - npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 - - - name: Node.js 6.x - node-version: "6.17" - npm-i: mocha@6.2.2 nyc@14.1.1 supertest@3.4.2 - - - name: Node.js 7.x - node-version: "7.10" - npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6 - - - name: Node.js 8.x - node-version: "8.17" - npm-i: mocha@7.2.0 nyc@14.1.1 - - - name: Node.js 9.x - node-version: "9.11" - npm-i: mocha@7.2.0 nyc@14.1.1 - - - name: Node.js 10.x - node-version: "10.24" - npm-i: mocha@8.4.0 - - name: Node.js 11.x node-version: "11.15" npm-i: mocha@8.4.0 From 82fc12a40b3e6694e9a2c9b1376e7548d95779f6 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Fri, 2 Aug 2024 16:26:45 -0400 Subject: [PATCH 746/889] Ignore `expires` and `maxAge` in `res.clearCookie()` (#5792) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add test for removing user provided expires * rework impl and tests to ignore maxAge, do not set it this is to take into account the built-in relative expires when passing a maxAge to res.cookie I realized that using maxAge to invalidate cookies inherrently hit this relativee expires behavior, and the goal of this PR is not to rework that relative expires behavior w/ maxAge, but to prevent users from overwriting these values by accident when clearing cookies * update history.md * explicitly delete maxAge instead of setting as undefined * drop the spread, use object.assign * wording, review comment on history.md Co-authored-by: Chris de Almeida * ♻️ use spread, update supported ecmascript version --------- Co-authored-by: Chris de Almeida --- .eslintrc.yml | 2 +- History.md | 2 ++ lib/response.js | 5 ++++- test/res.clearCookie.js | 26 ++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 9e282530d50..70bc9a6e7e1 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,6 +1,6 @@ root: true env: - es6: true + es2022: true node: true rules: eol-last: error diff --git a/History.md b/History.md index 89d5af3cebe..7c51a32d8be 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,8 @@ unreleased * `res.status()` accepts only integers, and input must be greater than 99 and less than 1000 * will throw a `RangeError: Invalid status code: ${code}. Status code must be greater than 99 and less than 1000.` for inputs outside this range * will throw a `TypeError: Invalid status code: ${code}. Status code must be an integer.` for non integer inputs +* change: + - `res.clearCookie` will ignore user provided `maxAge` and `expires` options 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/lib/response.js b/lib/response.js index 6ad54dbfc7e..a5a33e86097 100644 --- a/lib/response.js +++ b/lib/response.js @@ -707,7 +707,10 @@ res.get = function(field){ */ res.clearCookie = function clearCookie(name, options) { - var opts = merge({ expires: new Date(1), path: '/' }, options); + // Force cookie expiration by setting expires to the past + const opts = { path: '/', ...options, expires: new Date(1)}; + // ensure maxAge is not passed + delete opts.maxAge return this.cookie(name, '', opts); }; diff --git a/test/res.clearCookie.js b/test/res.clearCookie.js index fc0cfb99a3d..74a746eb7be 100644 --- a/test/res.clearCookie.js +++ b/test/res.clearCookie.js @@ -32,5 +32,31 @@ describe('res', function(){ .expect('Set-Cookie', 'sid=; Path=/admin; Expires=Thu, 01 Jan 1970 00:00:00 GMT') .expect(200, done) }) + + it('should ignore maxAge', function(done){ + var app = express(); + + app.use(function(req, res){ + res.clearCookie('sid', { path: '/admin', maxAge: 1000 }).end(); + }); + + request(app) + .get('/') + .expect('Set-Cookie', 'sid=; Path=/admin; Expires=Thu, 01 Jan 1970 00:00:00 GMT') + .expect(200, done) + }) + + it('should ignore user supplied expires param', function(done){ + var app = express(); + + app.use(function(req, res){ + res.clearCookie('sid', { path: '/admin', expires: new Date() }).end(); + }); + + request(app) + .get('/') + .expect('Set-Cookie', 'sid=; Path=/admin; Expires=Thu, 01 Jan 1970 00:00:00 GMT') + .expect(200, done) + }) }) }) From ecf762ff383c2cefa4e49b4a7e2d7af23a255d5d Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Fri, 9 Aug 2024 09:59:53 -0700 Subject: [PATCH 747/889] fix(deps)!: send@^1.0.0 (#5786) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 7c51a32d8be..00e9182116b 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ unreleased * `res.status()` accepts only integers, and input must be greater than 99 and less than 1000 * will throw a `RangeError: Invalid status code: ${code}. Status code must be greater than 99 and less than 1000.` for inputs outside this range * will throw a `TypeError: Invalid status code: ${code}. Status code must be an integer.` for non integer inputs + * deps: send@1.0.0 * change: - `res.clearCookie` will ignore user provided `maxAge` and `expires` options diff --git a/package.json b/package.json index 37b0a63ed4b..834fa595796 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "range-parser": "~1.2.1", "router": "2.0.0-beta.2", "safe-buffer": "5.2.1", - "send": "1.0.0-beta.2", + "send": "^1.0.0", "serve-static": "2.0.0-beta.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", From 41c054cff1e10f346feb39efe1f66660c0570aab Mon Sep 17 00:00:00 2001 From: Carlos Serrano Date: Sat, 17 Aug 2024 17:20:25 +0200 Subject: [PATCH 748/889] chore: upgrade `debug` dep from 3.10 to 4.3.6 (#5829) * chore: upgrade debug dep from 3.10 to 4.3.6 * docs: add debug dep upgrade to History.md --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 00e9182116b..8722c2ec0b8 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,7 @@ unreleased * deps: send@1.0.0 * change: - `res.clearCookie` will ignore user provided `maxAge` and `expires` options +* deps: debug@4.3.6 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index 834fa595796..44b885ba1c4 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", - "debug": "3.1.0", + "debug": "4.3.6", "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", From 09831580ec64c2b53d712dfbf47a47a5790aa560 Mon Sep 17 00:00:00 2001 From: Carlos Serrano Date: Sat, 17 Aug 2024 17:21:29 +0200 Subject: [PATCH 749/889] refactor: replace 'path-is-absolute' dep with node:path isAbsolute method (#5830) * refactor: replace 'path-is-absolute' dep with node:path isAbsolute method * docs: add path-is-absolute dep removal to History.md --- History.md | 2 ++ lib/response.js | 2 +- package.json | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 8722c2ec0b8..d8306a5d5ba 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,7 @@ unreleased ========================= +* remove: + - `path-is-absolute` dependency - use `path.isAbsolute` instead * breaking: * `res.status()` accepts only integers, and input must be greater than 99 and less than 1000 * will throw a `RangeError: Invalid status code: ${code}. Status code must be greater than 99 and less than 1000.` for inputs outside this range diff --git a/lib/response.js b/lib/response.js index a5a33e86097..1f1b7e924a8 100644 --- a/lib/response.js +++ b/lib/response.js @@ -21,7 +21,7 @@ var http = require('http'); var onFinished = require('on-finished'); var mime = require('mime-types') var path = require('path'); -var pathIsAbsolute = require('path-is-absolute'); +var pathIsAbsolute = require('path').isAbsolute; var statuses = require('statuses') var merge = require('utils-merge'); var sign = require('cookie-signature').sign; diff --git a/package.json b/package.json index 44b885ba1c4..30c9597269b 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "on-finished": "2.4.1", "once": "1.4.0", "parseurl": "~1.3.3", - "path-is-absolute": "1.0.1", "proxy-addr": "~2.0.7", "qs": "6.11.0", "range-parser": "~1.2.1", From f5b6e67aed1d8e81c30bd5be7bb88dbbfabfeb64 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sun, 18 Aug 2024 13:37:51 -0500 Subject: [PATCH 750/889] docs: update scorecard link (#5814) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ulises Gascón --- Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 0fa719e237b..34362d856f7 100644 --- a/Readme.md +++ b/Readme.md @@ -254,6 +254,6 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) [npm-install-size-url]: https://packagephobia.com/result?p=express [npm-url]: https://npmjs.org/package/express [npm-version-image]: https://badgen.net/npm/v/express -[ossf-scorecard-badge]: https://api.securityscorecards.dev/projects/github.com/expressjs/express/badge -[ossf-scorecard-visualizer]: https://kooltheba.github.io/openssf-scorecard-api-visualizer/#/projects/github.com/expressjs/express +[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/express/badge +[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/express [Code of Conduct]: https://github.com/expressjs/express/blob/master/Code-Of-Conduct.md From e35380a39d94937e3d0f7119e0efbc7cd69d003f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Mon, 19 Aug 2024 22:12:24 +0200 Subject: [PATCH 751/889] docs: add @IamLizu to the triage team (#5836) PR-URL: https://github.com/expressjs/express/pull/5836 --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 34362d856f7..bc108d55fc0 100644 --- a/Readme.md +++ b/Readme.md @@ -202,6 +202,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi** * [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him) * [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego** +* [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him) * [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger**
        From c5addb9a17c5b4c9fccdd2c04153a30595e03385 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Wed, 21 Aug 2024 20:15:02 -0700 Subject: [PATCH 752/889] deps: path-to-regexp@0.1.8 (#5603) --- History.md | 2 ++ package.json | 2 +- test/app.router.js | 26 ++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c02b24ffba2..d81f423d16f 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,8 @@ unreleased ========== + * deps: path-to-regexp@0.1.8 + - Adds support for named matching groups in the routes using a regex * deps: encodeurl@~2.0.0 - Removes encoding of `\`, `|`, and `^` to align better with URL spec * Deprecate passing `options.maxAge` and `options.expires` to `res.clearCookie` diff --git a/package.json b/package.json index 71781e11d64..e88618f997b 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.8", "proxy-addr": "~2.0.7", "qs": "6.11.0", "range-parser": "~1.2.1", diff --git a/test/app.router.js b/test/app.router.js index 707333f0432..8e427bd6dc7 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -193,6 +193,23 @@ describe('app.router', function(){ .expect('editing user 10', done); }) + if (supportsRegexp('(?.*)')) { + it('should populate req.params with named captures', function(done){ + var app = express(); + var re = new RegExp('^/user/(?[0-9]+)/(view|edit)?$'); + + app.get(re, function(req, res){ + var id = req.params.userId + , op = req.params[0]; + res.end(op + 'ing user ' + id); + }); + + request(app) + .get('/user/10/edit') + .expect('editing user 10', done); + }) + } + it('should ensure regexp matches path prefix', function (done) { var app = express() var p = [] @@ -1114,3 +1131,12 @@ describe('app.router', function(){ assert.strictEqual(app.get('/', function () {}), app) }) }) + +function supportsRegexp(source) { + try { + new RegExp(source) + return true + } catch (e) { + return false + } +} From a3e7e05e0a435b7b4be25bd38d8d0ca19a773ca9 Mon Sep 17 00:00:00 2001 From: S M Mahmudul Hasan Date: Thu, 22 Aug 2024 22:25:14 +0600 Subject: [PATCH 753/889] docs: specify new instructions for `question` and `discuss` PR-URL: https://github.com/expressjs/express/pull/5835 --- Triager-Guide.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Triager-Guide.md b/Triager-Guide.md index a2909ef30db..c15e6be5313 100644 --- a/Triager-Guide.md +++ b/Triager-Guide.md @@ -9,11 +9,18 @@ classification: * `needs triage`: This can be kept if the triager is unsure which next steps to take * `awaiting more info`: If more info has been requested from the author, apply this label. -* `question`: User questions that do not appear to be bugs or enhancements. -* `discuss`: Topics for discussion. Might end in an `enhancement` or `question` label. * `bug`: Issues that present a reasonable conviction there is a reproducible bug. * `enhancement`: Issues that are found to be a reasonable candidate feature additions. +If the issue is a question or discussion, it should be moved to GitHub Discussions. + +### Moving Discussions and Questions to GitHub Discussions + +For issues labeled with `question` or `discuss`, it is recommended to move them to GitHub Discussions instead: + +* **Questions**: User questions that do not appear to be bugs or enhancements should be moved to GitHub Discussions. +* **Discussions**: Topics for discussion should be moved to GitHub Discussions. If the discussion leads to a new feature or bug identification, it can be moved back to Issues. + In all cases, issues may be closed by maintainers if they don't receive a timely response when further information is sought, or when additional questions are asked. From 0b243b1aee0d8774f2b97da2e8ac4340adaed1b3 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Fri, 23 Aug 2024 22:37:27 +0200 Subject: [PATCH 754/889] 5.x: Upgrading `merge-descriptors` with allowing minors (#5782) * Upgrading `merge-descriptors` with allowing minors in v5 * Using ^2.0.0 as per request * Reflecting in History.md. * Update History.md --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index d8306a5d5ba..05730e259e3 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,7 @@ unreleased * change: - `res.clearCookie` will ignore user provided `maxAge` and `expires` options * deps: debug@4.3.6 +* deps: merge-descriptors@^2.0.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index 30c9597269b..e5c8d03d1bc 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "finalhandler": "1.2.0", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "^2.0.0", "methods": "~1.1.2", "mime-types": "~2.1.34", "on-finished": "2.4.1", From 2a980ad16052e53b398c9953fea50e3daa0b495c Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Fri, 23 Aug 2024 22:39:13 +0200 Subject: [PATCH 755/889] merge-descriptors@1.0.3 (#5781) * Allow patches for `merge-descriptors` dependency * Set fixed latest of v1 (1.0.3) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e88618f997b..91e29013a33 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "finalhandler": "1.2.0", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", From 65b62065d2b4308212fc3b19ab4986a9fa10ca41 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Fri, 23 Aug 2024 16:07:45 -0500 Subject: [PATCH 756/889] fix(deps) serve-staic@2.0.0 (#5790) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 05730e259e3..4c986606d5d 100644 --- a/History.md +++ b/History.md @@ -11,6 +11,7 @@ unreleased - `res.clearCookie` will ignore user provided `maxAge` and `expires` options * deps: debug@4.3.6 * deps: merge-descriptors@^2.0.0 +* deps: serve-static@^2.0.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index e5c8d03d1bc..b3fe60c8720 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "router": "2.0.0-beta.2", "safe-buffer": "5.2.1", "send": "^1.0.0", - "serve-static": "2.0.0-beta.2", + "serve-static": "^2.0.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", From 13e68943935f81aa7301c90d0d709d5153a675c9 Mon Sep 17 00:00:00 2001 From: Carlos Serrano Date: Fri, 23 Aug 2024 23:10:16 +0200 Subject: [PATCH 757/889] chore: qs@6.13.0 (#5847) Co-authored-by: Wes Todd --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 4c986606d5d..6ef8b18af7f 100644 --- a/History.md +++ b/History.md @@ -12,6 +12,7 @@ unreleased * deps: debug@4.3.6 * deps: merge-descriptors@^2.0.0 * deps: serve-static@^2.0.0 +* deps: qs@6.13.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index b3fe60c8720..5ab1324310d 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "once": "1.4.0", "parseurl": "~1.3.3", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "router": "2.0.0-beta.2", "safe-buffer": "5.2.1", From 91a58b5b0368e91c67971cfb13519c1b5087847d Mon Sep 17 00:00:00 2001 From: S M Mahmudul Hasan Date: Sat, 24 Aug 2024 05:17:12 +0600 Subject: [PATCH 758/889] cookie-signature@^1.2.1 (#5833) * upgraded `cookie-signature` to 1.2.1 * declared cookie-signature deps in history * add caret in version --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 6ef8b18af7f..2a563fbab21 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,7 @@ unreleased * deps: send@1.0.0 * change: - `res.clearCookie` will ignore user provided `maxAge` and `expires` options +* deps: cookie-signature@^1.2.1 * deps: debug@4.3.6 * deps: merge-descriptors@^2.0.0 * deps: serve-static@^2.0.0 diff --git a/package.json b/package.json index 5ab1324310d..e60aadca360 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", - "cookie-signature": "1.0.6", + "cookie-signature": "^1.2.1", "debug": "4.3.6", "depd": "2.0.0", "encodeurl": "~1.0.2", From 7748475747c3ccabc929dac78ea4eeb34003b245 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Sat, 31 Aug 2024 10:55:04 -0500 Subject: [PATCH 759/889] fix(deps): accepts@^2.0.0 (#5881) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2a563fbab21..3d931f2b1db 100644 --- a/History.md +++ b/History.md @@ -14,6 +14,7 @@ unreleased * deps: merge-descriptors@^2.0.0 * deps: serve-static@^2.0.0 * deps: qs@6.13.0 +* deps: accepts@^2.0.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index e60aadca360..ec307170318 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "api" ], "dependencies": { - "accepts": "~1.3.8", + "accepts": "^2.0.0", "body-parser": "2.0.0-beta.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", From 4e61d0100d903de94673d4202eaa7edde5888fb4 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Sat, 31 Aug 2024 11:06:25 -0500 Subject: [PATCH 760/889] fix(deps)!: mime-types@^3.0.0 (#5882) --- History.md | 2 ++ package.json | 2 +- test/res.type.js | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 3d931f2b1db..e2cb5c07c01 100644 --- a/History.md +++ b/History.md @@ -15,6 +15,8 @@ unreleased * deps: serve-static@^2.0.0 * deps: qs@6.13.0 * deps: accepts@^2.0.0 +* deps: mime-types@^3.0.0 + - `application/javascript` => `text/javascript` 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index ec307170318..83080a7b8a4 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "http-errors": "2.0.0", "merge-descriptors": "^2.0.0", "methods": "~1.1.2", - "mime-types": "~2.1.34", + "mime-types": "^3.0.0", "on-finished": "2.4.1", "once": "1.4.0", "parseurl": "~1.3.3", diff --git a/test/res.type.js b/test/res.type.js index 980717a6e30..09285af3914 100644 --- a/test/res.type.js +++ b/test/res.type.js @@ -14,7 +14,7 @@ describe('res', function(){ request(app) .get('/') - .expect('Content-Type', 'application/javascript; charset=utf-8') + .expect('Content-Type', 'text/javascript; charset=utf-8') .end(done) }) From 402e7f653fd79528df634c3464f2fe929e716ff3 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Sat, 31 Aug 2024 12:31:31 -0500 Subject: [PATCH 761/889] fix(deps): type-is@^2.0.0 (#5883) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e2cb5c07c01..69293ecad39 100644 --- a/History.md +++ b/History.md @@ -17,6 +17,7 @@ unreleased * deps: accepts@^2.0.0 * deps: mime-types@^3.0.0 - `application/javascript` => `text/javascript` +* deps: type-is@^2.0.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index 83080a7b8a4..dc3ba4af879 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "serve-static": "^2.0.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", - "type-is": "~1.6.18", + "type-is": "^2.0.0", "utils-merge": "1.0.1", "vary": "~1.1.2" }, From 05f40f4321fee5235de0159dcd2a826c2532dff1 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Sat, 31 Aug 2024 13:09:21 -0500 Subject: [PATCH 762/889] fix(deps)!: content-disposition@^1.0.0 (#5884) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 69293ecad39..c4d4045b753 100644 --- a/History.md +++ b/History.md @@ -18,6 +18,7 @@ unreleased * deps: mime-types@^3.0.0 - `application/javascript` => `text/javascript` * deps: type-is@^2.0.0 +* deps: content-disposition@^1.0.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index dc3ba4af879..c89c38f49dd 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "accepts": "^2.0.0", "body-parser": "2.0.0-beta.2", - "content-disposition": "0.5.4", + "content-disposition": "^1.0.0", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "^1.2.1", From accafc652eb18162eb7d88273e42db8bd7a2f821 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 2 Sep 2024 13:36:21 -0500 Subject: [PATCH 763/889] fix(deps): finalhandler@^2.0.0 (#5899) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c4d4045b753..911423735c2 100644 --- a/History.md +++ b/History.md @@ -19,6 +19,7 @@ unreleased - `application/javascript` => `text/javascript` * deps: type-is@^2.0.0 * deps: content-disposition@^1.0.0 +* deps: finalhandler@^2.0.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index c89c38f49dd..fd3e74cbade 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "^2.0.0", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "^2.0.0", From 125bb742a38cd97938a3932b47cc301e41c31f5d Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 9 Sep 2024 14:02:06 -0700 Subject: [PATCH 764/889] path-to-regexp@0.1.10 (#5902) * path-to-regexp@0.1.10 * Update History.md --- History.md | 3 ++- package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index d81f423d16f..b0aa2e0959e 100644 --- a/History.md +++ b/History.md @@ -1,8 +1,9 @@ unreleased ========== - * deps: path-to-regexp@0.1.8 + * deps: path-to-regexp@0.1.10 - Adds support for named matching groups in the routes using a regex + - Adds backtracking protection to parameters without regexes defined * deps: encodeurl@~2.0.0 - Removes encoding of `\`, `|`, and `^` to align better with URL spec * Deprecate passing `options.maxAge` and `options.expires` to `res.clearCookie` diff --git a/package.json b/package.json index 91e29013a33..87cf10be9c2 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.8", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", "qs": "6.11.0", "range-parser": "~1.2.1", From 4d713d2b767e13bfbd4f91f4dc9fd442e9896bcd Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 9 Sep 2024 18:03:32 -0400 Subject: [PATCH 765/889] update to fresh@2.0.0 (#5916) fixes handling of If-Modified-Since in combination with If-None-Match --- History.md | 3 ++- lib/request.js | 2 +- package.json | 2 +- test/req.fresh.js | 20 ++++++++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 911423735c2..0f4515b55c9 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,6 @@ unreleased ========================= -* remove: +* remove: - `path-is-absolute` dependency - use `path.isAbsolute` instead * breaking: * `res.status()` accepts only integers, and input must be greater than 99 and less than 1000 @@ -20,6 +20,7 @@ unreleased * deps: type-is@^2.0.0 * deps: content-disposition@^1.0.0 * deps: finalhandler@^2.0.0 +* deps: fresh@^2.0.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/lib/request.js b/lib/request.js index c528186aa13..372a9915e96 100644 --- a/lib/request.js +++ b/lib/request.js @@ -447,7 +447,7 @@ defineGetter(req, 'hostname', function hostname(){ /** * Check if the request is fresh, aka - * Last-Modified and/or the ETag + * Last-Modified or the ETag * still match. * * @return {Boolean} diff --git a/package.json b/package.json index fd3e74cbade..146369258bd 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "^2.0.0", - "fresh": "0.5.2", + "fresh": "2.0.0", "http-errors": "2.0.0", "merge-descriptors": "^2.0.0", "methods": "~1.1.2", diff --git a/test/req.fresh.js b/test/req.fresh.js index 9160e2caaf6..3bf6a1f65a7 100644 --- a/test/req.fresh.js +++ b/test/req.fresh.js @@ -46,5 +46,25 @@ describe('req', function(){ .get('/') .expect(200, 'false', done); }) + + it('should ignore "If-Modified-Since" when "If-None-Match" is present', function(done) { + var app = express(); + const etag = '"FooBar"' + const now = Date.now() + + app.disable('x-powered-by') + app.use(function(req, res) { + res.set('Etag', etag) + res.set('Last-Modified', new Date(now).toUTCString()) + res.send(req.fresh); + }); + + request(app) + .get('/') + .set('If-Modified-Since', new Date(now - 1000).toUTCString) + .set('If-None-Match', etag) + .expect(304, done); + }) + }) }) From 0264908903a64a3edd00fbe77e65c6748cc1b6e9 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 9 Sep 2024 17:50:11 -0500 Subject: [PATCH 766/889] feat(deps)!: router@^2.0.0 (#5885) --- examples/downloads/index.js | 4 +-- examples/resource/index.js | 2 +- examples/route-separation/index.js | 2 +- package.json | 2 +- test/app.all.js | 2 +- test/app.router.js | 54 +++++++++++++++--------------- test/req.route.js | 4 +-- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/examples/downloads/index.js b/examples/downloads/index.js index 5e48ac39709..c47dddd738a 100644 --- a/examples/downloads/index.js +++ b/examples/downloads/index.js @@ -23,8 +23,8 @@ app.get('/', function(req, res){ // /files/* is accessed via req.params[0] // but here we name it :file -app.get('/files/:file+', function (req, res, next) { - res.download(req.params.file, { root: FILES_DIR }, function (err) { +app.get('/files/*file', function (req, res, next) { + res.download(req.params.file.join('/'), { root: FILES_DIR }, function (err) { if (!err) return; // file sent if (err.status !== 404) return next(err); // non-404 error // file for download not found diff --git a/examples/resource/index.js b/examples/resource/index.js index ff1f6fe11f4..627ab24c5a2 100644 --- a/examples/resource/index.js +++ b/examples/resource/index.js @@ -12,7 +12,7 @@ var app = module.exports = express(); app.resource = function(path, obj) { this.get(path, obj.index); - this.get(path + '/:a..:b.:format?', function(req, res){ + this.get(path + '/:a..:b{.:format}', function(req, res){ var a = parseInt(req.params.a, 10); var b = parseInt(req.params.b, 10); var format = req.params.format; diff --git a/examples/route-separation/index.js b/examples/route-separation/index.js index 5d483811111..a471a4b0912 100644 --- a/examples/route-separation/index.js +++ b/examples/route-separation/index.js @@ -38,7 +38,7 @@ app.get('/', site.index); // User app.get('/users', user.list); -app.all('/user/:id/:op?', user.load); +app.all('/user/:id{/:op}', user.load); app.get('/user/:id', user.view); app.get('/user/:id/view', user.view); app.get('/user/:id/edit', user.edit); diff --git a/package.json b/package.json index 146369258bd..d7600267ca4 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", - "router": "2.0.0-beta.2", + "router": "^2.0.0", "safe-buffer": "5.2.1", "send": "^1.0.0", "serve-static": "^2.0.0", diff --git a/test/app.all.js b/test/app.all.js index 185a8332fe7..e4afca7d731 100644 --- a/test/app.all.js +++ b/test/app.all.js @@ -26,7 +26,7 @@ describe('app.all()', function(){ var app = express() , n = 0; - app.all('/*', function(req, res, next){ + app.all('/*splat', function(req, res, next){ if (n++) return done(new Error('DELETE called several times')); next(); }); diff --git a/test/app.router.js b/test/app.router.js index d6f3edf1ab2..7961aa348dc 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -316,12 +316,12 @@ describe('app.router', function(){ var app = express(); var router = new express.Router({ mergeParams: true }); - router.get('/(.*).(.*)', function (req, res) { + router.get(/^\/(.*)\.(.*)/, function (req, res) { var keys = Object.keys(req.params).sort(); res.send(keys.map(function(k){ return [k, req.params[k]] })); }); - app.use('/user/id:(\\d+)', router); + app.use(/^\/user\/id:(\d+)/, router); request(app) .get('/user/id:10/profile.json') @@ -332,12 +332,12 @@ describe('app.router', function(){ var app = express(); var router = new express.Router({ mergeParams: true }); - router.get('/(.*)', function (req, res) { + router.get(/\/(.*)/, function (req, res) { var keys = Object.keys(req.params).sort(); res.send(keys.map(function(k){ return [k, req.params[k]] })); }); - app.use('/user/id:(\\d+)/name:(\\w+)', router); + app.use(/^\/user\/id:(\d+)\/name:(\w+)/, router); request(app) .get('/user/id:10/name:tj/profile') @@ -348,12 +348,12 @@ describe('app.router', function(){ var app = express(); var router = new express.Router({ mergeParams: true }); - router.get('/name:(\\w+)', function(req, res){ + router.get(/\/name:(\w+)/, function(req, res){ var keys = Object.keys(req.params).sort(); res.send(keys.map(function(k){ return [k, req.params[k]] })); }); - app.use('/user/id:(\\d+)', router); + app.use(/\/user\/id:(\d+)/, router); request(app) .get('/user/id:10/name:tj') @@ -383,11 +383,11 @@ describe('app.router', function(){ var app = express(); var router = new express.Router({ mergeParams: true }); - router.get('/user:(\\w+)/*', function (req, res, next) { + router.get(/\/user:(\w+)\//, function (req, res, next) { next(); }); - app.use('/user/id:(\\d+)', function (req, res, next) { + app.use(/\/user\/id:(\d+)/, function (req, res, next) { router(req, res, function (err) { var keys = Object.keys(req.params).sort(); res.send(keys.map(function(k){ return [k, req.params[k]] })); @@ -610,8 +610,8 @@ describe('app.router', function(){ 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)' : '')); + app.get('/user{s}/:user/:op', function(req, res){ + res.end(req.params.op + 'ing ' + req.params.user + (req.url.startsWith('/users') ? ' (old)' : '')); }); request(app) @@ -657,7 +657,7 @@ describe('app.router', function(){ it('should denote an optional capture group', function(done){ var app = express(); - app.get('/user/:user/:op?', function(req, res){ + app.get('/user/:user{/:op}', function(req, res){ var op = req.params.op || 'view'; res.end(op + 'ing ' + req.params.user); }); @@ -670,7 +670,7 @@ describe('app.router', function(){ it('should populate the capture group', function(done){ var app = express(); - app.get('/user/:user/:op?', function(req, res){ + app.get('/user/:user{/:op}', function(req, res){ var op = req.params.op || 'view'; res.end(op + 'ing ' + req.params.user); }); @@ -685,8 +685,8 @@ describe('app.router', function(){ it('should match one segment', function (done) { var app = express() - app.get('/user/:user*', function (req, res) { - res.end(req.params.user) + app.get('/user/*user', function (req, res) { + res.end(req.params.user[0]) }) request(app) @@ -697,8 +697,8 @@ describe('app.router', function(){ it('should match many segments', function (done) { var app = express() - app.get('/user/:user*', function (req, res) { - res.end(req.params.user) + app.get('/user/*user', function (req, res) { + res.end(req.params.user.join('/')) }) request(app) @@ -709,7 +709,7 @@ describe('app.router', function(){ it('should match zero segments', function (done) { var app = express() - app.get('/user/:user*', function (req, res) { + app.get('/user{/*user}', function (req, res) { res.end(req.params.user) }) @@ -723,8 +723,8 @@ describe('app.router', function(){ it('should match one segment', function (done) { var app = express() - app.get('/user/:user+', function (req, res) { - res.end(req.params.user) + app.get('/user/*user', function (req, res) { + res.end(req.params.user[0]) }) request(app) @@ -735,8 +735,8 @@ describe('app.router', function(){ it('should match many segments', function (done) { var app = express() - app.get('/user/:user+', function (req, res) { - res.end(req.params.user) + app.get('/user/*user', function (req, res) { + res.end(req.params.user.join('/')) }) request(app) @@ -747,7 +747,7 @@ describe('app.router', function(){ it('should not match zero segments', function (done) { var app = express() - app.get('/user/:user+', function (req, res) { + app.get('/user/*user', function (req, res) { res.end(req.params.user) }) @@ -781,7 +781,7 @@ describe('app.router', function(){ var app = express(); var cb = after(2, done) - app.get('/:name.:format?', function(req, res){ + app.get('/:name{.:format}', function(req, res){ res.end(req.params.name + ' as ' + (req.params.format || 'html')); }); @@ -800,7 +800,7 @@ describe('app.router', function(){ var app = express() , calls = []; - app.get('/foo/:bar?', function(req, res, next){ + app.get('/foo{/:bar}', function(req, res, next){ calls.push('/foo/:bar?'); next(); }); @@ -885,7 +885,7 @@ describe('app.router', function(){ var app = express() , calls = []; - app.get('/foo/:bar?', function(req, res, next){ + app.get('/foo{/:bar}', function(req, res, next){ calls.push('/foo/:bar?'); next(); }); @@ -1096,7 +1096,7 @@ describe('app.router', function(){ var app = express(); var path = []; - app.get('/:path+', function (req, res, next) { + app.get('/*path', function (req, res, next) { path.push(0); next(); }); @@ -1116,7 +1116,7 @@ describe('app.router', function(){ next(); }); - app.get('/(.*)', function (req, res, next) { + app.get('/*splat', function (req, res, next) { path.push(4); next(); }); diff --git a/test/req.route.js b/test/req.route.js index 6c17fbb1c8f..9bd7ed923b4 100644 --- a/test/req.route.js +++ b/test/req.route.js @@ -8,7 +8,7 @@ describe('req', function(){ it('should be the executed Route', function(done){ var app = express(); - app.get('/user/:id/:op?', function(req, res, next){ + app.get('/user/:id{/:op}', function(req, res, next){ res.header('path-1', req.route.path) next(); }); @@ -20,7 +20,7 @@ describe('req', function(){ request(app) .get('/user/12/edit') - .expect('path-1', '/user/:id/:op?') + .expect('path-1', '/user/:id{/:op}') .expect('path-2', '/user/:id/edit') .expect(200, done) }) From 54271f69b511fea198471e6ff3400ab805d6b553 Mon Sep 17 00:00:00 2001 From: Chris de Almeida Date: Mon, 9 Sep 2024 17:16:58 -0500 Subject: [PATCH 767/889] fix: don't render redirect values in anchor href MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ulises Gascón --- lib/response.js | 2 +- test/res.redirect.js | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/response.js b/lib/response.js index 68d969ff05b..76b6b54a3b8 100644 --- a/lib/response.js +++ b/lib/response.js @@ -969,7 +969,7 @@ res.redirect = function redirect(url) { html: function(){ var u = escapeHtml(address); - body = '

        ' + statuses.message[status] + '. Redirecting to ' + u + '

        ' + body = '

        ' + statuses.message[status] + '. Redirecting to ' + u + '

        ' }, default: function(){ diff --git a/test/res.redirect.js b/test/res.redirect.js index 5ffc7e48f12..f7214d93312 100644 --- a/test/res.redirect.js +++ b/test/res.redirect.js @@ -106,7 +106,7 @@ describe('res', function(){ .set('Accept', 'text/html') .expect('Content-Type', /html/) .expect('Location', 'http://google.com/') - .expect(302, '

        Found. Redirecting to http://google.com

        ', done) + .expect(302, '

        Found. Redirecting to http://google.com

        ', done) }) it('should escape the url', function(done){ @@ -122,9 +122,27 @@ describe('res', function(){ .set('Accept', 'text/html') .expect('Content-Type', /html/) .expect('Location', '%3Cla\'me%3E') - .expect(302, '

        Found. Redirecting to %3Cla'me%3E

        ', done) + .expect(302, '

        Found. Redirecting to %3Cla'me%3E

        ', done) }) + it('should not render evil javascript links in anchor href (prevent XSS)', function(done){ + var app = express(); + var xss = 'javascript:eval(document.body.innerHTML=`

        XSS

        `);'; + var encodedXss = 'javascript:eval(document.body.innerHTML=%60%3Cp%3EXSS%3C/p%3E%60);'; + + app.use(function(req, res){ + res.redirect(xss); + }); + + request(app) + .get('/') + .set('Host', 'http://example.com/') + .set('Accept', 'text/html') + .expect('Content-Type', /html/) + .expect('Location', encodedXss) + .expect(302, '

        Found. Redirecting to ' + encodedXss +'

        ', done); + }); + it('should include the redirect type', function(done){ var app = express(); @@ -137,7 +155,7 @@ describe('res', function(){ .set('Accept', 'text/html') .expect('Content-Type', /html/) .expect('Location', 'http://google.com/') - .expect(301, '

        Moved Permanently. Redirecting to http://google.com

        ', done); + .expect(301, '

        Moved Permanently. Redirecting to http://google.com

        ', done); }) }) From ec4a01b6b8814d7b007f36a3023f4dbafdbc3d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 10 Sep 2024 01:36:30 +0200 Subject: [PATCH 768/889] feat: upgrade to body-parser@1.20.3 (#5926) PR-URL: https://github.com/expressjs/express/pull/5926 --- History.md | 5 ++++- package.json | 2 +- test/express.urlencoded.js | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index b0aa2e0959e..904db45b233 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,9 @@ unreleased ========== - + * deps: body-parser@0.6.0 + * add `depth` option to customize the depth level in the parser + * IMPORTANT: The default `depth` level for parsing URL-encoded data is now `32` (previously was `Infinity`) + * Remove link renderization in html while using `res.redirect` * deps: path-to-regexp@0.1.10 - Adds support for named matching groups in the routes using a regex - Adds backtracking protection to parameters without regexes defined diff --git a/package.json b/package.json index 87cf10be9c2..4c0fea2d2e5 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index e07432c86c3..537fb797e75 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -212,7 +212,7 @@ describe('express.urlencoded()', function () { it('should parse deep object', function (done) { var str = 'foo' - for (var i = 0; i < 500; i++) { + for (var i = 0; i < 32; i++) { str += '[p]' } @@ -230,7 +230,7 @@ describe('express.urlencoded()', function () { var depth = 0 var ref = obj.foo while ((ref = ref.p)) { depth++ } - assert.strictEqual(depth, 500) + assert.strictEqual(depth, 32) }) .expect(200, done) }) From 9ebe5d500d22cbb2b8aaa73446866b084c747971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 10 Sep 2024 02:46:25 +0200 Subject: [PATCH 769/889] feat: upgrade to send@0.19.0 (#5928) --- History.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 904db45b233..9f47885e3d2 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,7 @@ unreleased ========== + * deps: send@0.19.0 + * Remove link renderization in html while redirecting * deps: body-parser@0.6.0 * add `depth` option to customize the depth level in the parser * IMPORTANT: The default `depth` level for parsing URL-encoded data is now `32` (previously was `Infinity`) diff --git a/package.json b/package.json index 4c0fea2d2e5..1dc8c5b70cb 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", + "send": "0.19.0", "serve-static": "1.15.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", From 4c9ddc1c47bf579e55c2fe837d76a952e9fd8959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 10 Sep 2024 03:24:32 +0200 Subject: [PATCH 770/889] feat: upgrade to serve-static@0.16.0 --- History.md | 2 ++ package.json | 2 +- test/express.static.js | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 9f47885e3d2..3fe5fc7aaf7 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,7 @@ unreleased ========== + * deps: serve-static@0.16.0 + * Remove link renderization in html while redirecting * deps: send@0.19.0 * Remove link renderization in html while redirecting * deps: body-parser@0.6.0 diff --git a/package.json b/package.json index 1dc8c5b70cb..e9045763b01 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", - "serve-static": "1.15.0", + "serve-static": "1.16.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", diff --git a/test/express.static.js b/test/express.static.js index 245fd5929cc..23e607ed933 100644 --- a/test/express.static.js +++ b/test/express.static.js @@ -486,7 +486,7 @@ describe('express.static()', function () { request(this.app) .get('/users') .expect('Location', '/users/') - .expect(301, //, done) + .expect(301, /\/users\//, done) }) it('should redirect directories with query string', function (done) { @@ -508,7 +508,7 @@ describe('express.static()', function () { .get('/snow') .expect('Location', '/snow%20%E2%98%83/') .expect('Content-Type', /html/) - .expect(301, />Redirecting to \/snow%20%E2%98%83\/<\/a>Redirecting to \/snow%20%E2%98%83\/ Date: Tue, 10 Sep 2024 03:32:10 +0200 Subject: [PATCH 771/889] 4.20.0 --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 3fe5fc7aaf7..887a38f182d 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -unreleased +4.20.0 / 2024-09-10 ========== * deps: serve-static@0.16.0 * Remove link renderization in html while redirecting diff --git a/package.json b/package.json index e9045763b01..bffa70a6f1c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "4.19.2", + "version": "4.20.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 6c98f80b6ac95b90cff5da6857be4fe21d5e9c4e Mon Sep 17 00:00:00 2001 From: ctcpip Date: Mon, 9 Sep 2024 21:32:49 -0500 Subject: [PATCH 772/889] =?UTF-8?q?=F0=9F=94=A7=20update=20CI,=20remove=20?= =?UTF-8?q?unsupported=20versions,=20clean=20up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 6 +- .github/workflows/legacy.yml | 168 +++++++++++++---------------------- 2 files changed, 64 insertions(+), 110 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 150b67c3db0..e73fbce8cae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: node-version: [18, 19, 20, 21, 22] # Node.js release schedule: https://nodejs.org/en/about/releases/ - name: Node.js ${{ matrix.node-version }} + name: Node.js ${{ matrix.node-version }} - ${{matrix.os}} runs-on: ${{ matrix.os }} steps: @@ -59,10 +59,6 @@ jobs: with: node-version: ${{ matrix.node-version }} - - name: Npm version fixes - if: ${{matrix.npm-version != ''}} - run: npm install -g ${{ matrix.npm-version }} - - name: Configure npm loglevel run: | npm config set loglevel error diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 2d9d50440de..d26d6df34d2 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -1,120 +1,78 @@ name: legacy on: -- pull_request -- push + push: + branches: + - master + - develop + - '4.x' + - '5.x' + - '5.0' + paths-ignore: + - '*.md' + pull_request: + paths-ignore: + - '*.md' + +# Cancel in progress workflows +# in the scenario where we already had a run going for that PR/branch/tag but then triggered a new run +concurrency: + group: "${{ github.workflow }} ✨ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}" + cancel-in-progress: true jobs: test: - runs-on: ubuntu-latest strategy: fail-fast: false matrix: - name: - - Node.js 11.x - - Node.js 12.x - - Node.js 13.x - - Node.js 14.x - - Node.js 15.x - - Node.js 16.x - - Node.js 17.x - - include: - - name: Node.js 11.x - node-version: "11.15" - npm-i: mocha@8.4.0 - - - name: Node.js 12.x - node-version: "12.22" - npm-i: mocha@9.2.2 - - - name: Node.js 13.x - node-version: "13.14" - npm-i: mocha@9.2.2 + os: [ubuntu-latest, windows-latest] + node-version: [16, 17] + # Node.js release schedule: https://nodejs.org/en/about/releases/ - - name: Node.js 14.x - node-version: "14.20" - - - name: Node.js 15.x - node-version: "15.14" - - - name: Node.js 16.x - node-version: "16.20" - - - name: Node.js 17.x - node-version: "17.9" + name: Node.js ${{ matrix.node-version }} - ${{matrix.os}} + runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 - - - name: Install Node.js ${{ matrix.node-version }} - shell: bash -eo pipefail -l {0} - run: | - nvm install --default ${{ matrix.node-version }} - dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" - - - name: Configure npm - run: | - npm config set loglevel error - if [[ "$(npm config get package-lock)" == "true" ]]; then - npm config set package-lock false - else - npm config set shrinkwrap false - fi - - - name: Install npm module(s) ${{ matrix.npm-i }} - run: npm install --save-dev ${{ matrix.npm-i }} - if: matrix.npm-i != '' - - - name: Remove non-test dependencies - run: npm rm --silent --save-dev connect-redis - - - name: Setup Node.js version-specific dependencies - shell: bash - run: | - # eslint for linting - # - remove on Node.js < 12 - if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then - node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \ - grep -E '^eslint(-|$)' | \ - sort -r | \ - xargs -n1 npm rm --silent --save-dev - fi - - - name: Install Node.js dependencies - run: npm install - - - name: List environment - id: list_env - shell: bash - run: | - echo "node@$(node -v)" - echo "npm@$(npm -v)" - npm -s ls ||: - (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT" - - - name: Run tests - shell: bash - run: | - npm run test-ci - cp coverage/lcov.info "coverage/${{ matrix.name }}.lcov" - - - name: Lint code - if: steps.list_env.outputs.eslint != '' - run: npm run lint - - - name: Collect code coverage - run: | - mv ./coverage "./${{ matrix.name }}" - mkdir ./coverage - mv "./${{ matrix.name }}" "./coverage/${{ matrix.name }}" - - - name: Upload code coverage - uses: actions/upload-artifact@v3 - with: - name: coverage - path: ./coverage - retention-days: 1 + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Configure npm loglevel + run: | + npm config set loglevel error + shell: bash + + - name: Install dependencies + run: npm install + + - name: Output Node and NPM versions + run: | + echo "Node.js version: $(node -v)" + echo "NPM version: $(npm -v)" + + - name: Run tests + shell: bash + run: | + npm run test-ci + cp coverage/lcov.info "coverage/${{ matrix.node-version }}.lcov" + + - name: Collect code coverage + run: | + mv ./coverage "./${{ matrix.node-version }}" + mkdir ./coverage + mv "./${{ matrix.node-version }}" "./coverage/${{ matrix.node-version }}" + + - name: Upload code coverage + uses: actions/upload-artifact@v3 + with: + name: coverage + path: ./coverage + retention-days: 1 coverage: needs: test From bdd81f8670975ef30fd49e92513ef48d35029eaf Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Mon, 9 Sep 2024 20:28:55 -0700 Subject: [PATCH 773/889] Delete `back` as a magic string (#5933) --- History.md | 1 + examples/auth/index.js | 2 +- examples/cookies/index.js | 4 +-- examples/route-separation/user.js | 2 +- lib/response.js | 15 +------- test/res.location.js | 58 ------------------------------- 6 files changed, 6 insertions(+), 76 deletions(-) diff --git a/History.md b/History.md index 63efe1234f3..c11ef63a8a3 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,7 @@ unreleased * will throw a `RangeError: Invalid status code: ${code}. Status code must be greater than 99 and less than 1000.` for inputs outside this range * will throw a `TypeError: Invalid status code: ${code}. Status code must be an integer.` for non integer inputs * deps: send@1.0.0 + * `res.redirect('back')` and `res.location('back')` is no longer a supported magic string, explicitly use `req.get('Referrer') || '/'`. * change: - `res.clearCookie` will ignore user provided `maxAge` and `expires` options * deps: cookie-signature@^1.2.1 diff --git a/examples/auth/index.js b/examples/auth/index.js index 2859545c549..2884ca4e170 100644 --- a/examples/auth/index.js +++ b/examples/auth/index.js @@ -116,7 +116,7 @@ app.post('/login', function (req, res, next) { req.session.success = 'Authenticated as ' + user.name + ' click to logout. ' + ' You may now access /restricted.'; - res.redirect('back'); + res.redirect(req.get('Referrer') || '/'); }); } else { req.session.error = 'Authentication failed, please check your ' diff --git a/examples/cookies/index.js b/examples/cookies/index.js index 8bca73ff97a..0620cb40e45 100644 --- a/examples/cookies/index.js +++ b/examples/cookies/index.js @@ -33,7 +33,7 @@ app.get('/', function(req, res){ app.get('/forget', function(req, res){ res.clearCookie('remember'); - res.redirect('back'); + res.redirect(req.get('Referrer') || '/'); }); app.post('/', function(req, res){ @@ -43,7 +43,7 @@ app.post('/', function(req, res){ res.cookie('remember', 1, { maxAge: minute }) } - res.redirect('back'); + res.redirect(req.get('Referrer') || '/'); }); /* istanbul ignore next */ diff --git a/examples/route-separation/user.js b/examples/route-separation/user.js index 1c2aec7cd23..bc6fbd7baf3 100644 --- a/examples/route-separation/user.js +++ b/examples/route-separation/user.js @@ -43,5 +43,5 @@ exports.update = function(req, res){ var user = req.body.user; req.user.name = user.name; req.user.email = user.email; - res.redirect('back'); + res.redirect(req.get('Referrer') || '/'); }; diff --git a/lib/response.js b/lib/response.js index 4035d4fb06f..937e9858535 100644 --- a/lib/response.js +++ b/lib/response.js @@ -785,26 +785,13 @@ res.cookie = function (name, value, options) { */ res.location = function location(url) { - var loc; - - // "back" is an alias for the referrer - if (url === 'back') { - loc = this.req.get('Referrer') || '/'; - } else { - loc = String(url); - } - - return this.set('Location', encodeUrl(loc)); + return this.set('Location', encodeUrl(url)); }; /** * Redirect to the given `url` with optional response `status` * defaulting to 302. * - * The resulting `url` is determined by `res.location()`, so - * it will play nicely with mounted apps, relative paths, - * `"back"` etc. - * * Examples: * * res.redirect('/foo/bar'); diff --git a/test/res.location.js b/test/res.location.js index 7e1fbeba736..fb03221d7a4 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -46,64 +46,6 @@ describe('res', function(){ .expect(200, done) }) - describe('when url is "back"', function () { - it('should set location from "Referer" header', function (done) { - var app = express() - - app.use(function (req, res) { - res.location('back').end() - }) - - request(app) - .get('/') - .set('Referer', '/some/page.html') - .expect('Location', '/some/page.html') - .expect(200, done) - }) - - it('should set location from "Referrer" header', function (done) { - var app = express() - - app.use(function (req, res) { - res.location('back').end() - }) - - request(app) - .get('/') - .set('Referrer', '/some/page.html') - .expect('Location', '/some/page.html') - .expect(200, done) - }) - - it('should prefer "Referrer" header', function (done) { - var app = express() - - app.use(function (req, res) { - res.location('back').end() - }) - - request(app) - .get('/') - .set('Referer', '/some/page1.html') - .set('Referrer', '/some/page2.html') - .expect('Location', '/some/page2.html') - .expect(200, done) - }) - - it('should set the header to "/" without referrer', function (done) { - var app = express() - - app.use(function (req, res) { - res.location('back').end() - }) - - request(app) - .get('/') - .expect('Location', '/') - .expect(200, done) - }) - }) - it('should encode data uri1', function (done) { var app = express() app.use(function (req, res) { From fed8c2a8857a30b91e07a37f739aee18e756853f Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 9 Sep 2024 22:32:07 -0500 Subject: [PATCH 774/889] fix(deps): body-parser@^2.0.1 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index c11ef63a8a3..b27572ee945 100644 --- a/History.md +++ b/History.md @@ -22,6 +22,7 @@ unreleased * deps: content-disposition@^1.0.0 * deps: finalhandler@^2.0.0 * deps: fresh@^2.0.0 +* deps: body-parser@^2.0.1 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index 0367f403373..d6f12698c28 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ ], "dependencies": { "accepts": "^2.0.0", - "body-parser": "2.0.0-beta.2", + "body-parser": "^2.0.1", "content-disposition": "^1.0.0", "content-type": "~1.0.4", "cookie": "0.6.0", From b3906cbdded224554ce1c778996d77b5d2a15ebc Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 9 Sep 2024 23:32:19 -0500 Subject: [PATCH 775/889] fix(deps): serve-static@^2.1.0 --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index b27572ee945..4cec5788a5a 100644 --- a/History.md +++ b/History.md @@ -13,7 +13,7 @@ unreleased * deps: cookie-signature@^1.2.1 * deps: debug@4.3.6 * deps: merge-descriptors@^2.0.0 -* deps: serve-static@^2.0.0 +* deps: serve-static@^2.1.0 * deps: qs@6.13.0 * deps: accepts@^2.0.0 * deps: mime-types@^3.0.0 diff --git a/package.json b/package.json index d6f12698c28..d305b7ef446 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "router": "^2.0.0", "safe-buffer": "5.2.1", "send": "^1.0.0", - "serve-static": "^2.0.0", + "serve-static": "^2.1.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "^2.0.0", From 0c49926a9b7aff8bbca2a40d2549db0b41bab5b3 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 9 Sep 2024 23:34:03 -0500 Subject: [PATCH 776/889] fix(deps): send@^1.1.0 --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 4cec5788a5a..b87d130f33d 100644 --- a/History.md +++ b/History.md @@ -23,6 +23,7 @@ unreleased * deps: finalhandler@^2.0.0 * deps: fresh@^2.0.0 * deps: body-parser@^2.0.1 +* deps: send@^1.1.0 5.0.0-beta.3 / 2024-03-25 ========================= diff --git a/package.json b/package.json index d305b7ef446..c062162ddc2 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "range-parser": "~1.2.1", "router": "^2.0.0", "safe-buffer": "5.2.1", - "send": "^1.0.0", + "send": "^1.1.0", "serve-static": "^2.1.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", From 344b022fc7ed95cf07b46e097935e61151fd585f Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Mon, 9 Sep 2024 23:35:36 -0500 Subject: [PATCH 777/889] 5.0.0 closes #2237 closes https://github.com/expressjs/discussions/issues/233 --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index b87d130f33d..2592c976bf5 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,4 @@ -unreleased +5.0.0 / 2024-09-10 ========================= * remove: - `path-is-absolute` dependency - use `path.isAbsolute` instead diff --git a/package.json b/package.json index c062162ddc2..c1eff78d974 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-beta.3", + "version": "5.0.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 6340d1509f83e436f4484be1fb3a6d155ebb6a38 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 30 Sep 2024 16:49:26 -0400 Subject: [PATCH 778/889] remove --bail from test script (#5962) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c1eff78d974..3a10ae4dc5b 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ ], "scripts": { "lint": "eslint .", - "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/", + "test": "mocha --require test/support/env --reporter spec --check-leaks test/ test/acceptance/", "test-ci": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=lcovonly --reporter=text npm test", "test-cov": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=html --reporter=text npm test", "test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/" From 3e1a1cedb237568c2a34944a0f4e72eff3a0b40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Sun, 6 Oct 2024 17:34:26 +0200 Subject: [PATCH 779/889] Add @bjohansebas to the triage team (#6009) Co-authored-by: Sebastian Beltran --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index bc108d55fc0..32c0c7430d3 100644 --- a/Readme.md +++ b/Readme.md @@ -192,6 +192,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) ### Triagers * [aravindvnair99](https://github.com/aravindvnair99) - **Aravind Nair** +* [bjohansebas](https://github.com/bjohansebas) - **Sebastian Beltran** * [carpasse](https://github.com/carpasse) - **Carlos Serrano** * [CBID2](https://github.com/CBID2) - **Christine Belzie** * [enyoghasim](https://github.com/enyoghasim) - **David Enyoghasim** From 2cbf22721defccbb4f29f460ad007002ca87bd72 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Sun, 6 Oct 2024 14:06:57 -0700 Subject: [PATCH 780/889] Link and update captains (#6013) --- Contributing.md | 124 ++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/Contributing.md b/Contributing.md index 1654cee02f2..1055a7ea89d 100644 --- a/Contributing.md +++ b/Contributing.md @@ -141,68 +141,68 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ ### Active Projects and Captains -- `expressjs/badgeboard`: @wesleytodd -- `expressjs/basic-auth-connect`: N/A -- `expressjs/body-parser`: @wesleytodd, @jonchurch -- `expressjs/compression`: N/A -- `expressjs/connect-multiparty`: N/A -- `expressjs/cookie-parser`: @wesleytodd, @UlisesGascon -- `expressjs/cookie-session`: N/A -- `expressjs/cors`: @jonchurch -- `expressjs/discussions`: @wesleytodd -- `expressjs/errorhandler`: N/A -- `expressjs/express-paginate`: N/A -- `expressjs/express`: @wesleytodd -- `expressjs/expressjs.com`: @crandmck, @jonchurch -- `expressjs/flash`: N/A -- `expressjs/generator`: @wesleytodd -- `expressjs/method-override`: N/A -- `expressjs/morgan`: @jonchurch -- `expressjs/multer`: @LinusU -- `expressjs/response-time`: @blakeembrey -- `expressjs/serve-favicon`: N/A -- `expressjs/serve-index`: N/A -- `expressjs/serve-static`: N/A -- `expressjs/session`: N/A -- `expressjs/statusboard`: @wesleytodd -- `expressjs/timeout`: N/A -- `expressjs/vhost`: N/A -- `jshttp/accepts`: @blakeembrey -- `jshttp/basic-auth`: @blakeembrey -- `jshttp/compressible`: @blakeembrey -- `jshttp/content-disposition`: @blakeembrey -- `jshttp/content-type`: @blakeembrey -- `jshttp/cookie`: @wesleytodd -- `jshttp/etag`: @blakeembrey -- `jshttp/forwarded`: @blakeembrey -- `jshttp/fresh`: @blakeembrey -- `jshttp/http-assert`: @wesleytodd, @jonchurch -- `jshttp/http-errors`: @wesleytodd, @jonchurch -- `jshttp/media-typer`: @blakeembrey -- `jshttp/methods`: @blakeembrey -- `jshttp/mime-db`: @blakeembrey, @UlisesGascon -- `jshttp/mime-types`: @blakeembrey, @UlisesGascon -- `jshttp/negotiator`: @blakeembrey -- `jshttp/on-finished`: @wesleytodd -- `jshttp/on-headers`: @blakeembrey -- `jshttp/proxy-addr`: @wesleytodd -- `jshttp/range-parser`: @blakeembrey -- `jshttp/statuses`: @blakeembrey -- `jshttp/type-is`: @blakeembrey -- `jshttp/vary`: @blakeembrey -- `pillarjs/cookies`: @blakeembrey -- `pillarjs/csrf`: N/A -- `pillarjs/encodeurl`: @blakeembrey -- `pillarjs/finalhandler`: @wesleytodd -- `pillarjs/hbs`: N/A -- `pillarjs/multiparty`: @blakeembrey -- `pillarjs/parseurl`: @blakeembrey -- `pillarjs/path-to-regexp`: @blakeembrey -- `pillarjs/request`: @wesleytodd -- `pillarjs/resolve-path`: @blakeembrey -- `pillarjs/router`: @blakeembrey -- `pillarjs/send`: @blakeembrey -- `pillarjs/understanding-csrf`: N/A +- [`expressjs/badgeboard`](https://github.com/expressjs/badgeboard): @wesleytodd +- [`expressjs/basic-auth-connect`](https://github.com/expressjs/basic-auth-connect): @UlisesGascon +- [`expressjs/body-parser`](https://github.com/expressjs/body-parser): @wesleytodd, @jonchurch +- [`expressjs/compression`](https://github.com/expressjs/compression): N/A +- [`expressjs/connect-multiparty`](https://github.com/expressjs/connect-multiparty): N/A +- [`expressjs/cookie-parser`](https://github.com/expressjs/cookie-parser): @wesleytodd, @UlisesGascon +- [`expressjs/cookie-session`](https://github.com/expressjs/cookie-session): N/A +- [`expressjs/cors`](https://github.com/expressjs/cors): @jonchurch +- [`expressjs/discussions`](https://github.com/expressjs/discussions): @wesleytodd +- [`expressjs/errorhandler`](https://github.com/expressjs/errorhandler): N/A +- [`expressjs/express-paginate`](https://github.com/expressjs/express-paginate): N/A +- [`expressjs/express`](https://github.com/expressjs/express): @wesleytodd +- [`expressjs/expressjs.com`](https://github.com/expressjs/expressjs.com): @crandmck, @jonchurch +- [`expressjs/flash`](https://github.com/expressjs/flash): N/A +- [`expressjs/generator`](https://github.com/expressjs/generator): @wesleytodd +- [`expressjs/method-override`](https://github.com/expressjs/method-override): N/A +- [`expressjs/morgan`](https://github.com/expressjs/morgan): @jonchurch +- [`expressjs/multer`](https://github.com/expressjs/multer): @LinusU +- [`expressjs/response-time`](https://github.com/expressjs/response-time): @UlisesGascon +- [`expressjs/serve-favicon`](https://github.com/expressjs/serve-favicon): N/A +- [`expressjs/serve-index`](https://github.com/expressjs/serve-index): N/A +- [`expressjs/serve-static`](https://github.com/expressjs/serve-static): N/A +- [`expressjs/session`](https://github.com/expressjs/session): N/A +- [`expressjs/statusboard`](https://github.com/expressjs/statusboard): @wesleytodd +- [`expressjs/timeout`](https://github.com/expressjs/timeout): N/A +- [`expressjs/vhost`](https://github.com/expressjs/vhost): N/A +- [`jshttp/accepts`](https://github.com/jshttp/accepts): @blakeembrey +- [`jshttp/basic-auth`](https://github.com/jshttp/basic-auth): @blakeembrey +- [`jshttp/compressible`](https://github.com/jshttp/compressible): @blakeembrey +- [`jshttp/content-disposition`](https://github.com/jshttp/content-disposition): @blakeembrey +- [`jshttp/content-type`](https://github.com/jshttp/content-type): @blakeembrey +- [`jshttp/cookie`](https://github.com/jshttp/cookie): @blakeembrey +- [`jshttp/etag`](https://github.com/jshttp/etag): @blakeembrey +- [`jshttp/forwarded`](https://github.com/jshttp/forwarded): @blakeembrey +- [`jshttp/fresh`](https://github.com/jshttp/fresh): @blakeembrey +- [`jshttp/http-assert`](https://github.com/jshttp/http-assert): @wesleytodd, @jonchurch +- [`jshttp/http-errors`](https://github.com/jshttp/http-errors): @wesleytodd, @jonchurch +- [`jshttp/media-typer`](https://github.com/jshttp/media-typer): @blakeembrey +- [`jshttp/methods`](https://github.com/jshttp/methods): @blakeembrey +- [`jshttp/mime-db`](https://github.com/jshttp/mime-db): @blakeembrey, @UlisesGascon +- [`jshttp/mime-types`](https://github.com/jshttp/mime-types): @blakeembrey, @UlisesGascon +- [`jshttp/negotiator`](https://github.com/jshttp/negotiator): @blakeembrey +- [`jshttp/on-finished`](https://github.com/jshttp/on-finished): @wesleytodd +- [`jshttp/on-headers`](https://github.com/jshttp/on-headers): @blakeembrey +- [`jshttp/proxy-addr`](https://github.com/jshttp/proxy-addr): @wesleytodd +- [`jshttp/range-parser`](https://github.com/jshttp/range-parser): @blakeembrey +- [`jshttp/statuses`](https://github.com/jshttp/statuses): @blakeembrey +- [`jshttp/type-is`](https://github.com/jshttp/type-is): @blakeembrey +- [`jshttp/vary`](https://github.com/jshttp/vary): @blakeembrey +- [`pillarjs/cookies`](https://github.com/pillarjs/cookies): @blakeembrey +- [`pillarjs/csrf`](https://github.com/pillarjs/csrf): N/A +- [`pillarjs/encodeurl`](https://github.com/pillarjs/encodeurl): @blakeembrey +- [`pillarjs/finalhandler`](https://github.com/pillarjs/finalhandler): @wesleytodd +- [`pillarjs/hbs`](https://github.com/pillarjs/hbs): N/A +- [`pillarjs/multiparty`](https://github.com/pillarjs/multiparty): @blakeembrey +- [`pillarjs/parseurl`](https://github.com/pillarjs/parseurl): @blakeembrey +- [`pillarjs/path-to-regexp`](https://github.com/pillarjs/path-to-regexp): @blakeembrey +- [`pillarjs/request`](https://github.com/pillarjs/request): @wesleytodd +- [`pillarjs/resolve-path`](https://github.com/pillarjs/resolve-path): @blakeembrey +- [`pillarjs/router`](https://github.com/pillarjs/router): @wesleytodd +- [`pillarjs/send`](https://github.com/pillarjs/send): @blakeembrey +- [`pillarjs/understanding-csrf`](https://github.com/pillarjs/understanding-csrf): N/A ### Current Initiative Captains From 2027b87a27396d418f7848cc7fc4c353d798c3d9 Mon Sep 17 00:00:00 2001 From: Josh Buker Date: Tue, 8 Oct 2024 10:10:56 +0000 Subject: [PATCH 781/889] fix(deps): cookie@0.7.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ulises Gascón --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 2592c976bf5..1bf13282002 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +========== + +* Update `cookie` semver lock to address CVE-2024-47764 + 5.0.0 / 2024-09-10 ========================= * remove: diff --git a/package.json b/package.json index 3a10ae4dc5b..473f6a8612c 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "body-parser": "^2.0.1", "content-disposition": "^1.0.0", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "^1.2.1", "debug": "4.3.6", "depd": "2.0.0", From d14b2de782c16fbef39541c9009b01bd6ae90b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 8 Oct 2024 21:31:10 +0200 Subject: [PATCH 782/889] 5.0.1 PR-URL: https://github.com/expressjs/express/pull/6032 --- History.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 1bf13282002..1e3f939c611 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,7 @@ -unreleased +5.0.1 / 2024-10-08 ========== -* Update `cookie` semver lock to address CVE-2024-47764 +* Update `cookie` semver lock to address [CVE-2024-47764](https://nvd.nist.gov/vuln/detail/CVE-2024-47764) 5.0.0 / 2024-09-10 ========================= diff --git a/package.json b/package.json index 473f6a8612c..87335adf7a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0", + "version": "5.0.1", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From a46cfdc37f5e422db7ce6f12d321eb79694c1e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Wed, 9 Oct 2024 21:40:05 +0200 Subject: [PATCH 783/889] docs: update captains PR-URL: https://github.com/expressjs/express/pull/6027 --- Contributing.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Contributing.md b/Contributing.md index 1055a7ea89d..565eb13678b 100644 --- a/Contributing.md +++ b/Contributing.md @@ -144,29 +144,29 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - [`expressjs/badgeboard`](https://github.com/expressjs/badgeboard): @wesleytodd - [`expressjs/basic-auth-connect`](https://github.com/expressjs/basic-auth-connect): @UlisesGascon - [`expressjs/body-parser`](https://github.com/expressjs/body-parser): @wesleytodd, @jonchurch -- [`expressjs/compression`](https://github.com/expressjs/compression): N/A -- [`expressjs/connect-multiparty`](https://github.com/expressjs/connect-multiparty): N/A +- [`expressjs/compression`](https://github.com/expressjs/compression): @ulisesGascon +- [`expressjs/connect-multiparty`](https://github.com/expressjs/connect-multiparty): @ulisesGascon - [`expressjs/cookie-parser`](https://github.com/expressjs/cookie-parser): @wesleytodd, @UlisesGascon -- [`expressjs/cookie-session`](https://github.com/expressjs/cookie-session): N/A +- [`expressjs/cookie-session`](https://github.com/expressjs/cookie-session): @ulisesGascon - [`expressjs/cors`](https://github.com/expressjs/cors): @jonchurch - [`expressjs/discussions`](https://github.com/expressjs/discussions): @wesleytodd -- [`expressjs/errorhandler`](https://github.com/expressjs/errorhandler): N/A -- [`expressjs/express-paginate`](https://github.com/expressjs/express-paginate): N/A -- [`expressjs/express`](https://github.com/expressjs/express): @wesleytodd +- [`expressjs/errorhandler`](https://github.com/expressjs/errorhandler): @ulisesGascon +- [`expressjs/express-paginate`](https://github.com/expressjs/express-paginate): @ulisesGascon +- [`expressjs/express`](https://github.com/expressjs/express): @wesleytodd, @ulisesGascon - [`expressjs/expressjs.com`](https://github.com/expressjs/expressjs.com): @crandmck, @jonchurch -- [`expressjs/flash`](https://github.com/expressjs/flash): N/A +- [`expressjs/flash`](https://github.com/expressjs/flash): @ulisesGascon - [`expressjs/generator`](https://github.com/expressjs/generator): @wesleytodd -- [`expressjs/method-override`](https://github.com/expressjs/method-override): N/A +- [`expressjs/method-override`](https://github.com/expressjs/method-override): @ulisesGascon - [`expressjs/morgan`](https://github.com/expressjs/morgan): @jonchurch - [`expressjs/multer`](https://github.com/expressjs/multer): @LinusU - [`expressjs/response-time`](https://github.com/expressjs/response-time): @UlisesGascon -- [`expressjs/serve-favicon`](https://github.com/expressjs/serve-favicon): N/A -- [`expressjs/serve-index`](https://github.com/expressjs/serve-index): N/A -- [`expressjs/serve-static`](https://github.com/expressjs/serve-static): N/A -- [`expressjs/session`](https://github.com/expressjs/session): N/A +- [`expressjs/serve-favicon`](https://github.com/expressjs/serve-favicon): @ulisesGascon +- [`expressjs/serve-index`](https://github.com/expressjs/serve-index): @ulisesGascon +- [`expressjs/serve-static`](https://github.com/expressjs/serve-static): @ulisesGascon +- [`expressjs/session`](https://github.com/expressjs/session): @ulisesGascon - [`expressjs/statusboard`](https://github.com/expressjs/statusboard): @wesleytodd -- [`expressjs/timeout`](https://github.com/expressjs/timeout): N/A -- [`expressjs/vhost`](https://github.com/expressjs/vhost): N/A +- [`expressjs/timeout`](https://github.com/expressjs/timeout): @ulisesGascon +- [`expressjs/vhost`](https://github.com/expressjs/vhost): @ulisesGascon - [`jshttp/accepts`](https://github.com/jshttp/accepts): @blakeembrey - [`jshttp/basic-auth`](https://github.com/jshttp/basic-auth): @blakeembrey - [`jshttp/compressible`](https://github.com/jshttp/compressible): @blakeembrey @@ -191,10 +191,10 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - [`jshttp/type-is`](https://github.com/jshttp/type-is): @blakeembrey - [`jshttp/vary`](https://github.com/jshttp/vary): @blakeembrey - [`pillarjs/cookies`](https://github.com/pillarjs/cookies): @blakeembrey -- [`pillarjs/csrf`](https://github.com/pillarjs/csrf): N/A +- [`pillarjs/csrf`](https://github.com/pillarjs/csrf): @ulisesGascon - [`pillarjs/encodeurl`](https://github.com/pillarjs/encodeurl): @blakeembrey - [`pillarjs/finalhandler`](https://github.com/pillarjs/finalhandler): @wesleytodd -- [`pillarjs/hbs`](https://github.com/pillarjs/hbs): N/A +- [`pillarjs/hbs`](https://github.com/pillarjs/hbs): @ulisesGascon - [`pillarjs/multiparty`](https://github.com/pillarjs/multiparty): @blakeembrey - [`pillarjs/parseurl`](https://github.com/pillarjs/parseurl): @blakeembrey - [`pillarjs/path-to-regexp`](https://github.com/pillarjs/path-to-regexp): @blakeembrey @@ -202,7 +202,7 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - [`pillarjs/resolve-path`](https://github.com/pillarjs/resolve-path): @blakeembrey - [`pillarjs/router`](https://github.com/pillarjs/router): @wesleytodd - [`pillarjs/send`](https://github.com/pillarjs/send): @blakeembrey -- [`pillarjs/understanding-csrf`](https://github.com/pillarjs/understanding-csrf): N/A +- [`pillarjs/understanding-csrf`](https://github.com/pillarjs/understanding-csrf): @ulisesGascon ### Current Initiative Captains From ab022403361cc94fa7ccfd836e54378f0a20b20f Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sun, 20 Oct 2024 12:25:56 -0500 Subject: [PATCH 784/889] build: Node.js 23.0 (#6075) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e73fbce8cae..5668ed2f22b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - node-version: [18, 19, 20, 21, 22] + node-version: [18, 19, 20, 21, 22, 23] # Node.js release schedule: https://nodejs.org/en/about/releases/ name: Node.js ${{ matrix.node-version }} - ${{matrix.os}} From 94546a3cc549a93edadea3b698097509c7ef3c64 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sun, 20 Oct 2024 12:58:49 -0500 Subject: [PATCH 785/889] docs: add funding (#6064) --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 87335adf7a0..c90a8513115 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,10 @@ "license": "MIT", "repository": "expressjs/express", "homepage": "http://expressjs.com/", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + }, "keywords": [ "express", "framework", From 082d6d1253c590cb3c8920327c76e70328a1bd80 Mon Sep 17 00:00:00 2001 From: Chris de Almeida Date: Sun, 20 Oct 2024 13:06:49 -0500 Subject: [PATCH 786/889] test: add discarded middleware test (#5819) --- test/app.router.js | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/app.router.js b/test/app.router.js index 11742d98a74..1db40042a1c 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -1156,6 +1156,56 @@ describe('app.router', function(){ var app = express(); assert.strictEqual(app.get('/', function () {}), app) }) + + it('should should not use disposed router/middleware', function(done){ + // more context: https://github.com/expressjs/express/issues/5743#issuecomment-2277148412 + + var app = express(); + var router = new express.Router(); + + router.use(function(req, res, next){ + res.setHeader('old', 'foo'); + next(); + }); + + app.use(function (req, res, next) { + return router.handle(req, res, next); + }); + + app.get('/', function(req, res, next){ + res.send('yee'); + next(); + }); + + request(app) + .get('/') + .expect('old', 'foo') + .expect(function(res) { + if (typeof res.headers['new'] !== 'undefined') { + throw new Error('`new` header should not be present'); + } + }) + .expect(200, 'yee', function(err, res) { + if (err) return done(err); + + router = new express.Router(); + + router.use(function(req, res, next){ + res.setHeader('new', 'bar'); + next(); + }); + + request(app) + .get('/') + .expect('new', 'bar') + .expect(function(res) { + if (typeof res.headers['old'] !== 'undefined') { + throw new Error('`old` header should not be present'); + } + }) + .expect(200, 'yee', done); + }); + }) }) function supportsRegexp(source) { From b274047a5d38db1af0adc4e7ecba39a3a9f8f730 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sun, 20 Oct 2024 13:07:22 -0500 Subject: [PATCH 787/889] docs: update homepage link http to https (#5920) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ulises Gascón --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c90a8513115..017544db611 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ ], "license": "MIT", "repository": "expressjs/express", - "homepage": "http://expressjs.com/", + "homepage": "https://expressjs.com/", "funding": { "type": "opencollective", "url": "https://opencollective.com/express" From 508c74091f9a75277184e06793b35fe6ab2b8a42 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sun, 20 Oct 2024 13:09:00 -0500 Subject: [PATCH 788/889] docs: update readme (#5994) --- Readme.md | 80 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/Readme.md b/Readme.md index 32c0c7430d3..47c72f9bdfd 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ -[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/) +[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](https://expressjs.com/) -**Fast, unopinionated, minimalist web framework for [Node.js](http://nodejs.org).** +**Fast, unopinionated, minimalist web framework for [Node.js](https://nodejs.org).** **This project has a [Code of Conduct][].** @@ -26,10 +26,11 @@ ```js -const express = require('express') +import express from 'express' + const app = express() -app.get('/', function (req, res) { +app.get('/', (req, res) => { res.send('Hello World') }) @@ -42,7 +43,7 @@ This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Before installing, [download and install Node.js](https://nodejs.org/en/download/). -Node.js 0.10 or higher is required. +Node.js 18 or higher is required. If this is a brand new project, make sure to create a `package.json` first with the [`npm init` command](https://docs.npmjs.com/creating-a-package-json-file). @@ -50,11 +51,11 @@ the [`npm init` command](https://docs.npmjs.com/creating-a-package-json-file). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): -```console -$ npm install express +```bash +npm install express ``` -Follow [our installing guide](http://expressjs.com/en/starter/installing.html) +Follow [our installing guide](https://expressjs.com/en/starter/installing.html) for more information. ## Features @@ -69,14 +70,11 @@ for more information. ## Docs & Community - * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)] - * [#express](https://web.libera.chat/#express) on [Libera Chat](https://libera.chat) IRC + * [Website and Documentation](https://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)] * [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules - * Visit the [Wiki](https://github.com/expressjs/express/wiki) - * [Google Group](https://groups.google.com/group/express-js) for discussion - * [Gitter](https://gitter.im/expressjs/express) for support and discussion + * [Github Discussions](https://github.com/expressjs/discussions) for discussion on the development and usage of Express -**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x). +**PROTIP** Be sure to read the [migration guide to v5](https://expressjs.com/en/guide/migrating-5) ## Quick Start @@ -84,26 +82,26 @@ for more information. Install the executable. The executable's major version will match Express's: -```console -$ npm install -g express-generator@4 +```bash +npm install -g express-generator@4 ``` Create the app: -```console -$ express /tmp/foo && cd /tmp/foo +```bash +express /tmp/foo && cd /tmp/foo ``` Install dependencies: -```console -$ npm install +```bash +npm install ``` Start the server: -```console -$ npm start +```bash +npm start ``` View the website at: http://localhost:3000 @@ -115,29 +113,32 @@ $ npm start HTTP APIs. Express does not force you to use any specific ORM or template engine. With support for over - 14 template engines via [Consolidate.js](https://github.com/tj/consolidate.js), + 14 template engines via [@ladjs/consolidate](https://github.com/ladjs/consolidate), you can quickly craft your perfect framework. ## Examples - To view the examples, clone the Express repo and install the dependencies: + To view the examples, clone the Express repository: + +```bash +git clone https://github.com/expressjs/express.git --depth 1 && cd express +``` + + Then install the dependencies: -```console -$ git clone https://github.com/expressjs/express.git --depth 1 -$ cd express -$ npm install +```bash +npm install ``` Then run whichever example you want: -```console -$ node examples/content-negotiation +```bash +node examples/content-negotiation ``` ## Contributing [![Linux Build][github-actions-ci-image]][github-actions-ci-url] - [![Windows Build][appveyor-image]][appveyor-url] [![Test Coverage][coveralls-image]][coveralls-url] The Express.js project welcomes all constructive contributions. Contributions take many forms, @@ -152,11 +153,16 @@ If you discover a security vulnerability in Express, please see [Security Polici ### Running Tests -To run the test suite, first install the dependencies, then run `npm test`: +To run the test suite, first install the dependencies: + +```bash +npm install +``` + +Then run `npm test`: -```console -$ npm install -$ npm test +```bash +npm test ``` ## People @@ -244,11 +250,9 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) [MIT](LICENSE) -[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/express/master?label=windows -[appveyor-url]: https://ci.appveyor.com/project/dougwilson/express [coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/express/master [coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master -[github-actions-ci-image]: https://badgen.net/github/checks/expressjs/express/master?label=linux +[github-actions-ci-image]: https://badgen.net/github/checks/expressjs/express/master?label=CI [github-actions-ci-url]: https://github.com/expressjs/express/actions/workflows/ci.yml [npm-downloads-image]: https://badgen.net/npm/dm/express [npm-downloads-url]: https://npmcharts.com/compare/express?minimal=true From e162764f0f9c49eb6dc7d3d46cd99ac0e28e1948 Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Sun, 20 Oct 2024 11:10:23 -0700 Subject: [PATCH 789/889] docs: add bjohansebas as repo captain for expressjs.com (#6058) --- Contributing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Contributing.md b/Contributing.md index 565eb13678b..ebb8bb19441 100644 --- a/Contributing.md +++ b/Contributing.md @@ -134,7 +134,7 @@ project for at least 6 months as a committer prior to the request. They should h helped with code contributions as well as triaging issues. They are also required to have 2FA enabled on both their GitHub and npm accounts. Any TC member or existing captain on the repo can nominate another committer to the captain role, submit a PR to -this doc, under `Current Project Captains` section (maintaining the sort order) with +this doc, in the **Active Project Captains** section (maintaining the sort order) with the project, their GitHub handle and npm username (if different). The PR will require at least 2 approvals from TC members and 2 weeks hold time to allow for comment and/or dissent. When the PR is merged, a TC member will add them to the proper GitHub/npm groups. @@ -153,7 +153,7 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - [`expressjs/errorhandler`](https://github.com/expressjs/errorhandler): @ulisesGascon - [`expressjs/express-paginate`](https://github.com/expressjs/express-paginate): @ulisesGascon - [`expressjs/express`](https://github.com/expressjs/express): @wesleytodd, @ulisesGascon -- [`expressjs/expressjs.com`](https://github.com/expressjs/expressjs.com): @crandmck, @jonchurch +- [`expressjs/expressjs.com`](https://github.com/expressjs/expressjs.com): @crandmck, @jonchurch, @bjohansebas - [`expressjs/flash`](https://github.com/expressjs/flash): @ulisesGascon - [`expressjs/generator`](https://github.com/expressjs/generator): @wesleytodd - [`expressjs/method-override`](https://github.com/expressjs/method-override): @ulisesGascon From 8cb53ea5c3329032a1db47be019b717d8350fb0e Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Tue, 22 Oct 2024 20:22:26 +0200 Subject: [PATCH 790/889] refactor: Remove Object.setPrototypeOf polyfill (#6081) --- History.md | 5 +++++ lib/application.js | 17 ++++++++--------- package.json | 1 - 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/History.md b/History.md index 1e3f939c611..ae5a167a696 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +unreleased +======================== + +* Remove `Object.setPrototypeOf` polyfill + 5.0.1 / 2024-10-08 ========== diff --git a/lib/application.js b/lib/application.js index ecfe2186db7..b19055ec829 100644 --- a/lib/application.js +++ b/lib/application.js @@ -25,7 +25,6 @@ var merge = require('utils-merge'); var resolve = require('path').resolve; var once = require('once') var Router = require('router'); -var setPrototypeOf = require('setprototypeof') /** * Module variables. @@ -117,10 +116,10 @@ app.defaultConfiguration = function defaultConfiguration() { } // inherit protos - setPrototypeOf(this.request, parent.request) - setPrototypeOf(this.response, parent.response) - setPrototypeOf(this.engines, parent.engines) - setPrototypeOf(this.settings, parent.settings) + Object.setPrototypeOf(this.request, parent.request) + Object.setPrototypeOf(this.response, parent.response) + Object.setPrototypeOf(this.engines, parent.engines) + Object.setPrototypeOf(this.settings, parent.settings) }); // setup locals @@ -168,8 +167,8 @@ app.handle = function handle(req, res, callback) { res.req = req; // alter the prototypes - setPrototypeOf(req, this.request) - setPrototypeOf(res, this.response) + Object.setPrototypeOf(req, this.request) + Object.setPrototypeOf(res, this.response) // setup locals if (!res.locals) { @@ -232,8 +231,8 @@ app.use = function use(fn) { router.use(path, function mounted_app(req, res, next) { var orig = req.app; fn.handle(req, res, function (err) { - setPrototypeOf(req, orig.request) - setPrototypeOf(res, orig.response) + Object.setPrototypeOf(req, orig.request) + Object.setPrototypeOf(res, orig.response) next(err); }); }); diff --git a/package.json b/package.json index 017544db611..a23e46022ee 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "safe-buffer": "5.2.1", "send": "^1.1.0", "serve-static": "^2.1.0", - "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "^2.0.0", "utils-merge": "1.0.1", From c70197ad33057e88565bd7bde6454f9225ead6cc Mon Sep 17 00:00:00 2001 From: Bhavya Dhiman Date: Sun, 27 Oct 2024 15:40:33 +0530 Subject: [PATCH 791/889] fix(buffer): use node:buffer instead of safe-buffer (#6071) Main Changes: - Removed dependency `safe-buffer@5.2.1` - Use `node:buffer` core library instead of safe-buffer --- lib/response.js | 2 +- lib/utils.js | 2 +- package.json | 1 - test/express.json.js | 2 +- test/express.raw.js | 2 +- test/express.static.js | 2 +- test/express.text.js | 2 +- test/express.urlencoded.js | 2 +- test/res.attachment.js | 2 +- test/res.download.js | 2 +- test/res.send.js | 2 +- test/res.sendFile.js | 2 +- test/support/utils.js | 2 +- test/utils.js | 2 +- 14 files changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/response.js b/lib/response.js index 937e9858535..29511a74e03 100644 --- a/lib/response.js +++ b/lib/response.js @@ -12,7 +12,7 @@ * @private */ -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var contentDisposition = require('content-disposition'); var createError = require('http-errors') var encodeUrl = require('encodeurl'); diff --git a/lib/utils.js b/lib/utils.js index f66760a17c0..67eacf274e8 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -12,7 +12,7 @@ * @api private */ -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var contentType = require('content-type'); var etag = require('etag'); var mime = require('mime-types') diff --git a/package.json b/package.json index a23e46022ee..54b4bb5704e 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "qs": "6.13.0", "range-parser": "~1.2.1", "router": "^2.0.0", - "safe-buffer": "5.2.1", "send": "^1.1.0", "serve-static": "^2.1.0", "statuses": "2.0.1", diff --git a/test/express.json.js b/test/express.json.js index 859347e1dcb..c92d8234bb3 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -2,7 +2,7 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('..') var request = require('supertest') diff --git a/test/express.raw.js b/test/express.raw.js index f6513a7d48d..cd526e39139 100644 --- a/test/express.raw.js +++ b/test/express.raw.js @@ -2,7 +2,7 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('..') var request = require('supertest') diff --git a/test/express.static.js b/test/express.static.js index e5100e8c8d2..c7c7d4df892 100644 --- a/test/express.static.js +++ b/test/express.static.js @@ -1,7 +1,7 @@ 'use strict' var assert = require('assert') -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('..') var path = require('path') var request = require('supertest') diff --git a/test/express.text.js b/test/express.text.js index ce365fa73cc..e5fd9e415ac 100644 --- a/test/express.text.js +++ b/test/express.text.js @@ -2,7 +2,7 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('..') var request = require('supertest') diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index 37afb07f38a..2bf72b79b9d 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -2,7 +2,7 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('..') var request = require('supertest') diff --git a/test/res.attachment.js b/test/res.attachment.js index 6283ded0d65..1281584f3cb 100644 --- a/test/res.attachment.js +++ b/test/res.attachment.js @@ -1,6 +1,6 @@ 'use strict' -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('../') , request = require('supertest'); diff --git a/test/res.download.js b/test/res.download.js index f7d795d57c0..3ccd0c77440 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -3,7 +3,7 @@ var after = require('after'); var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('..'); var path = require('path') var request = require('supertest'); diff --git a/test/res.send.js b/test/res.send.js index bce62c8d406..1f9b372c8c0 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -1,7 +1,7 @@ 'use strict' var assert = require('assert') -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('..'); var methods = require('methods'); var request = require('supertest'); diff --git a/test/res.sendFile.js b/test/res.sendFile.js index 7bba9cd6d13..d0b4b1b50cf 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -3,7 +3,7 @@ var after = require('after'); var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var express = require('../') , request = require('supertest') var onFinished = require('on-finished'); diff --git a/test/support/utils.js b/test/support/utils.js index 5ad4ca98410..50350943d41 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -5,7 +5,7 @@ */ var assert = require('assert'); -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer /** * Module exports. diff --git a/test/utils.js b/test/utils.js index aff3f03aa33..0b68d38a69a 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,7 +1,7 @@ 'use strict' var assert = require('assert'); -var Buffer = require('safe-buffer').Buffer +var Buffer = require('node:buffer').Buffer var utils = require('../lib/utils'); describe('utils.etag(body, encoding)', function(){ From b31910c542c7079d8a763aff346400b6f4c0eaee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 29 Oct 2024 13:35:44 +0100 Subject: [PATCH 792/889] docs: Add DCO (#6048) Co-authored-by: Chris de Almeida --- Contributing.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Contributing.md b/Contributing.md index ebb8bb19441..fee08f74a7e 100644 --- a/Contributing.md +++ b/Contributing.md @@ -207,3 +207,31 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ ### Current Initiative Captains - Triage team [ref](https://github.com/expressjs/discussions/issues/227): @UlisesGascon + +## Developer's Certificate of Origin 1.1 + +```text +By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + + (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + + (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + + (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` From 9e3dbb43744620b8b490c61c9269a168e0c0e3ae Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Tue, 12 Nov 2024 16:30:34 +0100 Subject: [PATCH 793/889] chore(test): remove promise support check from tests (#6148) Promises are supported in all supported Node.js version so the check is unnecessary --- test/app.route.js | 4 +--- test/app.router.js | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/app.route.js b/test/app.route.js index a0c8696e509..03ae1293685 100644 --- a/test/app.route.js +++ b/test/app.route.js @@ -3,8 +3,6 @@ var express = require('../'); var request = require('supertest'); -var describePromises = global.Promise ? describe : describe.skip - describe('app.route', function(){ it('should return a new route', function(done){ var app = express(); @@ -64,7 +62,7 @@ describe('app.route', function(){ .expect(404, done); }); - describePromises('promise support', function () { + describe('promise support', function () { it('should pass rejected promise value', function (done) { var app = express() var route = app.route('/foo') diff --git a/test/app.router.js b/test/app.router.js index 1db40042a1c..bdf4011a61a 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -6,7 +6,6 @@ var express = require('../') , assert = require('assert') , methods = require('methods'); -var describePromises = global.Promise ? describe : describe.skip var shouldSkipQuery = require('./support/utils').shouldSkipQuery describe('app.router', function(){ @@ -963,7 +962,7 @@ describe('app.router', function(){ }) }) - describePromises('promise support', function () { + describe('promise support', function () { it('should pass rejected promise value', function (done) { var app = express() var router = new express.Router() From 805ef52ae6156abffe1dee7fa3c25dcd7923f913 Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Thu, 14 Nov 2024 13:01:25 -0800 Subject: [PATCH 794/889] Use loop for acceptParams (#6066) --- lib/utils.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 67eacf274e8..35b2781306f 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -84,16 +84,33 @@ exports.normalizeTypes = function(types){ */ function acceptParams (str) { - var parts = str.split(/ *; */); - var ret = { value: parts[0], quality: 1, params: {} } + var length = str.length; + var colonIndex = str.indexOf(';'); + var index = colonIndex === -1 ? length : colonIndex; + var ret = { value: str.slice(0, index).trim(), quality: 1, params: {} }; - for (var i = 1; i < parts.length; ++i) { - var pms = parts[i].split(/ *= */); - if ('q' === pms[0]) { - ret.quality = parseFloat(pms[1]); + while (index < length) { + var splitIndex = str.indexOf('=', index); + if (splitIndex === -1) break; + + var colonIndex = str.indexOf(';', index); + var endIndex = colonIndex === -1 ? length : colonIndex; + + if (splitIndex > endIndex) { + index = str.lastIndexOf(';', splitIndex - 1) + 1; + continue; + } + + var key = str.slice(index, splitIndex).trim(); + var value = str.slice(splitIndex + 1, endIndex).trim(); + + if (key === 'q') { + ret.quality = parseFloat(value); } else { - ret.params[pms[0]] = pms[1]; + ret.params[key] = value; } + + index = endIndex + 1; } return ret; From cc751cff8fc8e57146f78d8deadaf150fd03cd68 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 5 Nov 2024 19:08:48 -0500 Subject: [PATCH 795/889] improve step update documentation --- Release-Process.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Release-Process.md b/Release-Process.md index 9ca0a15ab46..8eee8aa089a 100644 --- a/Release-Process.md +++ b/Release-Process.md @@ -129,9 +129,10 @@ $ git merge --ff-only - see "Release branch" of "Branches" above. - see "Proposal branch" of "Non-patch flow" above. -**NOTE:** You may need to rebase the proposal branch to allow a fast-forward - merge. Using a fast-forward merge keeps the history clean as it does - not introduce merge commits. +> [!NOTE] +> You may need to rebase the proposal branch to allow a fast-forward +> merge. Using a fast-forward merge keeps the history clean as it does +> not introduce merge commits. ### Step 3. Update the History.md and package.json to the new version number @@ -189,11 +190,13 @@ $ npm login $ npm publish ``` -**NOTE:** The version number to publish will be picked up automatically from - package.json. +> [!NOTE] +> The version number to publish will be picked up automatically from +> package.json. ### Step 7. Update documentation website -The documentation website https://expressjs.com/ documents the current release version in various places. For a new release: -1. Change the value of `current_version` in https://github.com/expressjs/expressjs.com/blob/gh-pages/_data/express.yml to match the latest version number. -2. Add a new section to the change log. For example, for a 4.x release, https://github.com/expressjs/expressjs.com/blob/gh-pages/en/changelog/4x.md, +The documentation website https://expressjs.com/ documents the current release version in various places. To update these, follow these steps: + +1. Manually run the [`Update External Docs` workflow](https://github.com/expressjs/expressjs.com/actions/workflows/update-external-docs.yml) in expressjs.com repository. +2. Add a new section to the [changelog](https://github.com/expressjs/expressjs.com/blob/gh-pages/en/changelog/index.md) in the expressjs.com website. From 9f8589e31ce8e54097defb48da89c8538e92bfd9 Mon Sep 17 00:00:00 2001 From: Phillip9587 Date: Fri, 15 Nov 2024 17:08:49 +0100 Subject: [PATCH 796/889] cleanup: remove unnecessary require for global Buffer The Buffer object is globally available in Node.js, so there is no need to explicitly require it. --- History.md | 1 + lib/response.js | 1 - lib/utils.js | 1 - test/express.json.js | 1 - test/express.raw.js | 1 - test/express.static.js | 1 - test/express.text.js | 1 - test/express.urlencoded.js | 1 - test/res.attachment.js | 1 - test/res.download.js | 1 - test/res.send.js | 1 - test/res.sendFile.js | 1 - test/support/utils.js | 1 - test/utils.js | 1 - 14 files changed, 1 insertion(+), 13 deletions(-) diff --git a/History.md b/History.md index ae5a167a696..80eaabe420f 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ unreleased ======================== * Remove `Object.setPrototypeOf` polyfill +* cleanup: remove unnecessary require for global Buffer 5.0.1 / 2024-10-08 ========== diff --git a/lib/response.js b/lib/response.js index 29511a74e03..e439a06ae86 100644 --- a/lib/response.js +++ b/lib/response.js @@ -12,7 +12,6 @@ * @private */ -var Buffer = require('node:buffer').Buffer var contentDisposition = require('content-disposition'); var createError = require('http-errors') var encodeUrl = require('encodeurl'); diff --git a/lib/utils.js b/lib/utils.js index 35b2781306f..0092629f170 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -12,7 +12,6 @@ * @api private */ -var Buffer = require('node:buffer').Buffer var contentType = require('content-type'); var etag = require('etag'); var mime = require('mime-types') diff --git a/test/express.json.js b/test/express.json.js index c92d8234bb3..a46cc16fb89 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -2,7 +2,6 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('node:buffer').Buffer var express = require('..') var request = require('supertest') diff --git a/test/express.raw.js b/test/express.raw.js index cd526e39139..08f44904a4b 100644 --- a/test/express.raw.js +++ b/test/express.raw.js @@ -2,7 +2,6 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('node:buffer').Buffer var express = require('..') var request = require('supertest') diff --git a/test/express.static.js b/test/express.static.js index c7c7d4df892..65a3718a601 100644 --- a/test/express.static.js +++ b/test/express.static.js @@ -1,7 +1,6 @@ 'use strict' var assert = require('assert') -var Buffer = require('node:buffer').Buffer var express = require('..') var path = require('path') var request = require('supertest') diff --git a/test/express.text.js b/test/express.text.js index e5fd9e415ac..1bcc034b86f 100644 --- a/test/express.text.js +++ b/test/express.text.js @@ -2,7 +2,6 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('node:buffer').Buffer var express = require('..') var request = require('supertest') diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index 2bf72b79b9d..8503e0079af 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -2,7 +2,6 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('node:buffer').Buffer var express = require('..') var request = require('supertest') diff --git a/test/res.attachment.js b/test/res.attachment.js index 1281584f3cb..68e611bbc79 100644 --- a/test/res.attachment.js +++ b/test/res.attachment.js @@ -1,6 +1,5 @@ 'use strict' -var Buffer = require('node:buffer').Buffer var express = require('../') , request = require('supertest'); diff --git a/test/res.download.js b/test/res.download.js index 3ccd0c77440..82243d8b003 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -3,7 +3,6 @@ var after = require('after'); var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('node:buffer').Buffer var express = require('..'); var path = require('path') var request = require('supertest'); diff --git a/test/res.send.js b/test/res.send.js index 1f9b372c8c0..23ffd9305c5 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -1,7 +1,6 @@ 'use strict' var assert = require('assert') -var Buffer = require('node:buffer').Buffer var express = require('..'); var methods = require('methods'); var request = require('supertest'); diff --git a/test/res.sendFile.js b/test/res.sendFile.js index d0b4b1b50cf..e211fe9cb67 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -3,7 +3,6 @@ var after = require('after'); var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('node:buffer').Buffer var express = require('../') , request = require('supertest') var onFinished = require('on-finished'); diff --git a/test/support/utils.js b/test/support/utils.js index 50350943d41..c74f8efe0c2 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -5,7 +5,6 @@ */ var assert = require('assert'); -var Buffer = require('node:buffer').Buffer /** * Module exports. diff --git a/test/utils.js b/test/utils.js index 0b68d38a69a..ae73988b01d 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,7 +1,6 @@ 'use strict' var assert = require('assert'); -var Buffer = require('node:buffer').Buffer var utils = require('../lib/utils'); describe('utils.etag(body, encoding)', function(){ From 4e92ac903194b705a121ec49103fd9fcd779a42b Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Fri, 15 Nov 2024 17:23:42 +0100 Subject: [PATCH 797/889] cleanup: remove AsyncLocalStorage check from tests (#6147) Co-authored-by: Wes Todd --- History.md | 2 ++ test/express.json.js | 19 ++++--------------- test/express.raw.js | 19 ++++--------------- test/express.text.js | 19 ++++--------------- test/express.urlencoded.js | 19 ++++--------------- test/res.download.js | 21 +++++---------------- test/res.sendFile.js | 21 +++++---------------- 7 files changed, 28 insertions(+), 92 deletions(-) diff --git a/History.md b/History.md index 80eaabe420f..e1e5a1af210 100644 --- a/History.md +++ b/History.md @@ -2,8 +2,10 @@ unreleased ======================== * Remove `Object.setPrototypeOf` polyfill +* cleanup: remove AsyncLocalStorage check from tests * cleanup: remove unnecessary require for global Buffer + 5.0.1 / 2024-10-08 ========== diff --git a/test/express.json.js b/test/express.json.js index a46cc16fb89..2c394922c82 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -1,14 +1,11 @@ 'use strict' var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage + var express = require('..') var request = require('supertest') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('express.json()', function () { it('should parse JSON', function (done) { request(createApp()) @@ -502,13 +499,13 @@ describe('express.json()', function () { }) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { before(function () { var app = express() var store = { foo: 'bar' } app.use(function (req, res, next) { - req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage = new AsyncLocalStorage() req.asyncLocalStorage.run(store, next) }) @@ -755,11 +752,3 @@ function shouldContainInBody (str) { 'expected \'' + res.text + '\' to contain \'' + str + '\'') } } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} diff --git a/test/express.raw.js b/test/express.raw.js index 08f44904a4b..53995bf829c 100644 --- a/test/express.raw.js +++ b/test/express.raw.js @@ -1,14 +1,11 @@ 'use strict' var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage + var express = require('..') var request = require('supertest') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('express.raw()', function () { before(function () { this.app = createApp() @@ -327,13 +324,13 @@ describe('express.raw()', function () { }) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { before(function () { var app = express() var store = { foo: 'bar' } app.use(function (req, res, next) { - req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage = new AsyncLocalStorage() req.asyncLocalStorage.run(store, next) }) @@ -513,11 +510,3 @@ function createApp (options) { return app } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} diff --git a/test/express.text.js b/test/express.text.js index 1bcc034b86f..95fcbf86570 100644 --- a/test/express.text.js +++ b/test/express.text.js @@ -1,14 +1,11 @@ 'use strict' var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage + var express = require('..') var request = require('supertest') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('express.text()', function () { before(function () { this.app = createApp() @@ -360,13 +357,13 @@ describe('express.text()', function () { }) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { before(function () { var app = express() var store = { foo: 'bar' } app.use(function (req, res, next) { - req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage = new AsyncLocalStorage() req.asyncLocalStorage.run(store, next) }) @@ -567,11 +564,3 @@ function createApp (options) { return app } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index 8503e0079af..50c3e93bba8 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -1,14 +1,11 @@ 'use strict' var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage + var express = require('..') var request = require('supertest') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('express.urlencoded()', function () { before(function () { this.app = createApp() @@ -605,13 +602,13 @@ describe('express.urlencoded()', function () { }) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { before(function () { var app = express() var store = { foo: 'bar' } app.use(function (req, res, next) { - req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage = new AsyncLocalStorage() req.asyncLocalStorage.run(store, next) }) @@ -828,11 +825,3 @@ function expectKeyCount (count) { assert.strictEqual(Object.keys(JSON.parse(res.text)).length, count) } } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} diff --git a/test/res.download.js b/test/res.download.js index 82243d8b003..5718ff44096 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -2,7 +2,8 @@ var after = require('after'); var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage + var express = require('..'); var path = require('path') var request = require('supertest'); @@ -10,10 +11,6 @@ var utils = require('./support/utils') var FIXTURES_PATH = path.join(__dirname, 'fixtures') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('res', function(){ describe('.download(path)', function(){ it('should transfer as an attachment', function(done){ @@ -90,14 +87,14 @@ describe('res', function(){ .expect(200, cb); }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { it('should presist store', function (done) { var app = express() var cb = after(2, done) var store = { foo: 'bar' } app.use(function (req, res, next) { - req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage = new AsyncLocalStorage() req.asyncLocalStorage.run(store, next) }) @@ -124,7 +121,7 @@ describe('res', function(){ var store = { foo: 'bar' } app.use(function (req, res, next) { - req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage = new AsyncLocalStorage() req.asyncLocalStorage.run(store, next) }) @@ -487,11 +484,3 @@ describe('res', function(){ }) }) }) - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} diff --git a/test/res.sendFile.js b/test/res.sendFile.js index e211fe9cb67..ec90adf5d32 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -2,7 +2,8 @@ var after = require('after'); var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage + var express = require('../') , request = require('supertest') var onFinished = require('on-finished'); @@ -10,10 +11,6 @@ var path = require('path'); var fixtures = path.join(__dirname, 'fixtures'); var utils = require('./support/utils'); -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('res', function(){ describe('.sendFile(path)', function () { it('should error missing path', function (done) { @@ -266,14 +263,14 @@ describe('res', function(){ .expect(200, 'got 404 error', done) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { it('should presist store', function (done) { var app = express() var cb = after(2, done) var store = { foo: 'bar' } app.use(function (req, res, next) { - req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage = new AsyncLocalStorage() req.asyncLocalStorage.run(store, next) }) @@ -299,7 +296,7 @@ describe('res', function(){ var store = { foo: 'bar' } app.use(function (req, res, next) { - req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + req.asyncLocalStorage = new AsyncLocalStorage() req.asyncLocalStorage.run(store, next) }) @@ -900,11 +897,3 @@ function createApp(path, options, fn) { return app; } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} From 52ed64606fc1f5114d90265a66275a18f2d773af Mon Sep 17 00:00:00 2001 From: Jon Church Date: Wed, 20 Nov 2024 14:40:39 -0500 Subject: [PATCH 798/889] update history.md for acceptParams change (#6177) --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index e1e5a1af210..e2dfbc84d74 100644 --- a/History.md +++ b/History.md @@ -4,7 +4,7 @@ unreleased * Remove `Object.setPrototypeOf` polyfill * cleanup: remove AsyncLocalStorage check from tests * cleanup: remove unnecessary require for global Buffer - +* perf: use loop for acceptParams 5.0.1 / 2024-10-08 ========== From 39f5d633b55726469cf3bb72eb905cb6b1f59d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Wed, 27 Nov 2024 19:59:36 +0100 Subject: [PATCH 799/889] docs: add @rxmarbles to the triage team (#6151) --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 47c72f9bdfd..c0ae63ebd25 100644 --- a/Readme.md +++ b/Readme.md @@ -211,6 +211,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego** * [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him) * [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger** +* [rxmarbles](https://github.com/rxmarbles) **Rick Markins** (He/him)
        Triagers emeriti members From e4a61bd88e2f170eab64d937f3bf6c0812b4a649 Mon Sep 17 00:00:00 2001 From: Shahan Arshad <68821506+sazk07@users.noreply.github.com> Date: Thu, 28 Nov 2024 01:22:22 +0500 Subject: [PATCH 800/889] refactor: improve readability (#6173) --- examples/params/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/params/index.js b/examples/params/index.js index f3cd8457eb5..11eef51a592 100644 --- a/examples/params/index.js +++ b/examples/params/index.js @@ -32,7 +32,8 @@ app.param(['to', 'from'], function(req, res, next, num, name){ // Load user by id app.param('user', function(req, res, next, id){ - if (req.user = users[id]) { + req.user = users[id] + if (req.user) { next(); } else { next(createError(404, 'failed to find user')); From 43020ff2753477a5abc75a72931a807503d31bbf Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Fri, 20 Dec 2024 12:18:55 -0500 Subject: [PATCH 801/889] docs: clarify the security process in the triage role (#6217) --- Triager-Guide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Triager-Guide.md b/Triager-Guide.md index c15e6be5313..65aff265f01 100644 --- a/Triager-Guide.md +++ b/Triager-Guide.md @@ -68,3 +68,5 @@ If you have questions feel free to reach out to any of the TC members. - For recurring issues, it is helpful to create functional examples to demonstrate (publish as gists or a repo) - Review and identify the maintainers. If necessary, at-mention one or more of them if you are unsure what to do - Make sure all your interactions are professional, welcoming, and respectful to the parties involved. +- When an issue refers to security concerns, responsibility is delegated to the repository captain or the security group in any public communication. + - If an issue has been open for a long time, the person in charge should be contacted internally through the private Slack chat. \ No newline at end of file From b11122be85377375465b2aa103da43301e56f128 Mon Sep 17 00:00:00 2001 From: Jon Koops Date: Thu, 2 Jan 2025 08:00:30 +0100 Subject: [PATCH 802/889] chore: replace `methods` dependency with standard library (#6196) --- History.md | 1 + lib/application.js | 2 +- lib/utils.js | 7 +++++++ package.json | 1 - test/Route.js | 2 +- test/Router.js | 2 +- test/app.router.js | 2 +- test/res.send.js | 2 +- 8 files changed, 13 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index e2dfbc84d74..234671e5d65 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ unreleased * cleanup: remove AsyncLocalStorage check from tests * cleanup: remove unnecessary require for global Buffer * perf: use loop for acceptParams +* Replace `methods` dependency with standard library 5.0.1 / 2024-10-08 ========== diff --git a/lib/application.js b/lib/application.js index b19055ec829..ebef606bd38 100644 --- a/lib/application.js +++ b/lib/application.js @@ -14,10 +14,10 @@ */ var finalhandler = require('finalhandler'); -var methods = require('methods'); var debug = require('debug')('express:application'); var View = require('./view'); var http = require('http'); +var methods = require('./utils').methods; var compileETag = require('./utils').compileETag; var compileQueryParser = require('./utils').compileQueryParser; var compileTrust = require('./utils').compileTrust; diff --git a/lib/utils.js b/lib/utils.js index 0092629f170..d11f8aa1686 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -12,6 +12,7 @@ * @api private */ +var { METHODS } = require('node:http'); var contentType = require('content-type'); var etag = require('etag'); var mime = require('mime-types') @@ -19,6 +20,12 @@ var proxyaddr = require('proxy-addr'); var qs = require('qs'); var querystring = require('querystring'); +/** + * A list of lowercased HTTP methods that are supported by Node.js. + * @api private + */ +exports.methods = METHODS.map((method) => method.toLowerCase()); + /** * Return strong ETag for `body`. * diff --git a/package.json b/package.json index 54b4bb5704e..f42bbc4be54 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "fresh": "2.0.0", "http-errors": "2.0.0", "merge-descriptors": "^2.0.0", - "methods": "~1.1.2", "mime-types": "^3.0.0", "on-finished": "2.4.1", "once": "1.4.0", diff --git a/test/Route.js b/test/Route.js index 2a37b9a4839..a748ab74769 100644 --- a/test/Route.js +++ b/test/Route.js @@ -4,7 +4,7 @@ var after = require('after'); var assert = require('assert') var express = require('../') , Route = express.Route - , methods = require('methods') + , methods = require('../lib/utils').methods describe('Route', function(){ it('should work without handlers', function(done) { diff --git a/test/Router.js b/test/Router.js index a1952f445ac..fcd48ab3679 100644 --- a/test/Router.js +++ b/test/Router.js @@ -3,7 +3,7 @@ var after = require('after'); var express = require('../') , Router = express.Router - , methods = require('methods') + , methods = require('../lib/utils').methods , assert = require('assert'); describe('Router', function(){ diff --git a/test/app.router.js b/test/app.router.js index bdf4011a61a..61b48eb4a39 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -4,7 +4,7 @@ var after = require('after'); var express = require('../') , request = require('supertest') , assert = require('assert') - , methods = require('methods'); + , methods = require('../lib/utils').methods; var shouldSkipQuery = require('./support/utils').shouldSkipQuery diff --git a/test/res.send.js b/test/res.send.js index 23ffd9305c5..b061dfcc511 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -2,7 +2,7 @@ var assert = require('assert') var express = require('..'); -var methods = require('methods'); +var methods = require('../lib/utils').methods; var request = require('supertest'); var utils = require('./support/utils'); From 246f6f5aeebad1b9d6a0ea08cd96d3fe19f8f23c Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Wed, 8 Jan 2025 16:56:16 +0100 Subject: [PATCH 803/889] fix: Remove `utils-merge` dependency - use spread syntax instead (#6091) --- History.md | 1 + lib/application.js | 12 +----------- lib/response.js | 3 +-- package.json | 1 - test/res.cookie.js | 3 +-- 5 files changed, 4 insertions(+), 16 deletions(-) diff --git a/History.md b/History.md index 234671e5d65..485eb136a9d 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ======================== +* Remove `utils-merge` dependency - use spread syntax instead * Remove `Object.setPrototypeOf` polyfill * cleanup: remove AsyncLocalStorage check from tests * cleanup: remove unnecessary require for global Buffer diff --git a/lib/application.js b/lib/application.js index ebef606bd38..bd319532bd9 100644 --- a/lib/application.js +++ b/lib/application.js @@ -21,7 +21,6 @@ var methods = require('./utils').methods; var compileETag = require('./utils').compileETag; var compileQueryParser = require('./utils').compileQueryParser; var compileTrust = require('./utils').compileTrust; -var merge = require('utils-merge'); var resolve = require('path').resolve; var once = require('once') var Router = require('router'); @@ -525,7 +524,6 @@ app.render = function render(name, options, callback) { var done = callback; var engines = this.engines; var opts = options; - var renderOptions = {}; var view; // support callback function as second arg @@ -534,16 +532,8 @@ app.render = function render(name, options, callback) { opts = {}; } - // merge app.locals - merge(renderOptions, this.locals); - - // merge options._locals - if (opts._locals) { - merge(renderOptions, opts._locals); - } - // merge options - merge(renderOptions, opts); + var renderOptions = { ...this.locals, ...opts._locals, ...opts }; // set .cache unless explicitly provided if (renderOptions.cache == null) { diff --git a/lib/response.js b/lib/response.js index e439a06ae86..c5cf78d84f2 100644 --- a/lib/response.js +++ b/lib/response.js @@ -22,7 +22,6 @@ var mime = require('mime-types') var path = require('path'); var pathIsAbsolute = require('path').isAbsolute; var statuses = require('statuses') -var merge = require('utils-merge'); var sign = require('cookie-signature').sign; var normalizeType = require('./utils').normalizeType; var normalizeTypes = require('./utils').normalizeTypes; @@ -732,7 +731,7 @@ res.clearCookie = function clearCookie(name, options) { */ res.cookie = function (name, value, options) { - var opts = merge({}, options); + var opts = { ...options }; var secret = this.req.secret; var signed = opts.signed; diff --git a/package.json b/package.json index f42bbc4be54..c930d5bebb7 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "serve-static": "^2.1.0", "statuses": "2.0.1", "type-is": "^2.0.0", - "utils-merge": "1.0.1", "vary": "~1.1.2" }, "devDependencies": { diff --git a/test/res.cookie.js b/test/res.cookie.js index c837820605c..180d1be3452 100644 --- a/test/res.cookie.js +++ b/test/res.cookie.js @@ -3,7 +3,6 @@ var express = require('../') , request = require('supertest') , cookieParser = require('cookie-parser') -var merge = require('utils-merge'); describe('res', function(){ describe('.cookie(name, object)', function(){ @@ -130,7 +129,7 @@ describe('res', function(){ var app = express(); var options = { maxAge: 1000 }; - var optionsCopy = merge({}, options); + var optionsCopy = { ...options }; app.use(function(req, res){ res.cookie('name', 'tobi', options) From 6a40af82937803a7652b47641a7a3cd2f5c833c4 Mon Sep 17 00:00:00 2001 From: AbdelMonaam Aouini <52112750+Abdel-Monaam-Aouini@users.noreply.github.com> Date: Wed, 8 Jan 2025 21:45:36 +0100 Subject: [PATCH 804/889] fix(devdeps): update dev deps (#6211) Co-authored-by: Monaam Aouini --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c930d5bebb7..da580992995 100644 --- a/package.json +++ b/package.json @@ -63,14 +63,14 @@ }, "devDependencies": { "after": "0.8.2", - "connect-redis": "3.4.2", - "cookie-parser": "1.4.6", + "connect-redis": "8.0.1", + "cookie-parser": "1.4.7", "cookie-session": "2.0.0", - "ejs": "3.1.9", + "ejs": "3.1.10", "eslint": "8.47.0", - "express-session": "1.17.2", + "express-session": "1.18.1", "hbs": "4.2.0", - "marked": "0.7.0", + "marked": "15.0.3", "method-override": "3.0.0", "mocha": "10.2.0", "morgan": "1.10.0", From 41113599afb01040436dba993f06cacbdb8f8e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20=C5=81=C4=85giewka?= Date: Sat, 21 Dec 2024 22:58:33 +0100 Subject: [PATCH 805/889] fix(refactor): prefix built-in node module imports Since v5 relies on node >= 18, this is now possible (since v16, v14.18.0 [^1][^2]). It's functionally irrelevant: 1. It's not required for CJS nor ESM (with a few exceptions [^3]) 2. It has no performance promises However, there are upsides to this approach: 1. It brings clear boundaries to what's a built-in and what's an external dependency 2. It reduces the risk of importing unwanted deps where a built-in is expected 3. It's slightly more interoperable with other JS runtimes that provide node compatibility[^4], albeit only during development. Once imported from npm, built-ins are assumed. [^1]:https://nodejs.org/docs/latest-v22.x/api/modules.html#built-in-modules [^2]:https://github.com/nodejs/node/pull/37246 [^3]:https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix [^4]:https://docs.deno.com/runtime/fundamentals/node/#using-node's-built-in-modules --- History.md | 1 + examples/auth/index.js | 2 +- examples/downloads/index.js | 2 +- examples/ejs/index.js | 2 +- examples/error-pages/index.js | 2 +- examples/markdown/index.js | 4 +- examples/mvc/index.js | 2 +- examples/mvc/lib/boot.js | 4 +- examples/route-separation/index.js | 2 +- examples/search/index.js | 2 +- examples/static-files/index.js | 2 +- examples/view-constructor/github-view.js | 4 +- examples/view-locals/index.js | 2 +- lib/application.js | 14 +- lib/express.js | 2 +- lib/request.js | 4 +- lib/response.js | 6 +- lib/view.js | 4 +- test/Route.js | 2 +- test/Router.js | 152 +++--- test/app.engine.js | 6 +- test/app.head.js | 2 +- test/app.js | 2 +- test/app.listen.js | 2 +- test/app.locals.js | 2 +- test/app.render.js | 4 +- test/app.request.js | 2 +- test/app.router.js | 580 +++++++++++------------ test/app.routes.error.js | 2 +- test/app.use.js | 2 +- test/config.js | 2 +- test/exports.js | 2 +- test/express.json.js | 4 +- test/express.raw.js | 4 +- test/express.static.js | 4 +- test/express.text.js | 4 +- test/express.urlencoded.js | 4 +- test/middleware.basic.js | 2 +- test/req.get.js | 2 +- test/req.query.js | 2 +- test/res.append.js | 2 +- test/res.download.js | 6 +- test/res.format.js | 2 +- test/res.json.js | 2 +- test/res.jsonp.js | 2 +- test/res.location.js | 4 +- test/res.render.js | 2 +- test/res.send.js | 2 +- test/res.sendFile.js | 6 +- test/support/tmpl.js | 2 +- test/support/utils.js | 2 +- test/utils.js | 2 +- 52 files changed, 442 insertions(+), 441 deletions(-) diff --git a/History.md b/History.md index 485eb136a9d..5323220bcd5 100644 --- a/History.md +++ b/History.md @@ -7,6 +7,7 @@ unreleased * cleanup: remove unnecessary require for global Buffer * perf: use loop for acceptParams * Replace `methods` dependency with standard library +* refactor: prefix built-in node module imports 5.0.1 / 2024-10-08 ========== diff --git a/examples/auth/index.js b/examples/auth/index.js index 2884ca4e170..40b73e6de16 100644 --- a/examples/auth/index.js +++ b/examples/auth/index.js @@ -6,7 +6,7 @@ var express = require('../..'); var hash = require('pbkdf2-password')() -var path = require('path'); +var path = require('node:path'); var session = require('express-session'); var app = module.exports = express(); diff --git a/examples/downloads/index.js b/examples/downloads/index.js index c47dddd738a..ddc549ffec7 100644 --- a/examples/downloads/index.js +++ b/examples/downloads/index.js @@ -5,7 +5,7 @@ */ var express = require('../../'); -var path = require('path'); +var path = require('node:path'); var app = module.exports = express(); diff --git a/examples/ejs/index.js b/examples/ejs/index.js index a39d805a160..0940d0624fb 100644 --- a/examples/ejs/index.js +++ b/examples/ejs/index.js @@ -5,7 +5,7 @@ */ var express = require('../../'); -var path = require('path'); +var path = require('node:path'); var app = module.exports = express(); diff --git a/examples/error-pages/index.js b/examples/error-pages/index.js index efa815c4740..0863120bc8f 100644 --- a/examples/error-pages/index.js +++ b/examples/error-pages/index.js @@ -5,7 +5,7 @@ */ var express = require('../../'); -var path = require('path'); +var path = require('node:path'); var app = module.exports = express(); var logger = require('morgan'); var silent = process.env.NODE_ENV === 'test' diff --git a/examples/markdown/index.js b/examples/markdown/index.js index 23d645e66b2..53e40ac38e4 100644 --- a/examples/markdown/index.js +++ b/examples/markdown/index.js @@ -6,9 +6,9 @@ var escapeHtml = require('escape-html'); var express = require('../..'); -var fs = require('fs'); +var fs = require('node:fs'); var marked = require('marked'); -var path = require('path'); +var path = require('node:path'); var app = module.exports = express(); diff --git a/examples/mvc/index.js b/examples/mvc/index.js index da4727b282d..1d8aa0e3c31 100644 --- a/examples/mvc/index.js +++ b/examples/mvc/index.js @@ -6,7 +6,7 @@ var express = require('../..'); var logger = require('morgan'); -var path = require('path'); +var path = require('node:path'); var session = require('express-session'); var methodOverride = require('method-override'); diff --git a/examples/mvc/lib/boot.js b/examples/mvc/lib/boot.js index 0216e5d76d6..fc2ab0fad99 100644 --- a/examples/mvc/lib/boot.js +++ b/examples/mvc/lib/boot.js @@ -5,8 +5,8 @@ */ var express = require('../../..'); -var fs = require('fs'); -var path = require('path'); +var fs = require('node:fs'); +var path = require('node:path'); module.exports = function(parent, options){ var dir = path.join(__dirname, '..', 'controllers'); diff --git a/examples/route-separation/index.js b/examples/route-separation/index.js index a471a4b0912..0a29c9421a6 100644 --- a/examples/route-separation/index.js +++ b/examples/route-separation/index.js @@ -5,7 +5,7 @@ */ var express = require('../..'); -var path = require('path'); +var path = require('node:path'); var app = express(); var logger = require('morgan'); var cookieParser = require('cookie-parser'); diff --git a/examples/search/index.js b/examples/search/index.js index 4b57168987f..951e0d440a6 100644 --- a/examples/search/index.js +++ b/examples/search/index.js @@ -12,7 +12,7 @@ */ var express = require('../..'); -var path = require('path'); +var path = require('node:path'); var redis = require('redis'); var db = redis.createClient(); diff --git a/examples/static-files/index.js b/examples/static-files/index.js index 609c546b470..b7c697a2f9f 100644 --- a/examples/static-files/index.js +++ b/examples/static-files/index.js @@ -6,7 +6,7 @@ var express = require('../..'); var logger = require('morgan'); -var path = require('path'); +var path = require('node:path'); var app = express(); // log requests diff --git a/examples/view-constructor/github-view.js b/examples/view-constructor/github-view.js index 43d29336cac..eabfb2d0c18 100644 --- a/examples/view-constructor/github-view.js +++ b/examples/view-constructor/github-view.js @@ -4,8 +4,8 @@ * Module dependencies. */ -var https = require('https'); -var path = require('path'); +var https = require('node:https'); +var path = require('node:path'); var extname = path.extname; /** diff --git a/examples/view-locals/index.js b/examples/view-locals/index.js index a2af24f3553..e6355602d4e 100644 --- a/examples/view-locals/index.js +++ b/examples/view-locals/index.js @@ -5,7 +5,7 @@ */ var express = require('../..'); -var path = require('path'); +var path = require('node:path'); var User = require('./user'); var app = express(); diff --git a/lib/application.js b/lib/application.js index bd319532bd9..cf6d78c741e 100644 --- a/lib/application.js +++ b/lib/application.js @@ -16,12 +16,12 @@ var finalhandler = require('finalhandler'); var debug = require('debug')('express:application'); var View = require('./view'); -var http = require('http'); +var http = require('node:http'); var methods = require('./utils').methods; var compileETag = require('./utils').compileETag; var compileQueryParser = require('./utils').compileQueryParser; var compileTrust = require('./utils').compileTrust; -var resolve = require('path').resolve; +var resolve = require('node:path').resolve; var once = require('once') var Router = require('router'); @@ -468,8 +468,8 @@ app.disable = function disable(setting) { * Delegate `.VERB(...)` calls to `router.VERB(...)`. */ -methods.forEach(function(method){ - app[method] = function(path){ +methods.forEach(function (method) { + app[method] = function (path) { if (method === 'get' && arguments.length === 1) { // app.get(setting) return this.set(path); @@ -583,8 +583,8 @@ app.render = function render(name, options, callback) { * and HTTPS server you may do so with the "http" * and "https" modules as shown here: * - * var http = require('http') - * , https = require('https') + * var http = require('node:http') + * , https = require('node:https') * , express = require('express') * , app = express(); * @@ -595,7 +595,7 @@ app.render = function render(name, options, callback) { * @public */ -app.listen = function listen () { +app.listen = function listen() { var server = http.createServer(this) var args = Array.prototype.slice.call(arguments) if (typeof args[args.length - 1] === 'function') { diff --git a/lib/express.js b/lib/express.js index b4ef2996360..2d502eb54e4 100644 --- a/lib/express.js +++ b/lib/express.js @@ -13,7 +13,7 @@ */ var bodyParser = require('body-parser') -var EventEmitter = require('events').EventEmitter; +var EventEmitter = require('node:events').EventEmitter; var mixin = require('merge-descriptors'); var proto = require('./application'); var Router = require('router'); diff --git a/lib/request.js b/lib/request.js index 372a9915e96..d8e52630788 100644 --- a/lib/request.js +++ b/lib/request.js @@ -14,9 +14,9 @@ */ var accepts = require('accepts'); -var isIP = require('net').isIP; +var isIP = require('node:net').isIP; var typeis = require('type-is'); -var http = require('http'); +var http = require('node:http'); var fresh = require('fresh'); var parseRange = require('range-parser'); var parse = require('parseurl'); diff --git a/lib/response.js b/lib/response.js index c5cf78d84f2..f6f5740d2da 100644 --- a/lib/response.js +++ b/lib/response.js @@ -16,11 +16,11 @@ var contentDisposition = require('content-disposition'); var createError = require('http-errors') var encodeUrl = require('encodeurl'); var escapeHtml = require('escape-html'); -var http = require('http'); +var http = require('node:http'); var onFinished = require('on-finished'); var mime = require('mime-types') -var path = require('path'); -var pathIsAbsolute = require('path').isAbsolute; +var path = require('node:path'); +var pathIsAbsolute = require('node:path').isAbsolute; var statuses = require('statuses') var sign = require('cookie-signature').sign; var normalizeType = require('./utils').normalizeType; diff --git a/lib/view.js b/lib/view.js index 6beffca6e24..d66b4a2d89c 100644 --- a/lib/view.js +++ b/lib/view.js @@ -14,8 +14,8 @@ */ var debug = require('debug')('express:view'); -var path = require('path'); -var fs = require('fs'); +var path = require('node:path'); +var fs = require('node:fs'); /** * Module variables. diff --git a/test/Route.js b/test/Route.js index a748ab74769..e4b73c7e6ec 100644 --- a/test/Route.js +++ b/test/Route.js @@ -1,7 +1,7 @@ 'use strict' var after = require('after'); -var assert = require('assert') +var assert = require('node:assert') var express = require('../') , Route = express.Route , methods = require('../lib/utils').methods diff --git a/test/Router.js b/test/Router.js index fcd48ab3679..7bac7159b04 100644 --- a/test/Router.js +++ b/test/Router.js @@ -4,10 +4,10 @@ var after = require('after'); var express = require('../') , Router = express.Router , methods = require('../lib/utils').methods - , assert = require('assert'); + , assert = require('node:assert'); -describe('Router', function(){ - it('should return a function with router methods', function() { +describe('Router', function () { + it('should return a function with router methods', function () { var router = new Router(); assert(typeof router === 'function') @@ -16,32 +16,32 @@ describe('Router', function(){ assert(typeof router.use === 'function') }); - it('should support .use of other routers', function(done){ + it('should support .use of other routers', function (done) { var router = new Router(); var another = new Router(); - another.get('/bar', function(req, res){ + another.get('/bar', function (req, res) { res.end(); }); router.use('/foo', another); - router.handle({ url: '/foo/bar', method: 'GET' }, { end: done }, function(){}); + router.handle({ url: '/foo/bar', method: 'GET' }, { end: done }, function () { }); }); - it('should support dynamic routes', function(done){ + it('should support dynamic routes', function (done) { var router = new Router(); var another = new Router(); - another.get('/:bar', function(req, res){ + another.get('/:bar', function (req, res) { assert.strictEqual(req.params.bar, 'route') res.end(); }); router.use('/:foo', another); - router.handle({ url: '/test/route', method: 'GET' }, { end: done }, function(){}); + router.handle({ url: '/test/route', method: 'GET' }, { end: done }, function () { }); }); - it('should handle blank URL', function(done){ + it('should handle blank URL', function (done) { var router = new Router(); router.use(function (req, res) { @@ -88,10 +88,10 @@ describe('Router', function(){ }) }) - it('should not stack overflow with many registered routes', function(done){ + it('should not stack overflow with many registered routes', function (done) { this.timeout(5000) // long-running test - var handler = function(req, res){ res.end(new Error('wrong handler')) }; + var handler = function (req, res) { res.end(new Error('wrong handler')) }; var router = new Router(); for (var i = 0; i < 6000; i++) { @@ -102,7 +102,7 @@ describe('Router', function(){ res.end(); }); - router.handle({ url: '/', method: 'GET' }, { end: done }, function(){}); + router.handle({ url: '/', method: 'GET' }, { end: done }, function () { }); }); it('should not stack overflow with a large sync route stack', function (done) { @@ -159,69 +159,69 @@ describe('Router', function(){ }) }) - describe('.handle', function(){ - it('should dispatch', function(done){ + describe('.handle', function () { + it('should dispatch', function (done) { var router = new Router(); - router.route('/foo').get(function(req, res){ + router.route('/foo').get(function (req, res) { res.send('foo'); }); var res = { - send: function(val) { + send: function (val) { assert.strictEqual(val, 'foo') done(); } } - router.handle({ url: '/foo', method: 'GET' }, res, function(){}); + router.handle({ url: '/foo', method: 'GET' }, res, function () { }); }) }) - describe('.multiple callbacks', function(){ - it('should throw if a callback is null', function(){ + describe('.multiple callbacks', function () { + it('should throw if a callback is null', function () { assert.throws(function () { var router = new Router(); router.route('/foo').all(null); }) }) - it('should throw if a callback is undefined', function(){ + it('should throw if a callback is undefined', function () { assert.throws(function () { var router = new Router(); router.route('/foo').all(undefined); }) }) - it('should throw if a callback is not a function', function(){ + it('should throw if a callback is not a function', function () { assert.throws(function () { var router = new Router(); router.route('/foo').all('not a function'); }) }) - it('should not throw if all callbacks are functions', function(){ + it('should not throw if all callbacks are functions', function () { var router = new Router(); - router.route('/foo').all(function(){}).all(function(){}); + router.route('/foo').all(function () { }).all(function () { }); }) }) - describe('error', function(){ - it('should skip non error middleware', function(done){ + describe('error', function () { + it('should skip non error middleware', function (done) { var router = new Router(); - router.get('/foo', function(req, res, next){ + router.get('/foo', function (req, res, next) { next(new Error('foo')); }); - router.get('/bar', function(req, res, next){ + router.get('/bar', function (req, res, next) { next(new Error('bar')); }); - router.use(function(req, res, next){ + router.use(function (req, res, next) { assert(false); }); - router.use(function(err, req, res, next){ + router.use(function (err, req, res, next) { assert.equal(err.message, 'foo'); done(); }); @@ -229,59 +229,59 @@ describe('Router', function(){ router.handle({ url: '/foo', method: 'GET' }, {}, done); }); - it('should handle throwing inside routes with params', function(done) { + it('should handle throwing inside routes with params', function (done) { var router = new Router(); router.get('/foo/:id', function () { throw new Error('foo'); }); - router.use(function(req, res, next){ + router.use(function (req, res, next) { assert(false); }); - router.use(function(err, req, res, next){ + router.use(function (err, req, res, next) { assert.equal(err.message, 'foo'); done(); }); - router.handle({ url: '/foo/2', method: 'GET' }, {}, function() {}); + router.handle({ url: '/foo/2', method: 'GET' }, {}, function () { }); }); - it('should handle throwing in handler after async param', function(done) { + it('should handle throwing in handler after async param', function (done) { var router = new Router(); - router.param('user', function(req, res, next, val){ - process.nextTick(function(){ + router.param('user', function (req, res, next, val) { + process.nextTick(function () { req.user = val; next(); }); }); - router.use('/:user', function(req, res, next){ + router.use('/:user', function (req, res, next) { throw new Error('oh no!'); }); - router.use(function(err, req, res, next){ + router.use(function (err, req, res, next) { assert.equal(err.message, 'oh no!'); done(); }); - router.handle({ url: '/bob', method: 'GET' }, {}, function() {}); + router.handle({ url: '/bob', method: 'GET' }, {}, function () { }); }); - it('should handle throwing inside error handlers', function(done) { + it('should handle throwing inside error handlers', function (done) { var router = new Router(); - router.use(function(req, res, next){ + router.use(function (req, res, next) { throw new Error('boom!'); }); - router.use(function(err, req, res, next){ + router.use(function (err, req, res, next) { throw new Error('oops'); }); - router.use(function(err, req, res, next){ + router.use(function (err, req, res, next) { assert.equal(err.message, 'oops'); done(); }); @@ -412,17 +412,17 @@ describe('Router', function(){ }); }) - describe('.all', function() { - it('should support using .all to capture all http verbs', function(done){ + describe('.all', function () { + it('should support using .all to capture all http verbs', function (done) { var router = new Router(); var count = 0; - router.all('/foo', function(){ count++; }); + router.all('/foo', function () { count++; }); var url = '/foo?bar=baz'; methods.forEach(function testMethod(method) { - router.handle({ url: url, method: method }, {}, function() {}); + router.handle({ url: url, method: method }, {}, function () { }); }); assert.equal(count, methods.length); @@ -430,7 +430,7 @@ describe('Router', function(){ }) }) - describe('.use', function() { + describe('.use', function () { it('should require middleware', function () { var router = new Router() assert.throws(function () { router.use('/') }, /argument handler is required/) @@ -460,7 +460,7 @@ describe('Router', function(){ var cb = after(4, done) var router = new Router() - function no () { + function no() { throw new Error('should not be called') } @@ -474,30 +474,30 @@ describe('Router', function(){ router.handle({ url: '*', method: 'GET' }, { end: cb }, no) }) - it('should accept array of middleware', function(done){ + it('should accept array of middleware', function (done) { var count = 0; var router = new Router(); - function fn1(req, res, next){ + function fn1(req, res, next) { assert.equal(++count, 1); next(); } - function fn2(req, res, next){ + function fn2(req, res, next) { assert.equal(++count, 2); next(); } - router.use([fn1, fn2], function(req, res){ + router.use([fn1, fn2], function (req, res) { assert.equal(++count, 3); done(); }); - router.handle({ url: '/foo', method: 'GET' }, {}, function(){}); + router.handle({ url: '/foo', method: 'GET' }, {}, function () { }); }) }) - describe('.param', function() { + describe('.param', function () { it('should require function', function () { var router = new Router(); assert.throws(router.param.bind(router, 'id'), /argument fn is required/); @@ -508,15 +508,15 @@ describe('Router', function(){ assert.throws(router.param.bind(router, 'id', 42), /argument fn must be a function/); }); - it('should call param function when routing VERBS', function(done) { + it('should call param function when routing VERBS', function (done) { var router = new Router(); - router.param('id', function(req, res, next, id) { + router.param('id', function (req, res, next, id) { assert.equal(id, '123'); next(); }); - router.get('/foo/:id/bar', function(req, res, next) { + router.get('/foo/:id/bar', function (req, res, next) { assert.equal(req.params.id, '123'); next(); }); @@ -524,15 +524,15 @@ describe('Router', function(){ router.handle({ url: '/foo/123/bar', method: 'get' }, {}, done); }); - it('should call param function when routing middleware', function(done) { + it('should call param function when routing middleware', function (done) { var router = new Router(); - router.param('id', function(req, res, next, id) { + router.param('id', function (req, res, next, id) { assert.equal(id, '123'); next(); }); - router.use('/foo/:id/bar', function(req, res, next) { + router.use('/foo/:id/bar', function (req, res, next) { assert.equal(req.params.id, '123'); assert.equal(req.url, '/baz'); next(); @@ -541,17 +541,17 @@ describe('Router', function(){ router.handle({ url: '/foo/123/bar/baz', method: 'get' }, {}, done); }); - it('should only call once per request', function(done) { + it('should only call once per request', function (done) { var count = 0; var req = { url: '/foo/bob/bar', method: 'get' }; var router = new Router(); var sub = new Router(); - sub.get('/bar', function(req, res, next) { + sub.get('/bar', function (req, res, next) { next(); }); - router.param('user', function(req, res, next, user) { + router.param('user', function (req, res, next, user) { count++; req.user = user; next(); @@ -560,7 +560,7 @@ describe('Router', function(){ router.use('/foo/:user/', new Router()); router.use('/foo/:user/', sub); - router.handle(req, {}, function(err) { + router.handle(req, {}, function (err) { if (err) return done(err); assert.equal(count, 1); assert.equal(req.user, 'bob'); @@ -568,17 +568,17 @@ describe('Router', function(){ }); }); - it('should call when values differ', function(done) { + it('should call when values differ', function (done) { var count = 0; var req = { url: '/foo/bob/bar', method: 'get' }; var router = new Router(); var sub = new Router(); - sub.get('/bar', function(req, res, next) { + sub.get('/bar', function (req, res, next) { next(); }); - router.param('user', function(req, res, next, user) { + router.param('user', function (req, res, next, user) { count++; req.user = user; next(); @@ -587,7 +587,7 @@ describe('Router', function(){ router.use('/foo/:user/', new Router()); router.use('/:user/bob/', sub); - router.handle(req, {}, function(err) { + router.handle(req, {}, function (err) { if (err) return done(err); assert.equal(count, 2); assert.equal(req.user, 'foo'); @@ -596,8 +596,8 @@ describe('Router', function(){ }); }); - describe('parallel requests', function() { - it('should not mix requests', function(done) { + describe('parallel requests', function () { + it('should not mix requests', function (done) { var req1 = { url: '/foo/50/bar', method: 'get' }; var req2 = { url: '/foo/10/bar', method: 'get' }; var router = new Router(); @@ -605,11 +605,11 @@ describe('Router', function(){ var cb = after(2, done) - sub.get('/bar', function(req, res, next) { + sub.get('/bar', function (req, res, next) { next(); }); - router.param('ms', function(req, res, next, ms) { + router.param('ms', function (req, res, next, ms) { ms = parseInt(ms, 10); req.ms = ms; setTimeout(next, ms); @@ -618,14 +618,14 @@ describe('Router', function(){ router.use('/foo/:ms/', new Router()); router.use('/foo/:ms/', sub); - router.handle(req1, {}, function(err) { + router.handle(req1, {}, function (err) { assert.ifError(err); assert.equal(req1.ms, 50); assert.equal(req1.originalUrl, '/foo/50/bar'); cb() }); - router.handle(req2, {}, function(err) { + router.handle(req2, {}, function (err) { assert.ifError(err); assert.equal(req2.ms, 10); assert.equal(req2.originalUrl, '/foo/10/bar'); diff --git a/test/app.engine.js b/test/app.engine.js index 214510a94c0..b0553aa247e 100644 --- a/test/app.engine.js +++ b/test/app.engine.js @@ -1,9 +1,9 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('../') - , fs = require('fs'); -var path = require('path') + , fs = require('node:fs'); +var path = require('node:path') function render(path, options, fn) { fs.readFile(path, 'utf8', function(err, str){ diff --git a/test/app.head.js b/test/app.head.js index fabb98795ab..0207caaedad 100644 --- a/test/app.head.js +++ b/test/app.head.js @@ -2,7 +2,7 @@ var express = require('../'); var request = require('supertest'); -var assert = require('assert'); +var assert = require('node:assert'); describe('HEAD', function(){ it('should default to GET', function(done){ diff --git a/test/app.js b/test/app.js index fe7d4c2758a..c1e815a052d 100644 --- a/test/app.js +++ b/test/app.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('..') var request = require('supertest') diff --git a/test/app.listen.js b/test/app.listen.js index 7e7e731a3b8..180162a0fae 100644 --- a/test/app.listen.js +++ b/test/app.listen.js @@ -1,7 +1,7 @@ 'use strict' var express = require('../') -var assert = require('assert') +var assert = require('node:assert') describe('app.listen()', function(){ it('should wrap with an HTTP server', function(done){ diff --git a/test/app.locals.js b/test/app.locals.js index a4f804fe2a2..3963762fe2b 100644 --- a/test/app.locals.js +++ b/test/app.locals.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('../') describe('app', function(){ diff --git a/test/app.render.js b/test/app.render.js index 9d202acfdda..ca15e761d35 100644 --- a/test/app.render.js +++ b/test/app.render.js @@ -1,8 +1,8 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('..'); -var path = require('path') +var path = require('node:path') var tmpl = require('./support/tmpl'); describe('app', function(){ diff --git a/test/app.request.js b/test/app.request.js index 4930af84c25..b6c00f5baa3 100644 --- a/test/app.request.js +++ b/test/app.request.js @@ -10,7 +10,7 @@ describe('app', function(){ var app = express(); app.request.querystring = function(){ - return require('url').parse(this.url).query; + return require('node:url').parse(this.url).query; }; app.use(function(req, res){ diff --git a/test/app.router.js b/test/app.router.js index 61b48eb4a39..017f4f4ef45 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -3,26 +3,26 @@ var after = require('after'); var express = require('../') , request = require('supertest') - , assert = require('assert') + , assert = require('node:assert') , methods = require('../lib/utils').methods; var shouldSkipQuery = require('./support/utils').shouldSkipQuery -describe('app.router', function(){ - it('should restore req.params after leaving router', function(done){ +describe('app.router', function () { + it('should restore req.params after leaving router', function (done) { var app = express(); var router = new express.Router(); - function handler1(req, res, next){ + function handler1(req, res, next) { res.setHeader('x-user-id', String(req.params.id)); next() } - function handler2(req, res){ + function handler2(req, res) { res.send(req.params.id); } - router.use(function(req, res, next){ + router.use(function (req, res, next) { res.setHeader('x-router', String(req.params.id)); next(); }); @@ -30,32 +30,32 @@ describe('app.router', function(){ app.get('/user/:id', handler1, router, handler2); request(app) - .get('/user/1') - .expect('x-router', 'undefined') - .expect('x-user-id', '1') - .expect(200, '1', done); + .get('/user/1') + .expect('x-router', 'undefined') + .expect('x-user-id', '1') + .expect(200, '1', done); }) - describe('methods', function(){ - methods.forEach(function(method){ + describe('methods', function () { + methods.forEach(function (method) { if (method === 'connect') return; - it('should include ' + method.toUpperCase(), function(done){ + it('should include ' + method.toUpperCase(), function (done) { if (method === 'query' && shouldSkipQuery(process.versions.node)) { this.skip() } var app = express(); - app[method]('/foo', function(req, res){ + app[method]('/foo', function (req, res) { res.send(method) }); request(app) [method]('/foo') - .expect(200, done) + .expect(200, done) }) - it('should reject numbers for app.' + method, function(){ + it('should reject numbers for app.' + method, function () { var app = express(); assert.throws(app[method].bind(app, '/', 3), /argument handler must be a function/); }) @@ -77,22 +77,22 @@ describe('app.router', function(){ }); request(app) - .get('/') - .expect(404, cb) + .get('/') + .expect(404, cb) request(app) - .delete('/') - .expect(200, 'deleted everything', cb); + .delete('/') + .expect(200, 'deleted everything', cb); request(app) - .post('/') - .expect('X-Method-Altered', '1') - .expect(200, 'deleted everything', cb); + .post('/') + .expect('X-Method-Altered', '1') + .expect(200, 'deleted everything', cb); }); }) describe('decode params', function () { - it('should decode correct params', function(done){ + it('should decode correct params', function (done) { var app = express(); app.get('/:name', function (req, res) { @@ -100,11 +100,11 @@ describe('app.router', function(){ }); request(app) - .get('/foo%2Fbar') - .expect('foo/bar', done); + .get('/foo%2Fbar') + .expect('foo/bar', done); }) - it('should not accept params in malformed paths', function(done) { + it('should not accept params in malformed paths', function (done) { var app = express(); app.get('/:name', function (req, res) { @@ -112,11 +112,11 @@ describe('app.router', function(){ }); request(app) - .get('/%foobar') - .expect(400, done); + .get('/%foobar') + .expect(400, done); }) - it('should not decode spaces', function(done) { + it('should not decode spaces', function (done) { var app = express(); app.get('/:name', function (req, res) { @@ -124,11 +124,11 @@ describe('app.router', function(){ }); request(app) - .get('/foo+bar') - .expect('foo+bar', done); + .get('/foo+bar') + .expect('foo+bar', done); }) - it('should work with unicode', function(done) { + it('should work with unicode', function (done) { var app = express(); app.get('/:name', function (req, res) { @@ -136,77 +136,77 @@ describe('app.router', function(){ }); request(app) - .get('/%ce%b1') - .expect('\u03b1', done); + .get('/%ce%b1') + .expect('\u03b1', done); }) }) - it('should be .use()able', function(done){ + it('should be .use()able', function (done) { var app = express(); var calls = []; - app.use(function(req, res, next){ + app.use(function (req, res, next) { calls.push('before'); next(); }); - app.get('/', function(req, res, next){ + app.get('/', function (req, res, next) { calls.push('GET /') next(); }); - app.use(function(req, res, next){ + app.use(function (req, res, next) { calls.push('after'); res.json(calls) }); request(app) - .get('/') - .expect(200, ['before', 'GET /', 'after'], done) + .get('/') + .expect(200, ['before', 'GET /', 'after'], done) }) - describe('when given a regexp', function(){ - it('should match the pathname only', function(done){ + describe('when given a regexp', function () { + it('should match the pathname only', function (done) { var app = express(); - app.get(/^\/user\/[0-9]+$/, function(req, res){ + app.get(/^\/user\/[0-9]+$/, function (req, res) { res.end('user'); }); request(app) - .get('/user/12?foo=bar') - .expect('user', done); + .get('/user/12?foo=bar') + .expect('user', done); }) - it('should populate req.params with the captures', function(done){ + it('should populate req.params with the captures', function (done) { var app = express(); - app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function(req, res){ + app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function (req, res) { var id = req.params[0] , op = req.params[1]; res.end(op + 'ing user ' + id); }); request(app) - .get('/user/10/edit') - .expect('editing user 10', done); + .get('/user/10/edit') + .expect('editing user 10', done); }) if (supportsRegexp('(?.*)')) { - it('should populate req.params with named captures', function(done){ + it('should populate req.params with named captures', function (done) { var app = express(); var re = new RegExp('^/user/(?[0-9]+)/(view|edit)?$'); - app.get(re, function(req, res){ + app.get(re, function (req, res) { var id = req.params.userId , op = req.params[0]; res.end(op + 'ing user ' + id); }); request(app) - .get('/user/10/edit') - .expect('editing user 10', done); + .get('/user/10/edit') + .expect('editing user 10', done); }) } @@ -240,153 +240,153 @@ describe('app.router', function(){ }) }) - describe('case sensitivity', function(){ - it('should be disabled by default', function(done){ + describe('case sensitivity', function () { + it('should be disabled by default', function (done) { var app = express(); - app.get('/user', function(req, res){ + app.get('/user', function (req, res) { res.end('tj'); }); request(app) - .get('/USER') - .expect('tj', done); + .get('/USER') + .expect('tj', done); }) - describe('when "case sensitive routing" is enabled', function(){ - it('should match identical casing', function(done){ + describe('when "case sensitive routing" is enabled', function () { + it('should match identical casing', function (done) { var app = express(); app.enable('case sensitive routing'); - app.get('/uSer', function(req, res){ + app.get('/uSer', function (req, res) { res.end('tj'); }); request(app) - .get('/uSer') - .expect('tj', done); + .get('/uSer') + .expect('tj', done); }) - it('should not match otherwise', function(done){ + it('should not match otherwise', function (done) { var app = express(); app.enable('case sensitive routing'); - app.get('/uSer', function(req, res){ + app.get('/uSer', function (req, res) { res.end('tj'); }); request(app) - .get('/user') - .expect(404, done); + .get('/user') + .expect(404, done); }) }) }) - describe('params', function(){ - it('should overwrite existing req.params by default', function(done){ + describe('params', function () { + it('should overwrite existing req.params by default', function (done) { var app = express(); var router = new express.Router(); - router.get('/:action', function(req, res){ + router.get('/:action', function (req, res) { res.send(req.params); }); app.use('/user/:user', router); request(app) - .get('/user/1/get') - .expect(200, '{"action":"get"}', done); + .get('/user/1/get') + .expect(200, '{"action":"get"}', done); }) - it('should allow merging existing req.params', function(done){ + it('should allow merging existing req.params', function (done) { var app = express(); var router = new express.Router({ mergeParams: true }); - router.get('/:action', function(req, res){ + router.get('/:action', function (req, res) { var keys = Object.keys(req.params).sort(); - res.send(keys.map(function(k){ return [k, req.params[k]] })); + res.send(keys.map(function (k) { return [k, req.params[k]] })); }); app.use('/user/:user', router); request(app) - .get('/user/tj/get') - .expect(200, '[["action","get"],["user","tj"]]', done); + .get('/user/tj/get') + .expect(200, '[["action","get"],["user","tj"]]', done); }) - it('should use params from router', function(done){ + it('should use params from router', function (done) { var app = express(); var router = new express.Router({ mergeParams: true }); - router.get('/:thing', function(req, res){ + router.get('/:thing', function (req, res) { var keys = Object.keys(req.params).sort(); - res.send(keys.map(function(k){ return [k, req.params[k]] })); + res.send(keys.map(function (k) { return [k, req.params[k]] })); }); app.use('/user/:thing', router); request(app) - .get('/user/tj/get') - .expect(200, '[["thing","get"]]', done); + .get('/user/tj/get') + .expect(200, '[["thing","get"]]', done); }) - it('should merge numeric indices req.params', function(done){ + it('should merge numeric indices req.params', function (done) { var app = express(); var router = new express.Router({ mergeParams: true }); router.get(/^\/(.*)\.(.*)/, function (req, res) { var keys = Object.keys(req.params).sort(); - res.send(keys.map(function(k){ return [k, req.params[k]] })); + res.send(keys.map(function (k) { return [k, req.params[k]] })); }); app.use(/^\/user\/id:(\d+)/, router); request(app) - .get('/user/id:10/profile.json') - .expect(200, '[["0","10"],["1","profile"],["2","json"]]', done); + .get('/user/id:10/profile.json') + .expect(200, '[["0","10"],["1","profile"],["2","json"]]', done); }) - it('should merge numeric indices req.params when more in parent', function(done){ + it('should merge numeric indices req.params when more in parent', function (done) { var app = express(); var router = new express.Router({ mergeParams: true }); router.get(/\/(.*)/, function (req, res) { var keys = Object.keys(req.params).sort(); - res.send(keys.map(function(k){ return [k, req.params[k]] })); + res.send(keys.map(function (k) { return [k, req.params[k]] })); }); app.use(/^\/user\/id:(\d+)\/name:(\w+)/, router); request(app) - .get('/user/id:10/name:tj/profile') - .expect(200, '[["0","10"],["1","tj"],["2","profile"]]', done); + .get('/user/id:10/name:tj/profile') + .expect(200, '[["0","10"],["1","tj"],["2","profile"]]', done); }) - it('should merge numeric indices req.params when parent has same number', function(done){ + it('should merge numeric indices req.params when parent has same number', function (done) { var app = express(); var router = new express.Router({ mergeParams: true }); - router.get(/\/name:(\w+)/, function(req, res){ + router.get(/\/name:(\w+)/, function (req, res) { var keys = Object.keys(req.params).sort(); - res.send(keys.map(function(k){ return [k, req.params[k]] })); + res.send(keys.map(function (k) { return [k, req.params[k]] })); }); app.use(/\/user\/id:(\d+)/, router); request(app) - .get('/user/id:10/name:tj') - .expect(200, '[["0","10"],["1","tj"]]', done); + .get('/user/id:10/name:tj') + .expect(200, '[["0","10"],["1","tj"]]', done); }) - it('should ignore invalid incoming req.params', function(done){ + it('should ignore invalid incoming req.params', function (done) { var app = express(); var router = new express.Router({ mergeParams: true }); - router.get('/:name', function(req, res){ + router.get('/:name', function (req, res) { var keys = Object.keys(req.params).sort(); - res.send(keys.map(function(k){ return [k, req.params[k]] })); + res.send(keys.map(function (k) { return [k, req.params[k]] })); }); app.use('/user/', function (req, res, next) { @@ -395,11 +395,11 @@ describe('app.router', function(){ }); request(app) - .get('/user/tj') - .expect(200, '[["name","tj"]]', done); + .get('/user/tj') + .expect(200, '[["name","tj"]]', done); }) - it('should restore req.params', function(done){ + it('should restore req.params', function (done) { var app = express(); var router = new express.Router({ mergeParams: true }); @@ -410,45 +410,45 @@ describe('app.router', function(){ app.use(/\/user\/id:(\d+)/, function (req, res, next) { router(req, res, function (err) { var keys = Object.keys(req.params).sort(); - res.send(keys.map(function(k){ return [k, req.params[k]] })); + res.send(keys.map(function (k) { return [k, req.params[k]] })); }); }); request(app) - .get('/user/id:42/user:tj/profile') - .expect(200, '[["0","42"]]', done); + .get('/user/id:42/user:tj/profile') + .expect(200, '[["0","42"]]', done); }) }) - describe('trailing slashes', function(){ - it('should be optional by default', function(done){ + describe('trailing slashes', function () { + it('should be optional by default', function (done) { var app = express(); - app.get('/user', function(req, res){ + app.get('/user', function (req, res) { res.end('tj'); }); request(app) - .get('/user/') - .expect('tj', done); + .get('/user/') + .expect('tj', done); }) - describe('when "strict routing" is enabled', function(){ - it('should match trailing slashes', function(done){ + describe('when "strict routing" is enabled', function () { + it('should match trailing slashes', function (done) { var app = express(); app.enable('strict routing'); - app.get('/user/', function(req, res){ + app.get('/user/', function (req, res) { res.end('tj'); }); request(app) - .get('/user/') - .expect('tj', done); + .get('/user/') + .expect('tj', done); }) - it('should pass-though middleware', function(done){ + it('should pass-though middleware', function (done) { var app = express(); app.enable('strict routing'); @@ -458,17 +458,17 @@ describe('app.router', function(){ next(); }); - app.get('/user/', function(req, res){ + app.get('/user/', function (req, res) { res.end('tj'); }); request(app) - .get('/user/') - .expect('x-middleware', 'true') - .expect(200, 'tj', done); + .get('/user/') + .expect('x-middleware', 'true') + .expect(200, 'tj', done); }) - it('should pass-though mounted middleware', function(done){ + it('should pass-though mounted middleware', function (done) { var app = express(); app.enable('strict routing'); @@ -478,106 +478,106 @@ describe('app.router', function(){ next(); }); - app.get('/user/test/', function(req, res){ + app.get('/user/test/', function (req, res) { res.end('tj'); }); request(app) - .get('/user/test/') - .expect('x-middleware', 'true') - .expect(200, 'tj', done); + .get('/user/test/') + .expect('x-middleware', 'true') + .expect(200, 'tj', done); }) - it('should match no slashes', function(done){ + it('should match no slashes', function (done) { var app = express(); app.enable('strict routing'); - app.get('/user', function(req, res){ + app.get('/user', function (req, res) { res.end('tj'); }); request(app) - .get('/user') - .expect('tj', done); + .get('/user') + .expect('tj', done); }) - it('should match middleware when omitting the trailing slash', function(done){ + it('should match middleware when omitting the trailing slash', function (done) { var app = express(); app.enable('strict routing'); - app.use('/user/', function(req, res){ + app.use('/user/', function (req, res) { res.end('tj'); }); request(app) - .get('/user') - .expect(200, 'tj', done); + .get('/user') + .expect(200, 'tj', done); }) - it('should match middleware', function(done){ + it('should match middleware', function (done) { var app = express(); app.enable('strict routing'); - app.use('/user', function(req, res){ + app.use('/user', function (req, res) { res.end('tj'); }); request(app) - .get('/user') - .expect(200, 'tj', done); + .get('/user') + .expect(200, 'tj', done); }) - it('should match middleware when adding the trailing slash', function(done){ + it('should match middleware when adding the trailing slash', function (done) { var app = express(); app.enable('strict routing'); - app.use('/user', function(req, res){ + app.use('/user', function (req, res) { res.end('tj'); }); request(app) - .get('/user/') - .expect(200, 'tj', done); + .get('/user/') + .expect(200, 'tj', done); }) - it('should fail when omitting the trailing slash', function(done){ + it('should fail when omitting the trailing slash', function (done) { var app = express(); app.enable('strict routing'); - app.get('/user/', function(req, res){ + app.get('/user/', function (req, res) { res.end('tj'); }); request(app) - .get('/user') - .expect(404, done); + .get('/user') + .expect(404, done); }) - it('should fail when adding the trailing slash', function(done){ + it('should fail when adding the trailing slash', function (done) { var app = express(); app.enable('strict routing'); - app.get('/user', function(req, res){ + app.get('/user', function (req, res) { res.end('tj'); }); request(app) - .get('/user/') - .expect(404, done); + .get('/user/') + .expect(404, done); }) }) }) - it('should allow literal "."', function(done){ + it('should allow literal "."', function (done) { var app = express(); - app.get('/api/users/:from..:to', function(req, res){ + app.get('/api/users/:from..:to', function (req, res) { var from = req.params.from , to = req.params.to; @@ -585,119 +585,119 @@ describe('app.router', function(){ }); request(app) - .get('/api/users/1..50') - .expect('users from 1 to 50', done); + .get('/api/users/1..50') + .expect('users from 1 to 50', done); }) - describe(':name', function(){ - it('should denote a capture group', function(done){ + describe(':name', function () { + it('should denote a capture group', function (done) { var app = express(); - app.get('/user/:user', function(req, res){ + app.get('/user/:user', function (req, res) { res.end(req.params.user); }); request(app) - .get('/user/tj') - .expect('tj', done); + .get('/user/tj') + .expect('tj', done); }) - it('should match a single segment only', function(done){ + it('should match a single segment only', function (done) { var app = express(); - app.get('/user/:user', function(req, res){ + app.get('/user/:user', function (req, res) { res.end(req.params.user); }); request(app) - .get('/user/tj/edit') - .expect(404, done); + .get('/user/tj/edit') + .expect(404, done); }) - it('should allow several capture groups', function(done){ + it('should allow several capture groups', function (done) { var app = express(); - app.get('/user/:user/:op', function(req, res){ + app.get('/user/:user/:op', function (req, res) { res.end(req.params.op + 'ing ' + req.params.user); }); request(app) - .get('/user/tj/edit') - .expect('editing tj', done); + .get('/user/tj/edit') + .expect('editing tj', done); }) - it('should work following a partial capture group', function(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){ + app.get('/user{s}/:user/:op', function (req, res) { res.end(req.params.op + 'ing ' + req.params.user + (req.url.startsWith('/users') ? ' (old)' : '')); }); request(app) - .get('/user/tj/edit') - .expect('editing tj', cb); + .get('/user/tj/edit') + .expect('editing tj', cb); request(app) - .get('/users/tj/edit') - .expect('editing tj (old)', cb); + .get('/users/tj/edit') + .expect('editing tj (old)', cb); }) - it('should work inside literal parenthesis', function(done){ + it('should work inside literal parenthesis', function (done) { var app = express(); - app.get('/:user\\(:op\\)', function(req, res){ + app.get('/:user\\(:op\\)', function (req, res) { res.end(req.params.op + 'ing ' + req.params.user); }); request(app) - .get('/tj(edit)') - .expect('editing tj', done); + .get('/tj(edit)') + .expect('editing tj', done); }) - it('should work in array of paths', function(done){ + it('should work in array of paths', function (done) { var app = express(); var cb = after(2, done); - app.get(['/user/:user/poke', '/user/:user/pokes'], function(req, res){ + app.get(['/user/:user/poke', '/user/:user/pokes'], function (req, res) { res.end('poking ' + req.params.user); }); request(app) - .get('/user/tj/poke') - .expect('poking tj', cb); + .get('/user/tj/poke') + .expect('poking tj', cb); request(app) - .get('/user/tj/pokes') - .expect('poking tj', cb); + .get('/user/tj/pokes') + .expect('poking tj', cb); }) }) - describe(':name?', function(){ - it('should denote an optional capture group', function(done){ + describe(':name?', function () { + it('should denote an optional capture group', function (done) { var app = express(); - app.get('/user/:user{/:op}', function(req, res){ + app.get('/user/:user{/:op}', function (req, res) { var op = req.params.op || 'view'; res.end(op + 'ing ' + req.params.user); }); request(app) - .get('/user/tj') - .expect('viewing tj', done); + .get('/user/tj') + .expect('viewing tj', done); }) - it('should populate the capture group', function(done){ + it('should populate the capture group', function (done) { var app = express(); - app.get('/user/:user{/:op}', function(req, res){ + app.get('/user/:user{/:op}', function (req, res) { var op = req.params.op || 'view'; res.end(op + 'ing ' + req.params.user); }); request(app) - .get('/user/tj/edit') - .expect('editing tj', done); + .get('/user/tj/edit') + .expect('editing tj', done); }) }) @@ -777,12 +777,12 @@ describe('app.router', function(){ }) }) - describe('.:name', function(){ - it('should denote a format', function(done){ + describe('.:name', function () { + it('should denote a format', function (done) { var app = express(); var cb = after(2, done) - app.get('/:name.:format', function(req, res){ + app.get('/:name.:format', function (req, res) { res.end(req.params.name + ' as ' + req.params.format); }); @@ -796,12 +796,12 @@ describe('app.router', function(){ }) }) - describe('.:name?', function(){ - it('should denote an optional format', function(done){ + describe('.:name?', function () { + it('should denote an optional format', function (done) { var app = express(); var cb = after(2, done) - app.get('/:name{.:format}', function(req, res){ + app.get('/:name{.:format}', function (req, res) { res.end(req.params.name + ' as ' + (req.params.format || 'html')); }); @@ -815,12 +815,12 @@ describe('app.router', function(){ }) }) - describe('when next() is called', function(){ - it('should continue lookup', function(done){ + describe('when next() is called', function () { + it('should continue lookup', function (done) { var app = express() , calls = []; - app.get('/foo{/:bar}', function(req, res, next){ + app.get('/foo{/:bar}', function (req, res, next) { calls.push('/foo/:bar?'); next(); }); @@ -829,7 +829,7 @@ describe('app.router', function(){ assert(0); }); - app.get('/foo', function(req, res, next){ + app.get('/foo', function (req, res, next) { calls.push('/foo'); next(); }); @@ -840,16 +840,16 @@ describe('app.router', function(){ }); request(app) - .get('/foo') - .expect(200, ['/foo/:bar?', '/foo', '/foo 2'], done) + .get('/foo') + .expect(200, ['/foo/:bar?', '/foo', '/foo 2'], done) }) }) - describe('when next("route") is called', function(){ - it('should jump to next route', function(done){ + describe('when next("route") is called', function () { + it('should jump to next route', function (done) { var app = express() - function fn(req, res, next){ + function fn(req, res, next) { res.set('X-Hit', '1') next('route') } @@ -858,14 +858,14 @@ describe('app.router', function(){ res.end('failure') }); - app.get('/foo', function(req, res){ + app.get('/foo', function (req, res) { res.end('success') }) request(app) - .get('/foo') - .expect('X-Hit', '1') - .expect(200, 'success', done) + .get('/foo') + .expect('X-Hit', '1') + .expect(200, 'success', done) }) }) @@ -874,7 +874,7 @@ describe('app.router', function(){ var app = express() var router = express.Router() - function fn (req, res, next) { + function fn(req, res, next) { res.set('X-Hit', '1') next('router') } @@ -894,18 +894,18 @@ describe('app.router', function(){ }) request(app) - .get('/foo') - .expect('X-Hit', '1') - .expect(200, 'success', done) + .get('/foo') + .expect('X-Hit', '1') + .expect(200, 'success', done) }) }) - describe('when next(err) is called', function(){ - it('should break out of app.router', function(done){ + describe('when next(err) is called', function () { + it('should break out of app.router', function (done) { var app = express() , calls = []; - app.get('/foo{/:bar}', function(req, res, next){ + app.get('/foo{/:bar}', function (req, res, next) { calls.push('/foo/:bar?'); next(); }); @@ -914,7 +914,7 @@ describe('app.router', function(){ assert(0); }); - app.get('/foo', function(req, res, next){ + app.get('/foo', function (req, res, next) { calls.push('/foo'); next(new Error('fail')); }); @@ -923,7 +923,7 @@ describe('app.router', function(){ assert(0); }); - app.use(function(err, req, res, next){ + app.use(function (err, req, res, next) { res.json({ calls: calls, error: err.message @@ -931,11 +931,11 @@ describe('app.router', function(){ }) request(app) - .get('/foo') - .expect(200, { calls: ['/foo/:bar?', '/foo'], error: 'fail' }, done) + .get('/foo') + .expect(200, { calls: ['/foo/:bar?', '/foo'], error: 'fail' }, done) }) - it('should call handler in same route, if exists', function(done){ + it('should call handler in same route, if exists', function (done) { var app = express(); function fn1(req, res, next) { @@ -957,8 +957,8 @@ describe('app.router', function(){ }) request(app) - .get('/foo') - .expect('route go boom!', done) + .get('/foo') + .expect('route go boom!', done) }) }) @@ -967,45 +967,45 @@ describe('app.router', function(){ var app = express() var router = new express.Router() - router.use(function createError (req, res, next) { + router.use(function createError(req, res, next) { return Promise.reject(new Error('boom!')) }) - router.use(function sawError (err, req, res, next) { + router.use(function sawError(err, req, res, next) { res.send('saw ' + err.name + ': ' + err.message) }) app.use(router) request(app) - .get('/') - .expect(200, 'saw Error: boom!', done) + .get('/') + .expect(200, 'saw Error: boom!', done) }) it('should pass rejected promise without value', function (done) { var app = express() var router = new express.Router() - router.use(function createError (req, res, next) { + router.use(function createError(req, res, next) { return Promise.reject() }) - router.use(function sawError (err, req, res, next) { + router.use(function sawError(err, req, res, next) { res.send('saw ' + err.name + ': ' + err.message) }) app.use(router) request(app) - .get('/') - .expect(200, 'saw Error: Rejected promise', done) + .get('/') + .expect(200, 'saw Error: Rejected promise', done) }) it('should ignore resolved promise', function (done) { var app = express() var router = new express.Router() - router.use(function createError (req, res, next) { + router.use(function createError(req, res, next) { res.send('saw GET /foo') return Promise.resolve('foo') }) @@ -1017,8 +1017,8 @@ describe('app.router', function(){ app.use(router) request(app) - .get('/foo') - .expect(200, 'saw GET /foo', done) + .get('/foo') + .expect(200, 'saw GET /foo', done) }) describe('error handling', function () { @@ -1026,57 +1026,57 @@ describe('app.router', function(){ var app = express() var router = new express.Router() - router.use(function createError (req, res, next) { + router.use(function createError(req, res, next) { return Promise.reject(new Error('boom!')) }) - router.use(function handleError (err, req, res, next) { + router.use(function handleError(err, req, res, next) { return Promise.reject(new Error('caught: ' + err.message)) }) - router.use(function sawError (err, req, res, next) { + router.use(function sawError(err, req, res, next) { res.send('saw ' + err.name + ': ' + err.message) }) app.use(router) request(app) - .get('/') - .expect(200, 'saw Error: caught: boom!', done) + .get('/') + .expect(200, 'saw Error: caught: boom!', done) }) it('should pass rejected promise without value', function (done) { var app = express() var router = new express.Router() - router.use(function createError (req, res, next) { + router.use(function createError(req, res, next) { return Promise.reject() }) - router.use(function handleError (err, req, res, next) { + router.use(function handleError(err, req, res, next) { return Promise.reject(new Error('caught: ' + err.message)) }) - router.use(function sawError (err, req, res, next) { + router.use(function sawError(err, req, res, next) { res.send('saw ' + err.name + ': ' + err.message) }) app.use(router) request(app) - .get('/') - .expect(200, 'saw Error: caught: Rejected promise', done) + .get('/') + .expect(200, 'saw Error: caught: Rejected promise', done) }) it('should ignore resolved promise', function (done) { var app = express() var router = new express.Router() - router.use(function createError (req, res, next) { + router.use(function createError(req, res, next) { return Promise.reject(new Error('boom!')) }) - router.use(function handleError (err, req, res, next) { + router.use(function handleError(err, req, res, next) { res.send('saw ' + err.name + ': ' + err.message) return Promise.resolve('foo') }) @@ -1088,31 +1088,31 @@ describe('app.router', function(){ app.use(router) request(app) - .get('/foo') - .expect(200, 'saw Error: boom!', done) + .get('/foo') + .expect(200, 'saw Error: boom!', done) }) }) }) - it('should allow rewriting of the url', function(done){ + it('should allow rewriting of the url', function (done) { var app = express(); - app.get('/account/edit', function(req, res, next){ + app.get('/account/edit', function (req, res, next) { req.user = { id: 12 }; // faux authenticated user req.url = '/user/' + req.user.id + '/edit'; next(); }); - app.get('/user/:id/edit', function(req, res){ + app.get('/user/:id/edit', function (req, res) { res.send('editing user ' + req.params.id); }); request(app) - .get('/account/edit') - .expect('editing user 12', done); + .get('/account/edit') + .expect('editing user 12', done); }) - it('should run in order added', function(done){ + it('should run in order added', function (done) { var app = express(); var path = []; @@ -1121,17 +1121,17 @@ describe('app.router', function(){ next(); }); - app.get('/user/:id', function(req, res, next){ + app.get('/user/:id', function (req, res, next) { path.push(1); next(); }); - app.use(function(req, res, next){ + app.use(function (req, res, next) { path.push(2); next(); }); - app.all('/user/:id', function(req, res, next){ + app.all('/user/:id', function (req, res, next) { path.push(3); next(); }); @@ -1141,28 +1141,28 @@ describe('app.router', function(){ next(); }); - app.use(function(req, res, next){ + app.use(function (req, res, next) { path.push(5); res.end(path.join(',')) }); request(app) - .get('/user/1') - .expect(200, '0,1,2,3,4,5', done); + .get('/user/1') + .expect(200, '0,1,2,3,4,5', done); }) - it('should be chainable', function(){ + it('should be chainable', function () { var app = express(); - assert.strictEqual(app.get('/', function () {}), app) + assert.strictEqual(app.get('/', function () { }), app) }) - it('should should not use disposed router/middleware', function(done){ + it('should should not use disposed router/middleware', function (done) { // more context: https://github.com/expressjs/express/issues/5743#issuecomment-2277148412 var app = express(); var router = new express.Router(); - router.use(function(req, res, next){ + router.use(function (req, res, next) { res.setHeader('old', 'foo'); next(); }); @@ -1171,39 +1171,39 @@ describe('app.router', function(){ return router.handle(req, res, next); }); - app.get('/', function(req, res, next){ + app.get('/', function (req, res, next) { res.send('yee'); next(); }); request(app) - .get('/') - .expect('old', 'foo') - .expect(function(res) { - if (typeof res.headers['new'] !== 'undefined') { - throw new Error('`new` header should not be present'); - } - }) - .expect(200, 'yee', function(err, res) { - if (err) return done(err); - - router = new express.Router(); - - router.use(function(req, res, next){ - res.setHeader('new', 'bar'); - next(); - }); - - request(app) .get('/') - .expect('new', 'bar') - .expect(function(res) { - if (typeof res.headers['old'] !== 'undefined') { - throw new Error('`old` header should not be present'); + .expect('old', 'foo') + .expect(function (res) { + if (typeof res.headers['new'] !== 'undefined') { + throw new Error('`new` header should not be present'); } }) - .expect(200, 'yee', done); - }); + .expect(200, 'yee', function (err, res) { + if (err) return done(err); + + router = new express.Router(); + + router.use(function (req, res, next) { + res.setHeader('new', 'bar'); + next(); + }); + + request(app) + .get('/') + .expect('new', 'bar') + .expect(function (res) { + if (typeof res.headers['old'] !== 'undefined') { + throw new Error('`old` header should not be present'); + } + }) + .expect(200, 'yee', done); + }); }) }) diff --git a/test/app.routes.error.js b/test/app.routes.error.js index efc0108b0f2..ed53c7857ba 100644 --- a/test/app.routes.error.js +++ b/test/app.routes.error.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('../') , request = require('supertest'); diff --git a/test/app.use.js b/test/app.use.js index a88a2f2c8e9..1d56aa3b029 100644 --- a/test/app.use.js +++ b/test/app.use.js @@ -1,7 +1,7 @@ 'use strict' var after = require('after'); -var assert = require('assert') +var assert = require('node:assert') var express = require('..'); var request = require('supertest'); diff --git a/test/config.js b/test/config.js index b04367fdbf8..d004de03eaa 100644 --- a/test/config.js +++ b/test/config.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert'); +var assert = require('node:assert'); var express = require('..'); describe('config', function () { diff --git a/test/exports.js b/test/exports.js index dc635d1dbcb..fc7836c1594 100644 --- a/test/exports.js +++ b/test/exports.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('../'); var request = require('supertest'); diff --git a/test/express.json.js b/test/express.json.js index 2c394922c82..6b91734ed3b 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -1,7 +1,7 @@ 'use strict' -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage var express = require('..') var request = require('supertest') diff --git a/test/express.raw.js b/test/express.raw.js index 53995bf829c..362fccb1e38 100644 --- a/test/express.raw.js +++ b/test/express.raw.js @@ -1,7 +1,7 @@ 'use strict' -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage var express = require('..') var request = require('supertest') diff --git a/test/express.static.js b/test/express.static.js index 65a3718a601..16a8ec0516f 100644 --- a/test/express.static.js +++ b/test/express.static.js @@ -1,8 +1,8 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('..') -var path = require('path') +var path = require('node:path') var request = require('supertest') var utils = require('./support/utils') diff --git a/test/express.text.js b/test/express.text.js index 95fcbf86570..1d22929e3b2 100644 --- a/test/express.text.js +++ b/test/express.text.js @@ -1,7 +1,7 @@ 'use strict' -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage var express = require('..') var request = require('supertest') diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index 50c3e93bba8..b2df949f9f3 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -1,7 +1,7 @@ 'use strict' -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage var express = require('..') var request = require('supertest') diff --git a/test/middleware.basic.js b/test/middleware.basic.js index 19f00d9a296..1f1ed17571a 100644 --- a/test/middleware.basic.js +++ b/test/middleware.basic.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('../'); var request = require('supertest'); diff --git a/test/req.get.js b/test/req.get.js index 16589b3f059..e73d109c84a 100644 --- a/test/req.get.js +++ b/test/req.get.js @@ -2,7 +2,7 @@ var express = require('../') , request = require('supertest') - , assert = require('assert'); + , assert = require('node:assert'); describe('req', function(){ describe('.get(field)', function(){ diff --git a/test/req.query.js b/test/req.query.js index bc76d4106b5..c0d3c8376e9 100644 --- a/test/req.query.js +++ b/test/req.query.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('../') , request = require('supertest'); diff --git a/test/res.append.js b/test/res.append.js index 8f72598bf52..325dd4d12e0 100644 --- a/test/res.append.js +++ b/test/res.append.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('..') var request = require('supertest') diff --git a/test/res.download.js b/test/res.download.js index 5718ff44096..1bd7663c549 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -1,11 +1,11 @@ 'use strict' var after = require('after'); -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage var express = require('..'); -var path = require('path') +var path = require('node:path') var request = require('supertest'); var utils = require('./support/utils') diff --git a/test/res.format.js b/test/res.format.js index 59205bfaf42..be427309577 100644 --- a/test/res.format.js +++ b/test/res.format.js @@ -3,7 +3,7 @@ var after = require('after') var express = require('../') , request = require('supertest') - , assert = require('assert'); + , assert = require('node:assert'); var app1 = express(); diff --git a/test/res.json.js b/test/res.json.js index bef8adafd53..ffd547e95b2 100644 --- a/test/res.json.js +++ b/test/res.json.js @@ -2,7 +2,7 @@ var express = require('../') , request = require('supertest') - , assert = require('assert'); + , assert = require('node:assert'); describe('res', function(){ describe('.json(object)', function(){ diff --git a/test/res.jsonp.js b/test/res.jsonp.js index e9cc08bc05f..c1f90f11092 100644 --- a/test/res.jsonp.js +++ b/test/res.jsonp.js @@ -2,7 +2,7 @@ var express = require('../') , request = require('supertest') - , assert = require('assert'); + , assert = require('node:assert'); var utils = require('./support/utils'); describe('res', function(){ diff --git a/test/res.location.js b/test/res.location.js index fb03221d7a4..b81c6f07d8d 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -2,8 +2,8 @@ var express = require('../') , request = require('supertest') - , assert = require('assert') - , url = require('url'); + , assert = require('node:assert') + , url = require('node:url'); describe('res', function(){ describe('.location(url)', function(){ diff --git a/test/res.render.js b/test/res.render.js index 50f0b0a7425..114b398e0b4 100644 --- a/test/res.render.js +++ b/test/res.render.js @@ -1,7 +1,7 @@ 'use strict' var express = require('..'); -var path = require('path') +var path = require('node:path') var request = require('supertest'); var tmpl = require('./support/tmpl'); diff --git a/test/res.send.js b/test/res.send.js index b061dfcc511..860607c49b5 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var express = require('..'); var methods = require('../lib/utils').methods; var request = require('supertest'); diff --git a/test/res.sendFile.js b/test/res.sendFile.js index ec90adf5d32..505f8d114de 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -1,13 +1,13 @@ 'use strict' var after = require('after'); -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage var express = require('../') , request = require('supertest') var onFinished = require('on-finished'); -var path = require('path'); +var path = require('node:path'); var fixtures = path.join(__dirname, 'fixtures'); var utils = require('./support/utils'); diff --git a/test/support/tmpl.js b/test/support/tmpl.js index bab65669d33..e24b6fe773b 100644 --- a/test/support/tmpl.js +++ b/test/support/tmpl.js @@ -1,4 +1,4 @@ -var fs = require('fs'); +var fs = require('node:fs'); var variableRegExp = /\$([0-9a-zA-Z\.]+)/g; diff --git a/test/support/utils.js b/test/support/utils.js index c74f8efe0c2..25022528ef6 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -4,7 +4,7 @@ * @private */ -var assert = require('assert'); +var assert = require('node:assert'); /** * Module exports. diff --git a/test/utils.js b/test/utils.js index ae73988b01d..d1142266ac4 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert'); +var assert = require('node:assert'); var utils = require('../lib/utils'); describe('utils.etag(body, encoding)', function(){ From 4f952a953bab47e941ed70a358814ee64c031017 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 8 Jan 2025 17:20:29 -0600 Subject: [PATCH 806/889] fix: remove download size badges --- Readme.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/Readme.md b/Readme.md index c0ae63ebd25..f115e7c80fb 100644 --- a/Readme.md +++ b/Readme.md @@ -20,7 +20,6 @@ [![NPM Version][npm-version-image]][npm-url] -[![NPM Install Size][npm-install-size-image]][npm-install-size-url] [![NPM Downloads][npm-downloads-image]][npm-downloads-url] [![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer] @@ -257,8 +256,6 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) [github-actions-ci-url]: https://github.com/expressjs/express/actions/workflows/ci.yml [npm-downloads-image]: https://badgen.net/npm/dm/express [npm-downloads-url]: https://npmcharts.com/compare/express?minimal=true -[npm-install-size-image]: https://badgen.net/packagephobia/install/express -[npm-install-size-url]: https://packagephobia.com/result?p=express [npm-url]: https://npmjs.org/package/express [npm-version-image]: https://badgen.net/npm/v/express [ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/express/badge From 256a3d152794e6166f204f80b4400d8acad0f947 Mon Sep 17 00:00:00 2001 From: Jon Koops Date: Mon, 2 Dec 2024 11:03:36 +0100 Subject: [PATCH 807/889] Remove unused `depd` dependency Signed-off-by: Jon Koops --- History.md | 1 + package.json | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 5323220bcd5..25e29250f92 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,7 @@ unreleased * perf: use loop for acceptParams * Replace `methods` dependency with standard library * refactor: prefix built-in node module imports +* Remove unused `depd` dependency 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index da580992995..a0cc7b69d2b 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "cookie": "0.7.1", "cookie-signature": "^1.2.1", "debug": "4.3.6", - "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", From 1c5cf0feaddc46a2698457a49cf82bdb52b774b5 Mon Sep 17 00:00:00 2001 From: Hamir Mahal Date: Wed, 8 Jan 2025 11:36:06 -0800 Subject: [PATCH 808/889] refactor: remove `Invalid action input` --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5668ed2f22b..e4df6442b29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,6 @@ jobs: uses: actions/setup-node@v4 with: node-version: 'lts/*' - persist-credentials: false - name: Install dependencies run: npm install --ignore-scripts --only=dev From ff86319ed5384bb9907802a33716263f569e407d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Wed, 15 Jan 2025 07:39:30 +0100 Subject: [PATCH 809/889] ci: add support for OSSF scorecard reporting (#5431) --- .github/workflows/scorecard.yml | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000000..3bfd85a781a --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,72 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '16 21 * * 1' + push: + branches: [ "master" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # v2.0.6 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@2f93e4319b2f04a2efc38fa7f78bd681bc3f7b2f # v2.23.2 + with: + sarif_file: results.sarif \ No newline at end of file From 3bbffdc41c1adebd1c4297e3661e2b182b8d27ac Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 13 Jan 2025 13:30:47 -0500 Subject: [PATCH 810/889] docs: add @Phillip9587 to the triage team --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index f115e7c80fb..8dc52ca2588 100644 --- a/Readme.md +++ b/Readme.md @@ -209,6 +209,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him) * [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego** * [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him) +* [Phillip9587](https://github.com/Phillip9587) - **Phillip Barta** * [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger** * [rxmarbles](https://github.com/rxmarbles) **Rick Markins** (He/him) From 62336717bfb6ff0ddca1c320cab76218928e7f93 Mon Sep 17 00:00:00 2001 From: prajesh <75523737+pr4j3sh@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:24:07 +0530 Subject: [PATCH 811/889] fix: added a missing semicolon in css styles in examples/auth (#6297) --- examples/auth/views/head.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/auth/views/head.ejs b/examples/auth/views/head.ejs index 65386267d0d..c623b5cc8d1 100644 --- a/examples/auth/views/head.ejs +++ b/examples/auth/views/head.ejs @@ -10,7 +10,7 @@ font: 13px Helvetica, Arial, sans-serif; } .error { - color: red + color: red; } .success { color: green; From 7f13d572c13228856822af9ba4a7a094f4784ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 4 Feb 2025 11:28:18 +0100 Subject: [PATCH 812/889] docs: include team email in the security policy (#6278) --- Security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Security.md b/Security.md index dcfbe88abd4..ff106d62104 100644 --- a/Security.md +++ b/Security.md @@ -14,7 +14,7 @@ Thank you for improving the security of Express. We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions. -Report security bugs by emailing the lead maintainer in the Readme.md file. +Report security bugs by emailing `express-security@lists.openjsf.org`. To ensure the timely response to your report, please ensure that the entirety of the report is contained within the email body and not solely behind a web From 511d9dfca8f2329534ee9c75990163766b82c407 Mon Sep 17 00:00:00 2001 From: Ayoub Mabrouk <77799760+Ayoub-Mabrouk@users.noreply.github.com> Date: Tue, 4 Feb 2025 11:59:48 +0100 Subject: [PATCH 813/889] refactor: simplify `normalizeTypes` function (#6097) --- lib/utils.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index d11f8aa1686..d53c5a13374 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -70,16 +70,11 @@ exports.normalizeType = function(type){ * @api private */ -exports.normalizeTypes = function(types){ - var ret = []; - - for (var i = 0; i < types.length; ++i) { - ret.push(exports.normalizeType(types[i])); - } - - return ret; +exports.normalizeTypes = function(types) { + return types.map(exports.normalizeType); }; + /** * Parse accept params `str` returning an * object with `.value`, `.quality` and `.params`. From a5cb681eb8f5b61336ac2ce1424b3448711724f2 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Wed, 5 Feb 2025 13:27:59 +0100 Subject: [PATCH 814/889] ci: updated github actions ci workflow (#6314) --- .github/workflows/ci.yml | 66 +++++++++++++++++------------------- .github/workflows/legacy.yml | 62 ++++++++++++++++----------------- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4df6442b29..a04ea38e025 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,9 @@ on: paths-ignore: - '*.md' +permissions: + contents: read + # Cancel in progress workflows # in the scenario where we already had a run going for that PR/branch/tag but then triggered a new run concurrency: @@ -26,13 +29,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Setup Node.js {{ matrix.node-version }} + - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 'lts/*' - name: Install dependencies - run: npm install --ignore-scripts --only=dev + run: npm install --ignore-scripts --inlcude=dev - name: Run lint run: npm run lint @@ -73,44 +76,39 @@ jobs: - name: Run tests shell: bash - run: | - npm run test-ci - cp coverage/lcov.info "coverage/${{ matrix.node-version }}.lcov" - - - name: Collect code coverage - run: | - mv ./coverage "./${{ matrix.node-version }}" - mkdir ./coverage - mv "./${{ matrix.node-version }}" "./coverage/${{ matrix.node-version }}" + run: npm run test-ci - name: Upload code coverage - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: coverage - path: ./coverage + name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }} + path: ./coverage/lcov.info retention-days: 1 coverage: needs: test runs-on: ubuntu-latest + permissions: + contents: read + checks: write steps: - - uses: actions/checkout@v4 - - - name: Install lcov - shell: bash - run: sudo apt-get -y install lcov - - - name: Collect coverage reports - uses: actions/download-artifact@v3 - with: - name: coverage - path: ./coverage - - - name: Merge coverage reports - shell: bash - run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./coverage/lcov.info - - - name: Upload coverage report - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v4 + + - name: Install lcov + shell: bash + run: sudo apt-get -y install lcov + + - name: Collect coverage reports + uses: actions/download-artifact@v4 + with: + path: ./coverage + pattern: coverage-node-* + + - name: Merge coverage reports + shell: bash + run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./lcov.info + + - name: Upload coverage report + uses: coverallsapp/github-action@v2 + with: + file: ./lcov.info diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index d26d6df34d2..6139f2fd9b7 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -14,6 +14,9 @@ on: paths-ignore: - '*.md' +permissions: + contents: read + # Cancel in progress workflows # in the scenario where we already had a run going for that PR/branch/tag but then triggered a new run concurrency: @@ -57,44 +60,39 @@ jobs: - name: Run tests shell: bash - run: | - npm run test-ci - cp coverage/lcov.info "coverage/${{ matrix.node-version }}.lcov" - - - name: Collect code coverage - run: | - mv ./coverage "./${{ matrix.node-version }}" - mkdir ./coverage - mv "./${{ matrix.node-version }}" "./coverage/${{ matrix.node-version }}" + run: npm run test-ci - name: Upload code coverage - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: coverage - path: ./coverage + name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }} + path: ./coverage/lcov.info retention-days: 1 coverage: needs: test runs-on: ubuntu-latest + permissions: + contents: read + checks: write steps: - - uses: actions/checkout@v4 - - - name: Install lcov - shell: bash - run: sudo apt-get -y install lcov - - - name: Collect coverage reports - uses: actions/download-artifact@v3 - with: - name: coverage - path: ./coverage - - - name: Merge coverage reports - shell: bash - run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./coverage/lcov.info - - - name: Upload coverage report - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v4 + + - name: Install lcov + shell: bash + run: sudo apt-get -y install lcov + + - name: Collect coverage reports + uses: actions/download-artifact@v4 + with: + path: ./coverage + pattern: coverage-node-* + + - name: Merge coverage reports + shell: bash + run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./lcov.info + + - name: Upload coverage report + uses: coverallsapp/github-action@v2 + with: + file: ./lcov.info From 8d393459026192e788c8b60fee6b59c426266f94 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Wed, 5 Feb 2025 18:25:48 +0100 Subject: [PATCH 815/889] fix(ci): fix npm install --include typo (#6324) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a04ea38e025..e68bdfd724b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: node-version: 'lts/*' - name: Install dependencies - run: npm install --ignore-scripts --inlcude=dev + run: npm install --ignore-scripts --include=dev - name: Run lint run: npm run lint From ae6a4621bc19ae9d2e4d9d083baca0f422d7b536 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Wed, 5 Feb 2025 18:40:08 +0100 Subject: [PATCH 816/889] fix(ci): updated scorecard actions (#6322) --- .github/workflows/scorecard.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 3bfd85a781a..e9cdbdf1542 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,12 +32,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # v2.0.6 + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 with: results_file: results.sarif results_format: sarif @@ -59,7 +59,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: SARIF file path: results.sarif @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@2f93e4319b2f04a2efc38fa7f78bd681bc3f7b2f # v2.23.2 + uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 with: sarif_file: results.sarif \ No newline at end of file From af7cd90893f4619212e01f271fbaa10f3176fb33 Mon Sep 17 00:00:00 2001 From: Dustin Popp Date: Wed, 5 Feb 2025 12:05:39 -0600 Subject: [PATCH 817/889] feat(deps): use carat notation for dependency versions (#6317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dustin Popp Co-authored-by: Ulises Gascón --- package.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index a0cc7b69d2b..196831fc7b2 100644 --- a/package.json +++ b/package.json @@ -35,30 +35,30 @@ "accepts": "^2.0.0", "body-parser": "^2.0.1", "content-disposition": "^1.0.0", - "content-type": "~1.0.4", - "cookie": "0.7.1", + "content-type": "^1.0.4", + "cookie": "^0.7.1", "cookie-signature": "^1.2.1", - "debug": "4.3.6", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", + "debug": "^4.3.6", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", "finalhandler": "^2.0.0", - "fresh": "2.0.0", - "http-errors": "2.0.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", - "on-finished": "2.4.1", - "once": "1.4.0", - "parseurl": "~1.3.3", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.13.0", + "range-parser": "^1.2.1", "router": "^2.0.0", "send": "^1.1.0", "serve-static": "^2.1.0", - "statuses": "2.0.1", + "statuses": "^2.0.1", "type-is": "^2.0.0", - "vary": "~1.1.2" + "vary": "^1.1.2" }, "devDependencies": { "after": "0.8.2", From 55869f49a65f1e279d92488fa6319c9fd4d8eac2 Mon Sep 17 00:00:00 2001 From: Alexander Cerutti Date: Sat, 18 Jan 2025 21:37:48 +0100 Subject: [PATCH 818/889] feat: Added check to support Uint8Array in response sending (#6285) Unified usage of ArrayBuffer.isView to comprehend Buffer and removed isView function check Co-authored-by: Wes Todd Added Uint8Array test with encoding fix: added history.md entry --- History.md | 1 + lib/response.js | 2 +- test/res.send.js | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 25e29250f92..e08c52ee044 100644 --- a/History.md +++ b/History.md @@ -9,6 +9,7 @@ unreleased * Replace `methods` dependency with standard library * refactor: prefix built-in node module imports * Remove unused `depd` dependency +* Add support for `Uint8Array` in `res.send` 5.0.1 / 2024-10-08 ========== diff --git a/lib/response.js b/lib/response.js index f6f5740d2da..38f11e92379 100644 --- a/lib/response.js +++ b/lib/response.js @@ -130,7 +130,7 @@ res.send = function send(body) { case 'object': if (chunk === null) { chunk = ''; - } else if (Buffer.isBuffer(chunk)) { + } else if (ArrayBuffer.isView(chunk)) { if (!this.get('Content-Type')) { this.type('bin'); } diff --git a/test/res.send.js b/test/res.send.js index 860607c49b5..78a69a5c666 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -177,6 +177,19 @@ describe('res', function(){ .expect(200, 'hey', done); }) + it('should accept Uint8Array', function(done){ + var app = express(); + app.use(function(req, res){ + const encodedHey = new TextEncoder().encode("hey"); + res.set("Content-Type", "text/plain").send(encodedHey); + }) + + request(app) + .get("/") + .expect("Content-Type", "text/plain; charset=utf-8") + .expect(200, "hey", done); + }) + it('should not override ETag', function (done) { var app = express() From 85e48bb8c109d2200077bf8d50f3a163488d0fa5 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Mon, 10 Feb 2025 20:41:39 +0100 Subject: [PATCH 819/889] fix(deps): update debug to ^4.4.0 (#6313) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index e08c52ee044..6ff4da4025a 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,7 @@ unreleased * refactor: prefix built-in node module imports * Remove unused `depd` dependency * Add support for `Uint8Array` in `res.send` +* deps: debug@^4.4.0 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index 196831fc7b2..7c14248b9fe 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "content-type": "^1.0.4", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", - "debug": "^4.3.6", + "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", From 2d589b644a34c4e748fa650045e5827eaf65bf01 Mon Sep 17 00:00:00 2001 From: Dustin Popp Date: Wed, 12 Feb 2025 09:38:10 -0600 Subject: [PATCH 820/889] fix(docs): retroactively note 5.0.0-beta.1 api change in history file (#6333) Signed-off-by: Dustin Popp --- History.md | 1 + 1 file changed, 1 insertion(+) diff --git a/History.md b/History.md index 6ff4da4025a..cc201f32a06 100644 --- a/History.md +++ b/History.md @@ -90,6 +90,7 @@ changes from 5.0.0-alpha.8. - Change `dotfiles` option default to `'ignore'` - Remove `hidden` option; use `dotfiles` option instead - Use `mime-types` for file to content type mapping + - Remove `express.static.mime` export; use `mime-types` package instead - deps: send@1.0.0-beta.1 5.0.0-alpha.8 / 2020-03-25 From 99473c593a2de97ee82e5b0266ede4cdb682b68c Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 12 Feb 2025 09:44:53 -0600 Subject: [PATCH 821/889] feat(deps): body-parser@^2.1.0 (#6332) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index cc201f32a06..383f8883e20 100644 --- a/History.md +++ b/History.md @@ -11,6 +11,7 @@ unreleased * Remove unused `depd` dependency * Add support for `Uint8Array` in `res.send` * deps: debug@^4.4.0 +* deps: body-parser@^2.1.0 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index 7c14248b9fe..854e6907873 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ ], "dependencies": { "accepts": "^2.0.0", - "body-parser": "^2.0.1", + "body-parser": "^2.1.0", "content-disposition": "^1.0.0", "content-type": "^1.0.4", "cookie": "^0.7.1", From c2f576cbe9ed2f7988bf4e2f5ef6d7bea8a0ec9e Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Wed, 12 Feb 2025 10:09:50 -0600 Subject: [PATCH 822/889] feat(deps): router@^2.1.0 (#6331) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 383f8883e20..0b19c99df1c 100644 --- a/History.md +++ b/History.md @@ -12,6 +12,7 @@ unreleased * Add support for `Uint8Array` in `res.send` * deps: debug@^4.4.0 * deps: body-parser@^2.1.0 +* deps: router@^2.1.0 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index 854e6907873..9ba75117ee2 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "proxy-addr": "^2.0.7", "qs": "^6.13.0", "range-parser": "^1.2.1", - "router": "^2.0.0", + "router": "^2.1.0", "send": "^1.1.0", "serve-static": "^2.1.0", "statuses": "^2.0.1", From a42413d4e34a55c9ad972f4bbbbec95ec1490f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Wed, 12 Feb 2025 17:22:11 +0100 Subject: [PATCH 823/889] fix(docs): Update repo captains (#6234) * docs: update repo captains * docs: update repo captain nomination policies Ref: https://github.com/expressjs/express/pull/6234#issuecomment-2578555232 --- Contributing.md | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Contributing.md b/Contributing.md index fee08f74a7e..1fb88229951 100644 --- a/Contributing.md +++ b/Contributing.md @@ -132,23 +132,30 @@ Like TC members, Repo captains are a subset of committers. To become a captain for a project the candidate is expected to participate in that project for at least 6 months as a committer prior to the request. They should have helped with code contributions as well as triaging issues. They are also required to -have 2FA enabled on both their GitHub and npm accounts. Any TC member or existing -captain on the repo can nominate another committer to the captain role, submit a PR to -this doc, in the **Active Project Captains** section (maintaining the sort order) with -the project, their GitHub handle and npm username (if different). The PR will require -at least 2 approvals from TC members and 2 weeks hold time to allow for comment and/or -dissent. When the PR is merged, a TC member will add them to the proper GitHub/npm groups. +have 2FA enabled on both their GitHub and npm accounts. + +Any TC member or an existing captain on the **same** repo can nominate another committer +to the captain role. To do so, they should submit a PR to this document, updating the +**Active Project Captains** section (while maintaining the sort order) with the project +name, the nominee's GitHub handle, and their npm username (if different). +- Repos can have as many captains as make sense for the scope of work. +- A TC member or an existing repo captain **on the same project** can nominate a new captain. + Repo captains from other projects should not nominate captains for a different project. + +The PR will require at least 2 approvals from TC members and 2 weeks hold time to allow +for comment and/or dissent. When the PR is merged, a TC member will add them to the +proper GitHub/npm groups. ### Active Projects and Captains - [`expressjs/badgeboard`](https://github.com/expressjs/badgeboard): @wesleytodd -- [`expressjs/basic-auth-connect`](https://github.com/expressjs/basic-auth-connect): @UlisesGascon -- [`expressjs/body-parser`](https://github.com/expressjs/body-parser): @wesleytodd, @jonchurch +- [`expressjs/basic-auth-connect`](https://github.com/expressjs/basic-auth-connect): @ulisesGascon +- [`expressjs/body-parser`](https://github.com/expressjs/body-parser): @wesleytodd, @jonchurch, @ulisesGascon - [`expressjs/compression`](https://github.com/expressjs/compression): @ulisesGascon - [`expressjs/connect-multiparty`](https://github.com/expressjs/connect-multiparty): @ulisesGascon - [`expressjs/cookie-parser`](https://github.com/expressjs/cookie-parser): @wesleytodd, @UlisesGascon - [`expressjs/cookie-session`](https://github.com/expressjs/cookie-session): @ulisesGascon -- [`expressjs/cors`](https://github.com/expressjs/cors): @jonchurch +- [`expressjs/cors`](https://github.com/expressjs/cors): @jonchurch, @ulisesGascon - [`expressjs/discussions`](https://github.com/expressjs/discussions): @wesleytodd - [`expressjs/errorhandler`](https://github.com/expressjs/errorhandler): @ulisesGascon - [`expressjs/express-paginate`](https://github.com/expressjs/express-paginate): @ulisesGascon @@ -157,8 +164,8 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - [`expressjs/flash`](https://github.com/expressjs/flash): @ulisesGascon - [`expressjs/generator`](https://github.com/expressjs/generator): @wesleytodd - [`expressjs/method-override`](https://github.com/expressjs/method-override): @ulisesGascon -- [`expressjs/morgan`](https://github.com/expressjs/morgan): @jonchurch -- [`expressjs/multer`](https://github.com/expressjs/multer): @LinusU +- [`expressjs/morgan`](https://github.com/expressjs/morgan): @jonchurch, @ulisesGascon +- [`expressjs/multer`](https://github.com/expressjs/multer): @LinusU, @ulisesGascon - [`expressjs/response-time`](https://github.com/expressjs/response-time): @UlisesGascon - [`expressjs/serve-favicon`](https://github.com/expressjs/serve-favicon): @ulisesGascon - [`expressjs/serve-index`](https://github.com/expressjs/serve-index): @ulisesGascon @@ -176,16 +183,16 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - [`jshttp/etag`](https://github.com/jshttp/etag): @blakeembrey - [`jshttp/forwarded`](https://github.com/jshttp/forwarded): @blakeembrey - [`jshttp/fresh`](https://github.com/jshttp/fresh): @blakeembrey -- [`jshttp/http-assert`](https://github.com/jshttp/http-assert): @wesleytodd, @jonchurch -- [`jshttp/http-errors`](https://github.com/jshttp/http-errors): @wesleytodd, @jonchurch +- [`jshttp/http-assert`](https://github.com/jshttp/http-assert): @wesleytodd, @jonchurch, @ulisesGascon +- [`jshttp/http-errors`](https://github.com/jshttp/http-errors): @wesleytodd, @jonchurch, @ulisesGascon - [`jshttp/media-typer`](https://github.com/jshttp/media-typer): @blakeembrey - [`jshttp/methods`](https://github.com/jshttp/methods): @blakeembrey - [`jshttp/mime-db`](https://github.com/jshttp/mime-db): @blakeembrey, @UlisesGascon - [`jshttp/mime-types`](https://github.com/jshttp/mime-types): @blakeembrey, @UlisesGascon - [`jshttp/negotiator`](https://github.com/jshttp/negotiator): @blakeembrey -- [`jshttp/on-finished`](https://github.com/jshttp/on-finished): @wesleytodd +- [`jshttp/on-finished`](https://github.com/jshttp/on-finished): @wesleytodd, @ulisesGascon - [`jshttp/on-headers`](https://github.com/jshttp/on-headers): @blakeembrey -- [`jshttp/proxy-addr`](https://github.com/jshttp/proxy-addr): @wesleytodd +- [`jshttp/proxy-addr`](https://github.com/jshttp/proxy-addr): @wesleytodd, @ulisesGascon - [`jshttp/range-parser`](https://github.com/jshttp/range-parser): @blakeembrey - [`jshttp/statuses`](https://github.com/jshttp/statuses): @blakeembrey - [`jshttp/type-is`](https://github.com/jshttp/type-is): @blakeembrey @@ -193,14 +200,14 @@ dissent. When the PR is merged, a TC member will add them to the proper GitHub/ - [`pillarjs/cookies`](https://github.com/pillarjs/cookies): @blakeembrey - [`pillarjs/csrf`](https://github.com/pillarjs/csrf): @ulisesGascon - [`pillarjs/encodeurl`](https://github.com/pillarjs/encodeurl): @blakeembrey -- [`pillarjs/finalhandler`](https://github.com/pillarjs/finalhandler): @wesleytodd +- [`pillarjs/finalhandler`](https://github.com/pillarjs/finalhandler): @wesleytodd, @ulisesGascon - [`pillarjs/hbs`](https://github.com/pillarjs/hbs): @ulisesGascon - [`pillarjs/multiparty`](https://github.com/pillarjs/multiparty): @blakeembrey - [`pillarjs/parseurl`](https://github.com/pillarjs/parseurl): @blakeembrey - [`pillarjs/path-to-regexp`](https://github.com/pillarjs/path-to-regexp): @blakeembrey - [`pillarjs/request`](https://github.com/pillarjs/request): @wesleytodd - [`pillarjs/resolve-path`](https://github.com/pillarjs/resolve-path): @blakeembrey -- [`pillarjs/router`](https://github.com/pillarjs/router): @wesleytodd +- [`pillarjs/router`](https://github.com/pillarjs/router): @wesleytodd, @ulisesGascon - [`pillarjs/send`](https://github.com/pillarjs/send): @blakeembrey - [`pillarjs/understanding-csrf`](https://github.com/pillarjs/understanding-csrf): @ulisesGascon From 2a53336e5d90e2a8f8373e323c6df00f0ab08c25 Mon Sep 17 00:00:00 2001 From: Agung Jati Date: Wed, 12 Feb 2025 08:47:19 -0800 Subject: [PATCH 824/889] fix(deps): nyc@^17.1.0 (#6122) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0b19c99df1c..c73ac2d4596 100644 --- a/History.md +++ b/History.md @@ -13,6 +13,7 @@ unreleased * deps: debug@^4.4.0 * deps: body-parser@^2.1.0 * deps: router@^2.1.0 +* deps: nyc@^17.1.0 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index 9ba75117ee2..4176f948d56 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "method-override": "3.0.0", "mocha": "10.2.0", "morgan": "1.10.0", - "nyc": "15.1.0", + "nyc": "^17.1.0", "pbkdf2-password": "1.2.1", "supertest": "6.3.0", "vhost": "~3.0.2" From d2de128a32f1ce3d360bbe3fad56afa026fc8832 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 13 Feb 2025 10:44:50 -0600 Subject: [PATCH 825/889] fix (deps): update deps (#6337) fix(deps): mocha@^10.7.3 (closes #6121) fix(deps): marked@^15.0.3 (closes #6120) fix(deps): express-session@^1.18.1 (closes #6119) fix(deps): ejs@^3.1.10 (closes #6117) fix(deps): content-type@^1.0.5 (closes #6115) fix(deps): connect-redis@^8.0.1 (closes #6114) fix(deps): supertest@^6.3.4 (closes #6112) Co-authored-by: agungjati --- History.md | 7 +++++++ package.json | 14 +++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/History.md b/History.md index c73ac2d4596..5c7da2ad814 100644 --- a/History.md +++ b/History.md @@ -14,6 +14,13 @@ unreleased * deps: body-parser@^2.1.0 * deps: router@^2.1.0 * deps: nyc@^17.1.0 +* deps: mocha@^10.7.3 +* deps: marked@^15.0.3 +* deps: express-session@^1.18.1 +* deps: ejs@^3.1.10 +* deps: content-type@^1.0.5 +* deps: connect-redis@^8.0.1 +* deps: supertest@^6.3.4 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index 4176f948d56..85a98e0e9cb 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "accepts": "^2.0.0", "body-parser": "^2.1.0", "content-disposition": "^1.0.0", - "content-type": "^1.0.4", + "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", @@ -62,20 +62,20 @@ }, "devDependencies": { "after": "0.8.2", - "connect-redis": "8.0.1", + "connect-redis": "^8.0.1", "cookie-parser": "1.4.7", "cookie-session": "2.0.0", - "ejs": "3.1.10", + "ejs": "^3.1.10", "eslint": "8.47.0", - "express-session": "1.18.1", + "express-session": "^1.18.1", "hbs": "4.2.0", - "marked": "15.0.3", + "marked": "^15.0.3", "method-override": "3.0.0", - "mocha": "10.2.0", + "mocha": "^10.7.3", "morgan": "1.10.0", "nyc": "^17.1.0", "pbkdf2-password": "1.2.1", - "supertest": "6.3.0", + "supertest": "^6.3.0", "vhost": "~3.0.2" }, "engines": { From 327af123a1833239adf7eb47fee94542b692d451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Jos=C3=A9?= Date: Thu, 13 Feb 2025 14:39:31 -0500 Subject: [PATCH 826/889] feat: add support for ETag option in res.sendFile (#6073) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch introduces the ability to control the ETag generation through the `res.sendFile` function. Specifically, the ETag option is wired to the application's configuration, allowing it to be enabled or disabled based on the app's settings. Fixes: https://github.com/expressjs/express/issues/2294 Signed-off-by: Juan José Arboleda --- History.md | 1 + lib/response.js | 3 +++ test/res.sendFile.js | 13 +++++++++++++ 3 files changed, 17 insertions(+) diff --git a/History.md b/History.md index 5c7da2ad814..021315c5ab9 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,7 @@ unreleased * refactor: prefix built-in node module imports * Remove unused `depd` dependency * Add support for `Uint8Array` in `res.send` +* Add support for ETag option in res.sendFile * deps: debug@^4.4.0 * deps: body-parser@^2.1.0 * deps: router@^2.1.0 diff --git a/lib/response.js b/lib/response.js index 38f11e92379..b1dfcb23350 100644 --- a/lib/response.js +++ b/lib/response.js @@ -389,6 +389,9 @@ res.sendFile = function sendFile(path, options, callback) { // create file stream var pathname = encodeURI(path); + + // wire application etag option to send + opts.etag = this.app.enabled('etag'); var file = send(req, pathname, opts); // transfer diff --git a/test/res.sendFile.js b/test/res.sendFile.js index 505f8d114de..63ad5558b57 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -78,6 +78,19 @@ describe('res', function(){ }); }); + it('should disable the ETag function if requested', function (done) { + var app = createApp(path.resolve(fixtures, 'name.txt')).disable('etag'); + + request(app) + .get('/') + .expect(handleHeaders) + .expect(200, done); + + function handleHeaders (res) { + assert(res.headers.etag === undefined); + } + }); + it('should 404 for directory', function (done) { var app = createApp(path.resolve(fixtures, 'blog')); From 6ed3439584b6bc77b0f1156f8797700df063fa63 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Fri, 14 Feb 2025 16:51:27 +0100 Subject: [PATCH 827/889] fix(docs): Update multiple links to use `https` instead of `http` (#6338) --- .editorconfig | 2 +- Charter.md | 6 +++--- Collaborator-Guide.md | 2 +- Release-Process.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.editorconfig b/.editorconfig index cdb36c1b466..12cf1111232 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -# http://editorconfig.org +# https://editorconfig.org root = true [*] diff --git a/Charter.md b/Charter.md index a906e52909a..6227d6f6c85 100644 --- a/Charter.md +++ b/Charter.md @@ -20,11 +20,11 @@ alike. Express is made of many modules spread between three GitHub Orgs: -- [expressjs](http://github.com/expressjs/): Top level middleware and +- [expressjs](https://github.com/expressjs/): Top level middleware and libraries -- [pillarjs](http://github.com/pillarjs/): Components which make up +- [pillarjs](https://github.com/pillarjs/): Components which make up Express but can also be used for other web frameworks -- [jshttp](http://github.com/jshttp/): Low level HTTP libraries +- [jshttp](https://github.com/jshttp/): Low level HTTP libraries ### 1.2: Out-of-Scope diff --git a/Collaborator-Guide.md b/Collaborator-Guide.md index 3c73307d61b..ef8b6581448 100644 --- a/Collaborator-Guide.md +++ b/Collaborator-Guide.md @@ -7,7 +7,7 @@ Open issues for the expressjs.com website in https://github.com/expressjs/expres ## PRs and Code contributions * Tests must pass. -* Follow the [JavaScript Standard Style](http://standardjs.com/) and `npm run lint`. +* Follow the [JavaScript Standard Style](https://standardjs.com/) and `npm run lint`. * If you fix a bug, add a test. ## Branches diff --git a/Release-Process.md b/Release-Process.md index 8eee8aa089a..e332820f052 100644 --- a/Release-Process.md +++ b/Release-Process.md @@ -31,7 +31,7 @@ Before publishing, the following preconditions should be met: below) will exist documenting: - the proposed changes - the type of release: patch, minor or major - - the version number (according to semantic versioning - http://semver.org) + - the version number (according to semantic versioning - https://semver.org) - The proposed changes should be complete. There are two main release flows: patch and non-patch. From caa4f68ee8d32474676fa29cc2086dcc1d62208b Mon Sep 17 00:00:00 2001 From: Andrea Polverino <36574883+andvea@users.noreply.github.com> Date: Fri, 14 Feb 2025 17:20:53 +0100 Subject: [PATCH 828/889] feat: Extend res.links() to allow adding multiple links with the same rel (closes #2729) (#4885) --- History.md | 1 + lib/response.js | 19 +++++++++++++++---- test/res.links.js | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 021315c5ab9..98cfb14c259 100644 --- a/History.md +++ b/History.md @@ -11,6 +11,7 @@ unreleased * Remove unused `depd` dependency * Add support for `Uint8Array` in `res.send` * Add support for ETag option in res.sendFile +* Extend res.links() to allow adding multiple links with the same rel * deps: debug@^4.4.0 * deps: body-parser@^2.1.0 * deps: router@^2.1.0 diff --git a/lib/response.js b/lib/response.js index b1dfcb23350..9362d0ed5dd 100644 --- a/lib/response.js +++ b/lib/response.js @@ -80,7 +80,11 @@ res.status = function status(code) { * * res.links({ * next: 'http://api.example.com/users?page=2', - * last: 'http://api.example.com/users?page=5' + * last: 'http://api.example.com/users?page=5', + * pages: [ + * 'http://api.example.com/users?page=1', + * 'http://api.example.com/users?page=2' + * ] * }); * * @param {Object} links @@ -88,11 +92,18 @@ res.status = function status(code) { * @public */ -res.links = function(links){ +res.links = function(links) { var link = this.get('Link') || ''; if (link) link += ', '; - return this.set('Link', link + Object.keys(links).map(function(rel){ - return '<' + links[rel] + '>; rel="' + rel + '"'; + return this.set('Link', link + Object.keys(links).map(function(rel) { + // Allow multiple links if links[rel] is an array + if (Array.isArray(links[rel])) { + return links[rel].map(function (singleLink) { + return `<${singleLink}>; rel="${rel}"`; + }).join(', '); + } else { + return `<${links[rel]}>; rel="${rel}"`; + } }).join(', ')); }; diff --git a/test/res.links.js b/test/res.links.js index 240b7fcfda3..40665fd558a 100644 --- a/test/res.links.js +++ b/test/res.links.js @@ -43,5 +43,23 @@ describe('res', function(){ .expect('Link', '; rel="next", ; rel="last", ; rel="prev"') .expect(200, done); }) + + it('should set multiple links for single rel', function (done) { + var app = express(); + + app.use(function (req, res) { + res.links({ + next: 'http://api.example.com/users?page=2', + last: ['http://api.example.com/users?page=5', 'http://api.example.com/users?page=1'] + }); + + res.end(); + }); + + request(app) + .get('/') + .expect('Link', '; rel="next", ; rel="last", ; rel="last"') + .expect(200, done); + }) }) }) From 59703c23217cf7671e8f46bf77e2192fcab3c066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 27 Feb 2025 22:47:13 +0100 Subject: [PATCH 829/889] docs: update emeritus triagers (#6345) --- Readme.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Readme.md b/Readme.md index 8dc52ca2588..a06d16e7cd4 100644 --- a/Readme.md +++ b/Readme.md @@ -200,14 +200,9 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [bjohansebas](https://github.com/bjohansebas) - **Sebastian Beltran** * [carpasse](https://github.com/carpasse) - **Carlos Serrano** * [CBID2](https://github.com/CBID2) - **Christine Belzie** -* [enyoghasim](https://github.com/enyoghasim) - **David Enyoghasim** * [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him) * [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin** -* [0ss](https://github.com/0ss) - **Salah** -* [import-brain](https://github.com/import-brain) - **Eric Cheng** (he/him) * [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi** -* [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him) -* [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego** * [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him) * [Phillip9587](https://github.com/Phillip9587) - **Phillip Barta** * [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger** @@ -244,6 +239,12 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [sheplu](https://github.com/sheplu) - **Jean Burellier** * [tarunyadav1](https://github.com/tarunyadav1) - **Tarun yadav** * [tunniclm](https://github.com/tunniclm) - **Mike Tunnicliffe** + * [enyoghasim](https://github.com/enyoghasim) - **David Enyoghasim** + * [0ss](https://github.com/0ss) - **Salah** + * [import-brain](https://github.com/import-brain) - **Eric Cheng** (he/him) + * [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him) + * [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego** +
        From 90e522ac90e000e290f91dc4f0cf523f802c31ca Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 4 Mar 2025 09:09:18 -0500 Subject: [PATCH 830/889] fix(docs): update guidance for triager nominations (#6349) * docs: update guidance for triager nominations * Update Contributing.md Co-authored-by: Wes Todd * Update Contributing.md --------- Co-authored-by: Wes Todd --- Contributing.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index 1fb88229951..fe25ccbcff6 100644 --- a/Contributing.md +++ b/Contributing.md @@ -67,7 +67,8 @@ Currently, any existing [organization member](https://github.com/orgs/expressjs/ a new triager. If you are interested in becoming a triager, our best advice is to actively participate in the community by helping triaging issues and pull requests. As well we recommend to engage in other community activities like attending the TC meetings, and participating in the Slack -discussions. +discussions. If you feel ready and have been helping triage some issues, reach out to an active member of the organization to ask if they'd +be willing to support you. If they agree, they can create a pull request to formalize your nomination. In the case of an objection to the nomination, the triage team is responsible for working with the individuals involved and finding a resolution. You can also reach out to any of the [organization members](https://github.com/orgs/expressjs/people) if you have questions or need guidance. From 35e15362ab209809c40e6849f1bb783f9fbff860 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Wed, 5 Mar 2025 10:11:29 -0500 Subject: [PATCH 831/889] fix(docs): clarify guidelines for becoming a committer (#6364) * docs: clarify guidelines for becoming a committer * Update Contributing.md Co-authored-by: Chris de Almeida --------- Co-authored-by: Chris de Almeida --- Contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index fe25ccbcff6..a93da2349df 100644 --- a/Contributing.md +++ b/Contributing.md @@ -75,7 +75,7 @@ if you have questions or need guidance. ## Becoming a Committer -All contributors who land a non-trivial contribution should be on-boarded in a timely manner, +All contributors who have landed significant and valuable contributions should be onboarded in a timely manner, and added as a committer, and be given write access to the repository. Committers are expected to follow this policy and continue to send pull requests, go through From 9cbe2c2cbb0123457a0949233bacb7fe18b277ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 11 Mar 2025 22:49:08 +0100 Subject: [PATCH 832/889] docs: add @dpopp07 to the triage team (#6352) --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index a06d16e7cd4..685308c7553 100644 --- a/Readme.md +++ b/Readme.md @@ -200,6 +200,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [bjohansebas](https://github.com/bjohansebas) - **Sebastian Beltran** * [carpasse](https://github.com/carpasse) - **Carlos Serrano** * [CBID2](https://github.com/CBID2) - **Christine Belzie** +* [dpopp07](https://github.com/dpopp07) - **Dustin Popp** * [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him) * [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin** * [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi** From 1e359f57fc8cc33795c768d94560befbb6a61b2b Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Tue, 11 Mar 2025 16:49:58 -0500 Subject: [PATCH 833/889] fix(deps): qs@^6.14.0 (#6374) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 98cfb14c259..a00214f08a9 100644 --- a/History.md +++ b/History.md @@ -23,6 +23,7 @@ unreleased * deps: content-type@^1.0.5 * deps: connect-redis@^8.0.1 * deps: supertest@^6.3.4 +* deps: qs@^6.14.0 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index 85a98e0e9cb..5e5b02d3d02 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", - "qs": "^6.13.0", + "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.1.0", "send": "^1.1.0", From 0bb00e19068e9d95afcebb1821ab1eec5c1430aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Tue, 11 Mar 2025 22:50:59 +0100 Subject: [PATCH 834/889] ci: add dependabot (#5435) Co-authored-by: Shivam Sharma Co-authored-by: Sebastian Beltran --- .github/workflows/dependabot.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/dependabot.yml diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml new file mode 100644 index 00000000000..a6096a49b45 --- /dev/null +++ b/.github/workflows/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + + - package-ecosystem: npm + directory: / + schedule: + interval: monthly + time: "23:00" + timezone: Europe/London + open-pull-requests-limit: 10 + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] \ No newline at end of file From 4a2175dfc979606160e5f5a9ae05ff7a25d6c8f5 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sun, 16 Mar 2025 17:44:57 -0500 Subject: [PATCH 835/889] fix dependabot config (#6392) --- .github/{workflows => }/dependabot.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{workflows => }/dependabot.yml (100%) diff --git a/.github/workflows/dependabot.yml b/.github/dependabot.yml similarity index 100% rename from .github/workflows/dependabot.yml rename to .github/dependabot.yml From 1d63162dbfe5aa50549bbefb1dceae42ceda88f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:11:59 +0100 Subject: [PATCH 836/889] build(deps): bump github/codeql-action from 3.24.7 to 3.28.11 (#6398) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.7 to 3.28.11. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3.24.7...6bb031afdd8eb862ea3fc1848194185e076637e5) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index db4e01aff56..665fdc45c5a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -38,7 +38,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 + uses: github/codeql-action/init@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: languages: javascript # If you wish to specify custom queries, you can do so here or in a config file. @@ -61,6 +61,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 + uses: github/codeql-action/analyze@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: category: "/language:javascript" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index e9cdbdf1542..93e1f49961b 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 + uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: sarif_file: results.sarif \ No newline at end of file From 29d09803c11641d910107793947cefe4c0133358 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:12:20 +0100 Subject: [PATCH 837/889] build(deps): bump ossf/scorecard-action from 2.4.0 to 2.4.1 (#6397) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.0 to 2.4.1. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/62b2cac7ed8198b15735ed49ab1e5cf35480ba46...f49aabe0b5af0936a0987cfb85d86b75731b0186) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 93e1f49961b..62935a2d00f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 with: results_file: results.sarif results_format: sarif From 9e97144222cb4c29df0a96b689781e87fc3e781c Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Tue, 18 Mar 2025 19:12:45 -0500 Subject: [PATCH 838/889] feat(deps): finalhandler@2.1.0 (#6373) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(deps): finalhandler@2.1.0 * Update History.md Co-authored-by: Phillip Barta --------- Co-authored-by: Phillip Barta Co-authored-by: Ulises Gascón --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index a00214f08a9..03a5def16b2 100644 --- a/History.md +++ b/History.md @@ -23,6 +23,7 @@ unreleased * deps: content-type@^1.0.5 * deps: connect-redis@^8.0.1 * deps: supertest@^6.3.4 +* deps: finalhandler@^2.1.0 * deps: qs@^6.14.0 5.0.1 / 2024-10-08 diff --git a/package.json b/package.json index 5e5b02d3d02..0fdfd62bb1f 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", - "finalhandler": "^2.0.0", + "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", From 1f311c59d4b9cb94562ae0dd9917351e556f1602 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Mar 2025 20:08:24 -0500 Subject: [PATCH 839/889] build(deps-dev): bump cookie-session from 2.0.0 to 2.1.0 (#6399) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0fdfd62bb1f..8197db4f8b1 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "after": "0.8.2", "connect-redis": "^8.0.1", "cookie-parser": "1.4.7", - "cookie-session": "2.0.0", + "cookie-session": "2.1.0", "ejs": "^3.1.10", "eslint": "8.47.0", "express-session": "^1.18.1", From 6b51e8ef979d0aa6dc42ee0d61c8eb4c3e3196df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 27 Mar 2025 02:31:57 +0100 Subject: [PATCH 840/889] deps: body-parser@^2.2.0 (#6419) --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 03a5def16b2..60c6cd21eb8 100644 --- a/History.md +++ b/History.md @@ -13,7 +13,7 @@ unreleased * Add support for ETag option in res.sendFile * Extend res.links() to allow adding multiple links with the same rel * deps: debug@^4.4.0 -* deps: body-parser@^2.1.0 +* deps: body-parser@^2.2.0 * deps: router@^2.1.0 * deps: nyc@^17.1.0 * deps: mocha@^10.7.3 diff --git a/package.json b/package.json index 8197db4f8b1..a0b022e6b24 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ ], "dependencies": { "accepts": "^2.0.0", - "body-parser": "^2.1.0", + "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", From f1a2dc884de77fe9e84cdc8807407bd57a2e1008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 27 Mar 2025 02:32:28 +0100 Subject: [PATCH 841/889] deps: type-is@^2.0.1 (#6420) --- History.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 60c6cd21eb8..073a6489890 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ unreleased ======================== +* deps: type-is@2.0.1 * Remove `utils-merge` dependency - use spread syntax instead * Remove `Object.setPrototypeOf` polyfill * cleanup: remove AsyncLocalStorage check from tests diff --git a/package.json b/package.json index a0b022e6b24..6ee7dcd2a76 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "send": "^1.1.0", "serve-static": "^2.1.0", "statuses": "^2.0.1", - "type-is": "^2.0.0", + "type-is": "^2.0.1", "vary": "^1.1.2" }, "devDependencies": { From eb6d12587a2fdb907bd91cbedcd3b92f434fadd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 27 Mar 2025 02:47:40 +0100 Subject: [PATCH 842/889] deps: router@^2.2.0 (#6417) --- History.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 073a6489890..1dc50ea5c67 100644 --- a/History.md +++ b/History.md @@ -15,7 +15,7 @@ unreleased * Extend res.links() to allow adding multiple links with the same rel * deps: debug@^4.4.0 * deps: body-parser@^2.2.0 -* deps: router@^2.1.0 +* deps: router@^2.2.0 * deps: nyc@^17.1.0 * deps: mocha@^10.7.3 * deps: marked@^15.0.3 diff --git a/package.json b/package.json index 6ee7dcd2a76..56ed1b7d9d0 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", - "router": "^2.1.0", + "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.1.0", "statuses": "^2.0.1", From 7b44e1d8501d7b8a15de5bbee7d10a67d86f2630 Mon Sep 17 00:00:00 2001 From: Phillip9587 Date: Wed, 26 Mar 2025 15:43:11 +0100 Subject: [PATCH 843/889] ci: use full SHAs for github action versions Ref: https://github.com/expressjs/security-wg/issues/2 --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/codeql.yml | 2 +- .github/workflows/legacy.yml | 12 ++++++------ .github/workflows/scorecard.yml | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e68bdfd724b..0421d562429 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,9 +28,9 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 with: node-version: 'lts/*' @@ -52,12 +52,12 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 with: node-version: ${{ matrix.node-version }} @@ -79,7 +79,7 @@ jobs: run: npm run test-ci - name: Upload code coverage - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }} path: ./coverage/lcov.info @@ -92,14 +92,14 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install lcov shell: bash run: sudo apt-get -y install lcov - name: Collect coverage reports - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: path: ./coverage pattern: coverage-node-* @@ -109,6 +109,6 @@ jobs: run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./lcov.info - name: Upload coverage report - uses: coverallsapp/github-action@v2 + uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6 with: file: ./lcov.info diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 665fdc45c5a..d3e37aa4d6a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 6139f2fd9b7..81ffb94d748 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -36,12 +36,12 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 with: node-version: ${{ matrix.node-version }} @@ -63,7 +63,7 @@ jobs: run: npm run test-ci - name: Upload code coverage - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }} path: ./coverage/lcov.info @@ -76,14 +76,14 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install lcov shell: bash run: sudo apt-get -y install lcov - name: Collect coverage reports - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: path: ./coverage pattern: coverage-node-* @@ -93,6 +93,6 @@ jobs: run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./lcov.info - name: Upload coverage report - uses: coverallsapp/github-action@v2 + uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6 with: file: ./lcov.info diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 62935a2d00f..20c76dae0db 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -59,7 +59,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: SARIF file path: results.sarif @@ -69,4 +69,4 @@ jobs: - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 with: - sarif_file: results.sarif \ No newline at end of file + sarif_file: results.sarif From cb4c56e9a7ebc208730886e010b75475bf816fd9 Mon Sep 17 00:00:00 2001 From: Mert Can Altin Date: Fri, 28 Mar 2025 02:43:18 +0300 Subject: [PATCH 844/889] fix(docs): remove @mertcanaltin from Triagers (#6408) * doc: remove @mertcanaltin from Triagers * move emeritus --------- Co-authored-by: Mert Can Altin Co-authored-by: Wes Todd --- Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 685308c7553..7443b818591 100644 --- a/Readme.md +++ b/Readme.md @@ -202,7 +202,6 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [CBID2](https://github.com/CBID2) - **Christine Belzie** * [dpopp07](https://github.com/dpopp07) - **Dustin Popp** * [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him) -* [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin** * [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi** * [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him) * [Phillip9587](https://github.com/Phillip9587) - **Phillip Barta** @@ -245,7 +244,8 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [import-brain](https://github.com/import-brain) - **Eric Cheng** (he/him) * [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him) * [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego** - + * [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin** +
        From 4c4f3ea1059319d217dbb8177dfec902d2917424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Fri, 28 Mar 2025 01:46:06 +0100 Subject: [PATCH 845/889] fix(deps): serve-static@^2.2.0 (#6418) * Update package.json * Update History.md --------- Co-authored-by: Wes Todd --- History.md | 3 ++- package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 1dc50ea5c67..fcba2340b62 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,6 @@ unreleased ======================== -* deps: type-is@2.0.1 * Remove `utils-merge` dependency - use spread syntax instead * Remove `Object.setPrototypeOf` polyfill * cleanup: remove AsyncLocalStorage check from tests @@ -26,6 +25,8 @@ unreleased * deps: supertest@^6.3.4 * deps: finalhandler@^2.1.0 * deps: qs@^6.14.0 +* deps: server-static@2.2.0 +* deps: type-is@2.0.1 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index 56ed1b7d9d0..d4a605bed7c 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", - "serve-static": "^2.1.0", + "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" From cd7d4397c398a3f3ecadeaf9ef6ac1377bd414c4 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 27 Mar 2025 20:13:27 -0500 Subject: [PATCH 846/889] 5.1.0 --- History.md | 43 ++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/History.md b/History.md index fcba2340b62..5b6cba51ed8 100644 --- a/History.md +++ b/History.md @@ -1,32 +1,25 @@ -unreleased +5.1.0 / 2025-03-31 ======================== -* Remove `utils-merge` dependency - use spread syntax instead -* Remove `Object.setPrototypeOf` polyfill -* cleanup: remove AsyncLocalStorage check from tests -* cleanup: remove unnecessary require for global Buffer +* Add support for `Uint8Array` in `res.send()` +* Add support for ETag option in `res.sendFile()` +* Add support for multiple links with the same rel in `res.links()` +* Add funding field to package.json * perf: use loop for acceptParams -* Replace `methods` dependency with standard library * refactor: prefix built-in node module imports -* Remove unused `depd` dependency -* Add support for `Uint8Array` in `res.send` -* Add support for ETag option in res.sendFile -* Extend res.links() to allow adding multiple links with the same rel -* deps: debug@^4.4.0 -* deps: body-parser@^2.2.0 -* deps: router@^2.2.0 -* deps: nyc@^17.1.0 -* deps: mocha@^10.7.3 -* deps: marked@^15.0.3 -* deps: express-session@^1.18.1 -* deps: ejs@^3.1.10 -* deps: content-type@^1.0.5 -* deps: connect-redis@^8.0.1 -* deps: supertest@^6.3.4 -* deps: finalhandler@^2.1.0 -* deps: qs@^6.14.0 -* deps: server-static@2.2.0 -* deps: type-is@2.0.1 +* deps: remove `setprototypeof` +* deps: remove `safe-buffer` +* deps: remove `utils-merge` +* deps: remove `methods` +* deps: remove `depd` +* deps: `debug@^4.4.0` +* deps: `body-parser@^2.2.0` +* deps: `router@^2.2.0` +* deps: `content-type@^1.0.5` +* deps: `finalhandler@^2.1.0` +* deps: `qs@^6.14.0` +* deps: `server-static@2.2.0` +* deps: `type-is@2.0.1` 5.0.1 / 2024-10-08 ========== diff --git a/package.json b/package.json index d4a605bed7c..bdcd25e60fa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.1", + "version": "5.1.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From fa40ecfe7619acdfdeecf19d445ce5e9892d77ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 21:53:14 -0500 Subject: [PATCH 847/889] build(deps): bump github/codeql-action from 3.28.11 to 3.28.13 (#6429) --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d3e37aa4d6a..57bed1fac96 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -38,7 +38,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 with: languages: javascript # If you wish to specify custom queries, you can do so here or in a config file. @@ -61,6 +61,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 with: category: "/language:javascript" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 20c76dae0db..019e1a88cc8 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@6bb031afdd8eb862ea3fc1848194185e076637e5 # v3.28.11 + uses: github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 with: sarif_file: results.sarif From 3dc96995df98cd76d8d31f3b6825401f25899be0 Mon Sep 17 00:00:00 2001 From: Ayoub Mabrouk <77799760+Ayoub-Mabrouk@users.noreply.github.com> Date: Thu, 10 Apr 2025 18:49:23 -0700 Subject: [PATCH 848/889] Refactor: simplify `acceptsLanguages` implementation using spread operator (#6137) Refactored `req.acceptsLanguages` to use the spread operator for passing arguments directly to `accept.languages`, eliminating the need for `.apply`. This approach improves readability and streamlines the function call. --- lib/request.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/request.js b/lib/request.js index d8e52630788..63e0c1cd607 100644 --- a/lib/request.js +++ b/lib/request.js @@ -169,9 +169,8 @@ req.acceptsCharsets = function(){ * @public */ -req.acceptsLanguages = function(){ - var accept = accepts(this); - return accept.languages.apply(accept, arguments); +req.acceptsLanguages = function(...languages) { + return accepts(this).languages(...languages); }; /** From 5da5a11a498a3034623960861e542a3b39b00c94 Mon Sep 17 00:00:00 2001 From: Ashish Sharma <42138955+ashish3011@users.noreply.github.com> Date: Fri, 11 Apr 2025 07:27:43 +0530 Subject: [PATCH 849/889] increased code coverage of utils.js file (#6386) Co-authored-by: Sebastian Beltran --- test/utils.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/utils.js b/test/utils.js index d1142266ac4..b11b26680bd 100644 --- a/test/utils.js +++ b/test/utils.js @@ -25,6 +25,18 @@ describe('utils.etag(body, encoding)', function(){ }) }) +describe('utils.normalizeType acceptParams method', () => { + it('should handle a type with a malformed parameter and break the loop in acceptParams', () => { + const result = utils.normalizeType('text/plain;invalid'); + assert.deepEqual(result,{ + value: 'text/plain', + quality: 1, + params: {} // No parameters are added since "invalid" has no "=" + }); + }); +}); + + describe('utils.setCharset(type, charset)', function () { it('should do anything without type', function () { assert.strictEqual(utils.setCharset(), undefined); From f9954dd317a1b534e62a5ae3aa7f52f3582b8881 Mon Sep 17 00:00:00 2001 From: dufucun Date: Thu, 17 Apr 2025 00:18:38 +0800 Subject: [PATCH 850/889] fix(test): remove duplicate word (#6456) Signed-off-by: dufucun --- test/app.router.js | 2 +- test/res.format.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/app.router.js b/test/app.router.js index 017f4f4ef45..6e7be684e55 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -1156,7 +1156,7 @@ describe('app.router', function () { assert.strictEqual(app.get('/', function () { }), app) }) - it('should should not use disposed router/middleware', function (done) { + it('should not use disposed router/middleware', function (done) { // more context: https://github.com/expressjs/express/issues/5743#issuecomment-2277148412 var app = express(); diff --git a/test/res.format.js b/test/res.format.js index be427309577..0d770d57651 100644 --- a/test/res.format.js +++ b/test/res.format.js @@ -237,7 +237,7 @@ function test(app) { }) describe('when no match is made', function(){ - it('should should respond with 406 not acceptable', function(done){ + it('should respond with 406 not acceptable', function(done){ request(app) .get('/') .set('Accept', 'foo/bar') From a1161b4686a081b0e923419feab077e5b1c08f9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 23:01:58 +0200 Subject: [PATCH 851/889] build(deps): bump github/codeql-action from 3.28.13 to 3.28.16 (#6498) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.13 to 3.28.16. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/1b549b9259bda1cb5ddde3b41741a82a2d15a841...28deaeda66b76a05916b6923827895f2b14ab387) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.28.16 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 57bed1fac96..9ff3f6ebd12 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -38,7 +38,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 + uses: github/codeql-action/init@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 with: languages: javascript # If you wish to specify custom queries, you can do so here or in a config file. @@ -61,6 +61,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 + uses: github/codeql-action/analyze@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 with: category: "/language:javascript" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 019e1a88cc8..6561d86d42b 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3.28.13 + uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 with: sarif_file: results.sarif From 73555815b95a32bc9a48f6052711f95132da6248 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 23:02:09 +0200 Subject: [PATCH 852/889] build(deps): bump actions/setup-node from 4.3.0 to 4.4.0 (#6497) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.3.0 to 4.4.0. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/cdca7365b2dadb8aad0a33bc7601856ffabcc48e...49933ea5288caeca8642d1e84afbd3f7d6820020) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 4.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/legacy.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0421d562429..83df62b4098 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Node.js - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 'lts/*' @@ -57,7 +57,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 81ffb94d748..cd788a00dd3 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -41,7 +41,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ matrix.node-version }} From 1ca803dd5545e97bcacd9821df668eca1b0d3f83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 23:02:23 +0200 Subject: [PATCH 853/889] build(deps): bump actions/download-artifact from 4.2.1 to 4.3.0 (#6496) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.2.1 to 4.3.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/95815c38cf2ff2164869cbab79da8d1f422bc89e...d3f86a106a0bac45b974a628896c90dbdf5c8093) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/legacy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83df62b4098..ab7dfd0b571 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,7 +99,7 @@ jobs: run: sudo apt-get -y install lcov - name: Collect coverage reports - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: path: ./coverage pattern: coverage-node-* diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index cd788a00dd3..d64895c707b 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -83,7 +83,7 @@ jobs: run: sudo apt-get -y install lcov - name: Collect coverage reports - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: path: ./coverage pattern: coverage-node-* From ee1ef41bd3c28fde436c86c31e6959949a3e0f6a Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Thu, 8 May 2025 04:08:25 +0200 Subject: [PATCH 854/889] ci: add node.js 24 to test matrix (#6504) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab7dfd0b571..7022c9da6ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - node-version: [18, 19, 20, 21, 22, 23] + node-version: [18, 19, 20, 21, 22, 23, 24] # Node.js release schedule: https://nodejs.org/en/about/releases/ name: Node.js ${{ matrix.node-version }} - ${{matrix.os}} From 9784321e89b7d32aaff481aa24a9e8cccef4b101 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Fri, 9 May 2025 15:29:27 +0200 Subject: [PATCH 855/889] ci: update codeql config (#6488) --- .github/workflows/codeql.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9ff3f6ebd12..cfa5ec4b741 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -31,6 +31,10 @@ jobs: actions: read contents: read security-events: write + strategy: + fail-fast: false + matrix: + language: [javascript, actions] steps: - name: Checkout repository @@ -40,7 +44,10 @@ jobs: - name: Initialize CodeQL uses: github/codeql-action/init@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 with: - languages: javascript + languages: ${{ matrix.language }} + config: | + paths-ignore: + - test # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. @@ -62,5 +69,3 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 - with: - category: "/language:javascript" From 9f4dbe3a1332cd883069ba9b73a9eed99234cfc7 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Thu, 15 May 2025 12:40:26 -0400 Subject: [PATCH 856/889] chore: wider range for query test skip (#6512) --- test/support/utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/support/utils.js b/test/support/utils.js index 25022528ef6..a43ca0bb435 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -76,10 +76,10 @@ function getMajorVersion(versionString) { } function shouldSkipQuery(versionString) { - // Skipping HTTP QUERY tests on Node 21, it is reported in http.METHODS on 21.7.2 but not supported - // update this implementation to run on supported versions of 21 once they exist + // Skipping HTTP QUERY tests below Node 22, QUERY wasn't fully supported by Node until 22 + // we could update this implementation to run on supported versions of 21 once they exist // upstream tracking https://github.com/nodejs/node/issues/51562 // express tracking issue: https://github.com/expressjs/express/issues/5615 - return Number(getMajorVersion(versionString)) === 21 + return Number(getMajorVersion(versionString)) < 22 } From dfd1851245aa2a563c8612777ef10143be4a5cec Mon Sep 17 00:00:00 2001 From: Noritaka Kobayashi Date: Tue, 27 May 2025 17:36:50 +0900 Subject: [PATCH 857/889] test: fix typos in test descriptions (#6535) --- test/express.json.js | 10 +++++----- test/express.raw.js | 10 +++++----- test/express.text.js | 10 +++++----- test/express.urlencoded.js | 10 +++++----- test/res.download.js | 4 ++-- test/res.sendFile.js | 4 ++-- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/express.json.js b/test/express.json.js index 6b91734ed3b..6f7768afc23 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -539,7 +539,7 @@ describe('express.json()', function () { this.app = app }) - it('should presist store', function (done) { + it('should persist store', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/json') @@ -561,7 +561,7 @@ describe('express.json()', function () { .end(done) }) - it('should presist store when inflated', function (done) { + it('should persist store when inflated', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/json') @@ -572,7 +572,7 @@ describe('express.json()', function () { test.end(done) }) - it('should presist store when inflate error', function (done) { + it('should persist store when inflate error', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/json') @@ -582,7 +582,7 @@ describe('express.json()', function () { test.end(done) }) - it('should presist store when parse error', function (done) { + it('should persist store when parse error', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/json') @@ -592,7 +592,7 @@ describe('express.json()', function () { .end(done) }) - it('should presist store when limit exceeded', function (done) { + it('should persist store when limit exceeded', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/json') diff --git a/test/express.raw.js b/test/express.raw.js index 362fccb1e38..aface9093d5 100644 --- a/test/express.raw.js +++ b/test/express.raw.js @@ -368,7 +368,7 @@ describe('express.raw()', function () { this.app = app }) - it('should presist store', function (done) { + it('should persist store', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/octet-stream') @@ -379,7 +379,7 @@ describe('express.raw()', function () { .end(done) }) - it('should presist store when unmatched content-type', function (done) { + it('should persist store when unmatched content-type', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/fizzbuzz') @@ -389,7 +389,7 @@ describe('express.raw()', function () { .end(done) }) - it('should presist store when inflated', function (done) { + it('should persist store when inflated', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/octet-stream') @@ -400,7 +400,7 @@ describe('express.raw()', function () { test.end(done) }) - it('should presist store when inflate error', function (done) { + it('should persist store when inflate error', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/octet-stream') @@ -410,7 +410,7 @@ describe('express.raw()', function () { test.end(done) }) - it('should presist store when limit exceeded', function (done) { + it('should persist store when limit exceeded', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/octet-stream') diff --git a/test/express.text.js b/test/express.text.js index 1d22929e3b2..2ce6052a07b 100644 --- a/test/express.text.js +++ b/test/express.text.js @@ -397,7 +397,7 @@ describe('express.text()', function () { this.app = app }) - it('should presist store', function (done) { + it('should persist store', function (done) { request(this.app) .post('/') .set('Content-Type', 'text/plain') @@ -408,7 +408,7 @@ describe('express.text()', function () { .end(done) }) - it('should presist store when unmatched content-type', function (done) { + it('should persist store when unmatched content-type', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/fizzbuzz') @@ -418,7 +418,7 @@ describe('express.text()', function () { .end(done) }) - it('should presist store when inflated', function (done) { + it('should persist store when inflated', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'text/plain') @@ -429,7 +429,7 @@ describe('express.text()', function () { test.end(done) }) - it('should presist store when inflate error', function (done) { + it('should persist store when inflate error', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'text/plain') @@ -439,7 +439,7 @@ describe('express.text()', function () { test.end(done) }) - it('should presist store when limit exceeded', function (done) { + it('should persist store when limit exceeded', function (done) { request(this.app) .post('/') .set('Content-Type', 'text/plain') diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index b2df949f9f3..2f32f9fed1b 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -642,7 +642,7 @@ describe('express.urlencoded()', function () { this.app = app }) - it('should presist store', function (done) { + it('should persist store', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') @@ -653,7 +653,7 @@ describe('express.urlencoded()', function () { .end(done) }) - it('should presist store when unmatched content-type', function (done) { + it('should persist store when unmatched content-type', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/fizzbuzz') @@ -663,7 +663,7 @@ describe('express.urlencoded()', function () { .end(done) }) - it('should presist store when inflated', function (done) { + it('should persist store when inflated', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/x-www-form-urlencoded') @@ -674,7 +674,7 @@ describe('express.urlencoded()', function () { test.end(done) }) - it('should presist store when inflate error', function (done) { + it('should persist store when inflate error', function (done) { var test = request(this.app).post('/') test.set('Content-Encoding', 'gzip') test.set('Content-Type', 'application/x-www-form-urlencoded') @@ -684,7 +684,7 @@ describe('express.urlencoded()', function () { test.end(done) }) - it('should presist store when limit exceeded', function (done) { + it('should persist store when limit exceeded', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') diff --git a/test/res.download.js b/test/res.download.js index 1bd7663c549..db42662e2b2 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -88,7 +88,7 @@ describe('res', function(){ }) describe('async local storage', function () { - it('should presist store', function (done) { + it('should persist store', function (done) { var app = express() var cb = after(2, done) var store = { foo: 'bar' } @@ -116,7 +116,7 @@ describe('res', function(){ .expect(200, 'tobi', cb) }) - it('should presist store on error', function (done) { + it('should persist store on error', function (done) { var app = express() var store = { foo: 'bar' } diff --git a/test/res.sendFile.js b/test/res.sendFile.js index 63ad5558b57..9b0cd83cca3 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -277,7 +277,7 @@ describe('res', function(){ }) describe('async local storage', function () { - it('should presist store', function (done) { + it('should persist store', function (done) { var app = express() var cb = after(2, done) var store = { foo: 'bar' } @@ -304,7 +304,7 @@ describe('res', function(){ .expect(200, 'tobi', cb) }) - it('should presist store on error', function (done) { + it('should persist store on error', function (done) { var app = express() var store = { foo: 'bar' } From 99a0bd3354e4f52eacb08aeccce4a4058e7d59b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mert=20=C5=9Ei=C5=9Fmano=C4=9Flu?= Date: Thu, 29 May 2025 02:55:05 +0300 Subject: [PATCH 858/889] ci: disable credential persistence for checkout actions (#6522) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mert Şişmanoğlu --- .github/workflows/ci.yml | 4 ++++ .github/workflows/codeql.yml | 2 ++ .github/workflows/legacy.yml | 2 ++ 3 files changed, 8 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7022c9da6ba..39486b9c0fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: @@ -93,6 +95,8 @@ jobs: checks: write steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: Install lcov shell: bash diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index cfa5ec4b741..0ec794deaa7 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,6 +39,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index d64895c707b..dab9630366b 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -77,6 +77,8 @@ jobs: checks: write steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false - name: Install lcov shell: bash From fedd60e6426a56146e22655a465e10f81b8e7f03 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Thu, 29 May 2025 05:46:44 +0530 Subject: [PATCH 859/889] ci: allow manual triggering of workflow (#6515) --- .github/workflows/ci.yml | 1 + .github/workflows/codeql.yml | 1 + .github/workflows/legacy.yml | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39486b9c0fa..8c69b9c937e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,7 @@ on: pull_request: paths-ignore: - '*.md' + workflow_dispatch: permissions: contents: read diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0ec794deaa7..791a57f2c13 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -19,6 +19,7 @@ on: branches: ["master"] schedule: - cron: "0 0 * * 1" + workflow_dispatch: permissions: contents: read diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index dab9630366b..64074c95f66 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -13,7 +13,8 @@ on: pull_request: paths-ignore: - '*.md' - + workflow_dispatch: + permissions: contents: read From b8ab46594da8d2626c59ba36f76264ad980c533d Mon Sep 17 00:00:00 2001 From: kgarg1 <31365353+kgarg1@users.noreply.github.com> Date: Thu, 29 May 2025 05:56:16 +0530 Subject: [PATCH 860/889] test: add coverage for app.listen() variants (#6476) * test: add coverage for app.listen() variants - verify alternate signatures (port+host+backlog) - verify server.address() shape * fix linter issue --------- Co-authored-by: kuldeep --- test/app.listen.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/app.listen.js b/test/app.listen.js index 180162a0fae..3ef94ff184a 100644 --- a/test/app.listen.js +++ b/test/app.listen.js @@ -24,4 +24,32 @@ describe('app.listen()', function(){ }) }) }) + it('accepts port + hostname + backlog + callback', function (done) { + const app = express(); + const server = app.listen(0, '127.0.0.1', 5, function () { + const { address, port } = server.address(); + assert.strictEqual(address, '127.0.0.1'); + assert(Number.isInteger(port) && port > 0); + // backlog isn’t directly inspectable, but if no error was thrown + // we know it was accepted. + server.close(done); + }); + }); + it('accepts just a callback (no args)', function (done) { + const app = express(); + // same as app.listen(0, done) + const server = app.listen(); + server.close(done); + }); + it('server.address() gives a { address, port, family } object', function (done) { + const app = express(); + const server = app.listen(0, () => { + const addr = server.address(); + assert(addr && typeof addr === 'object'); + assert.strictEqual(typeof addr.address, 'string'); + assert(Number.isInteger(addr.port) && addr.port > 0); + assert(typeof addr.family === 'string'); + server.close(done); + }); + }); }) From 52872b84caf8426492108f59c1c229ac991396da Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 9 Jun 2025 15:34:53 -0500 Subject: [PATCH 861/889] =?UTF-8?q?fix(docs):=20move=20documentation=20and?= =?UTF-8?q?=20charters=20to=20the=20discussions=20and=20.github=20?= =?UTF-8?q?=E2=80=A6=20(#6427)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: move documentation and charters to the discussions and .github repository * Update Readme.md --- Charter.md | 92 -------------- Code-Of-Conduct.md | 139 --------------------- Collaborator-Guide.md | 51 -------- Contributing.md | 245 ------------------------------------- Readme-Guide.md | 125 ------------------- Readme.md | 42 ++++--- Release-Process.md | 202 ------------------------------ Security.md => SECURITY.md | 0 Triager-Guide.md | 72 ----------- 9 files changed, 24 insertions(+), 944 deletions(-) delete mode 100644 Charter.md delete mode 100644 Code-Of-Conduct.md delete mode 100644 Collaborator-Guide.md delete mode 100644 Contributing.md delete mode 100644 Readme-Guide.md delete mode 100644 Release-Process.md rename Security.md => SECURITY.md (100%) delete mode 100644 Triager-Guide.md diff --git a/Charter.md b/Charter.md deleted file mode 100644 index 6227d6f6c85..00000000000 --- a/Charter.md +++ /dev/null @@ -1,92 +0,0 @@ -# Express Charter - -## Section 0: Guiding Principles - -The Express project is part of the OpenJS Foundation which operates -transparently, openly, collaboratively, and ethically. -Project proposals, timelines, and status must not merely be open, but -also easily visible to outsiders. - -## Section 1: Scope - -Express is a HTTP web server framework with a simple and expressive API -which is highly aligned with Node.js core. We aim to be the best in -class for writing performant, spec compliant, and powerful web servers -in Node.js. As one of the oldest and most popular web frameworks in -the ecosystem, we have an important place for new users and experts -alike. - -### 1.1: In-scope - -Express is made of many modules spread between three GitHub Orgs: - -- [expressjs](https://github.com/expressjs/): Top level middleware and - libraries -- [pillarjs](https://github.com/pillarjs/): Components which make up - Express but can also be used for other web frameworks -- [jshttp](https://github.com/jshttp/): Low level HTTP libraries - -### 1.2: Out-of-Scope - -Section Intentionally Left Blank - -## Section 2: Relationship with OpenJS Foundation CPC. - -Technical leadership for the projects within the OpenJS Foundation is -delegated to the projects through their project charters by the OpenJS -Cross Project Council (CPC). In the case of the Express project, it is -delegated to the Express Technical Committee ("TC"). - -This Technical Committee is in charge of both the day-to-day operations -of the project, as well as its technical management. This charter can -be amended by the TC requiring at least two approvals and a minimum two -week comment period for other TC members or CPC members to object. Any -changes the CPC wishes to propose will be considered a priority but -will follow the same process. - -### 2.1 Other Formal Project Relationships - -Section Intentionally Left Blank - -## Section 3: Express Governing Body - -The Express project is managed by the Technical Committee ("TC"). -Members can be added to the TC at any time. Any committer can nominate -another committer to the TC and the TC uses its standard consensus -seeking process to evaluate whether or not to add this new member. -Members who do not participate consistently at the level of a majority -of the other members are expected to resign. - -## Section 4: Roles & Responsibilities - -The Express TC manages all aspects of both the technical and community -parts of the project. Members of the TC should attend the regular -meetings when possible, and be available for discussion of time -sensitive or important issues. - -### Section 4.1 Project Operations & Management - -Section Intentionally Left Blank - -### Section 4.2: Decision-making, Voting, and/or Elections - -The Express TC uses a "consensus seeking" process for issues that are -escalated to the TC. The group tries to find a resolution that has no -open objections among TC members. If a consensus cannot be reached -that has no objections then a majority wins vote is called. It is also -expected that the majority of decisions made by the TC are via a -consensus seeking process and that voting is only used as a last-resort. - -Resolution may involve returning the issue to committers with -suggestions on how to move forward towards a consensus. It is not -expected that a meeting of the TC will resolve all issues on its -agenda during that meeting and may prefer to continue the discussion -happening among the committers. - -### Section 4.3: Other Project Roles - -Section Intentionally Left Blank - -## Section 5: Definitions - -Section Intentionally Left Blank diff --git a/Code-Of-Conduct.md b/Code-Of-Conduct.md deleted file mode 100644 index ca4c6b31468..00000000000 --- a/Code-Of-Conduct.md +++ /dev/null @@ -1,139 +0,0 @@ -# Contributor Covenant Code of Conduct - -As a member of the Open JS Foundation, Express has adopted the -[Contributor Covenant 2.0][cc-20-doc]. - -If an issue arises and you cannot resolve it directly with the parties -involved, you can report it to the Express project TC through the following -email: express-coc@lists.openjsf.org - -In addition, the OpenJS Foundation maintains a Code of Conduct Panel (CoCP). -This is a foundation-wide team established to manage escalation when a reporter -believes that a report to a member project or the CPC has not been properly -handled. In order to escalate to the CoCP send an email to -coc-escalation@lists.openjsf.org. - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or advances - of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email address, - without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for -moderation decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail -address, posting via an official social media account, or acting as an -appointed representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -express-coc@lists.openjsf.org. All complaints will be reviewed and -investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or permanent -ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited -interaction with those enforcing the Code of Conduct, is allowed during this -period. Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the -project community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant, version 2.0][cc-20-doc]. - -Community Impact Guidelines were inspired by -[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). - -[cc-20-doc]: https://www.contributor-covenant.org/version/2/0/code_of_conduct/ - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. diff --git a/Collaborator-Guide.md b/Collaborator-Guide.md deleted file mode 100644 index ef8b6581448..00000000000 --- a/Collaborator-Guide.md +++ /dev/null @@ -1,51 +0,0 @@ -# Express Collaborator Guide - -## Website Issues - -Open issues for the expressjs.com website in https://github.com/expressjs/expressjs.com. - -## PRs and Code contributions - -* Tests must pass. -* Follow the [JavaScript Standard Style](https://standardjs.com/) and `npm run lint`. -* If you fix a bug, add a test. - -## Branches - -Use the `master` branch for bug fixes or minor work that is intended for the -current release stream. - -Use the correspondingly named branch, e.g. `5.0`, for anything intended for -a future release of Express. - -## Steps for contributing - -1. [Create an issue](https://github.com/expressjs/express/issues/new) for the - bug you want to fix or the feature that you want to add. -2. Create your own [fork](https://github.com/expressjs/express) on GitHub, then - checkout your fork. -3. Write your code in your local copy. It's good practice to create a branch for - each new issue you work on, although not compulsory. -4. To run the test suite, first install the dependencies by running `npm install`, - then run `npm test`. -5. Ensure your code is linted by running `npm run lint` -- fix any issue you - see listed. -6. If the tests pass, you can commit your changes to your fork and then create - a pull request from there. Make sure to reference your issue from the pull - request comments by including the issue number e.g. `#123`. - -## Issues which are questions - -We will typically close any vague issues or questions that are specific to some -app you are writing. Please double check the docs and other references before -being trigger happy with posting a question issue. - -Things that will help get your question issue looked at: - -* Full and runnable JS code. -* Clear description of the problem or unexpected behavior. -* Clear description of the expected result. -* Steps you have taken to debug it yourself. - -If you post a question and do not outline the above items or make it easy for -us to understand and reproduce your issue, it will be closed. diff --git a/Contributing.md b/Contributing.md deleted file mode 100644 index a93da2349df..00000000000 --- a/Contributing.md +++ /dev/null @@ -1,245 +0,0 @@ -# Express.js Community Contributing Guide 1.0 - -The goal of this document is to create a contribution process that: - -* Encourages new contributions. -* Encourages contributors to remain involved. -* Avoids unnecessary processes and bureaucracy whenever possible. -* Creates a transparent decision making process that makes it clear how -contributors can be involved in decision making. - -## Vocabulary - -* A **Contributor** is any individual creating or commenting on an issue or pull request. -* A **Committer** is a subset of contributors who have been given write access to the repository. -* A **Project Captain** is the lead maintainer of a repository. -* A **TC (Technical Committee)** is a group of committers representing the required technical -expertise to resolve rare disputes. -* A **Triager** is a subset of contributors who have been given triage access to the repository. - -## Logging Issues - -Log an issue for any question or problem you might have. When in doubt, log an issue, and -any additional policies about what to include will be provided in the responses. The only -exception is security disclosures which should be sent privately. - -Committers may direct you to another repository, ask for additional clarifications, and -add appropriate metadata before the issue is addressed. - -Please be courteous and respectful. Every participant is expected to follow the -project's Code of Conduct. - -## Contributions - -Any change to resources in this repository must be through pull requests. This applies to all changes -to documentation, code, binary files, etc. Even long term committers and TC members must use -pull requests. - -No pull request can be merged without being reviewed. - -For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that -contributors in other timezones have time to review. Consideration should also be given to -weekends and other holiday periods to ensure active committers all have reasonable time to -become involved in the discussion and review process if they wish. - -The default for each contribution is that it is accepted once no committer has an objection. -During a review, committers may also request that a specific contributor who is most versed in a -particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off" -process for contributions to land. Once all issues brought by committers are addressed it can -be landed by any committer. - -In the case of an objection being raised in a pull request by another committer, all involved -committers should seek to arrive at a consensus by way of addressing concerns being expressed -by discussion, compromise on the proposed change, or withdrawal of the proposed change. - -If a contribution is controversial and committers cannot agree about how to get it to land -or if it should land then it should be escalated to the TC. TC members should regularly -discuss pending contributions in order to find a resolution. It is expected that only a -small minority of issues be brought to the TC for resolution and that discussion and -compromise among committers be the default resolution mechanism. - -## Becoming a Triager - -Anyone can become a triager! Read more about the process of being a triager in -[the triage process document](Triager-Guide.md). - -Currently, any existing [organization member](https://github.com/orgs/expressjs/people) can nominate -a new triager. If you are interested in becoming a triager, our best advice is to actively participate -in the community by helping triaging issues and pull requests. As well we recommend -to engage in other community activities like attending the TC meetings, and participating in the Slack -discussions. If you feel ready and have been helping triage some issues, reach out to an active member of the organization to ask if they'd -be willing to support you. If they agree, they can create a pull request to formalize your nomination. In the case of an objection to the nomination, the triage team is responsible for working with the individuals involved and finding a resolution. - -You can also reach out to any of the [organization members](https://github.com/orgs/expressjs/people) -if you have questions or need guidance. - -## Becoming a Committer - -All contributors who have landed significant and valuable contributions should be onboarded in a timely manner, -and added as a committer, and be given write access to the repository. - -Committers are expected to follow this policy and continue to send pull requests, go through -proper review, and have other committers merge their pull requests. - -## TC Process - -The TC uses a "consensus seeking" process for issues that are escalated to the TC. -The group tries to find a resolution that has no open objections among TC members. -If a consensus cannot be reached that has no objections then a majority wins vote -is called. It is also expected that the majority of decisions made by the TC are via -a consensus seeking process and that voting is only used as a last-resort. - -Resolution may involve returning the issue to project captains with suggestions on -how to move forward towards a consensus. It is not expected that a meeting of the TC -will resolve all issues on its agenda during that meeting and may prefer to continue -the discussion happening among the project captains. - -Members can be added to the TC at any time. Any TC member can nominate another committer -to the TC and the TC uses its standard consensus seeking process to evaluate whether or -not to add this new member. The TC will consist of a minimum of 3 active members and a -maximum of 10. If the TC should drop below 5 members the active TC members should nominate -someone new. If a TC member is stepping down, they are encouraged (but not required) to -nominate someone to take their place. - -TC members will be added as admin's on the Github orgs, npm orgs, and other resources as -necessary to be effective in the role. - -To remain "active" a TC member should have participation within the last 12 months and miss -no more than six consecutive TC meetings. Our goal is to increase participation, not punish -people for any lack of participation, this guideline should be only be used as such -(replace an inactive member with a new active one, for example). Members who do not meet this -are expected to step down. If A TC member does not step down, an issue can be opened in the -discussions repo to move them to inactive status. TC members who step down or are removed due -to inactivity will be moved into inactive status. - -Inactive status members can become active members by self nomination if the TC is not already -larger than the maximum of 10. They will also be given preference if, while at max size, an -active member steps down. - -## Project Captains - -The Express TC can designate captains for individual projects/repos in the -organizations. These captains are responsible for being the primary -day-to-day maintainers of the repo on a technical and community front. -Repo captains are empowered with repo ownership and package publication rights. -When there are conflicts, especially on topics that effect the Express project -at large, captains are responsible to raise it up to the TC and drive -those conflicts to resolution. Captains are also responsible for making sure -community members follow the community guidelines, maintaining the repo -and the published package, as well as in providing user support. - -Like TC members, Repo captains are a subset of committers. - -To become a captain for a project the candidate is expected to participate in that -project for at least 6 months as a committer prior to the request. They should have -helped with code contributions as well as triaging issues. They are also required to -have 2FA enabled on both their GitHub and npm accounts. - -Any TC member or an existing captain on the **same** repo can nominate another committer -to the captain role. To do so, they should submit a PR to this document, updating the -**Active Project Captains** section (while maintaining the sort order) with the project -name, the nominee's GitHub handle, and their npm username (if different). -- Repos can have as many captains as make sense for the scope of work. -- A TC member or an existing repo captain **on the same project** can nominate a new captain. - Repo captains from other projects should not nominate captains for a different project. - -The PR will require at least 2 approvals from TC members and 2 weeks hold time to allow -for comment and/or dissent. When the PR is merged, a TC member will add them to the -proper GitHub/npm groups. - -### Active Projects and Captains - -- [`expressjs/badgeboard`](https://github.com/expressjs/badgeboard): @wesleytodd -- [`expressjs/basic-auth-connect`](https://github.com/expressjs/basic-auth-connect): @ulisesGascon -- [`expressjs/body-parser`](https://github.com/expressjs/body-parser): @wesleytodd, @jonchurch, @ulisesGascon -- [`expressjs/compression`](https://github.com/expressjs/compression): @ulisesGascon -- [`expressjs/connect-multiparty`](https://github.com/expressjs/connect-multiparty): @ulisesGascon -- [`expressjs/cookie-parser`](https://github.com/expressjs/cookie-parser): @wesleytodd, @UlisesGascon -- [`expressjs/cookie-session`](https://github.com/expressjs/cookie-session): @ulisesGascon -- [`expressjs/cors`](https://github.com/expressjs/cors): @jonchurch, @ulisesGascon -- [`expressjs/discussions`](https://github.com/expressjs/discussions): @wesleytodd -- [`expressjs/errorhandler`](https://github.com/expressjs/errorhandler): @ulisesGascon -- [`expressjs/express-paginate`](https://github.com/expressjs/express-paginate): @ulisesGascon -- [`expressjs/express`](https://github.com/expressjs/express): @wesleytodd, @ulisesGascon -- [`expressjs/expressjs.com`](https://github.com/expressjs/expressjs.com): @crandmck, @jonchurch, @bjohansebas -- [`expressjs/flash`](https://github.com/expressjs/flash): @ulisesGascon -- [`expressjs/generator`](https://github.com/expressjs/generator): @wesleytodd -- [`expressjs/method-override`](https://github.com/expressjs/method-override): @ulisesGascon -- [`expressjs/morgan`](https://github.com/expressjs/morgan): @jonchurch, @ulisesGascon -- [`expressjs/multer`](https://github.com/expressjs/multer): @LinusU, @ulisesGascon -- [`expressjs/response-time`](https://github.com/expressjs/response-time): @UlisesGascon -- [`expressjs/serve-favicon`](https://github.com/expressjs/serve-favicon): @ulisesGascon -- [`expressjs/serve-index`](https://github.com/expressjs/serve-index): @ulisesGascon -- [`expressjs/serve-static`](https://github.com/expressjs/serve-static): @ulisesGascon -- [`expressjs/session`](https://github.com/expressjs/session): @ulisesGascon -- [`expressjs/statusboard`](https://github.com/expressjs/statusboard): @wesleytodd -- [`expressjs/timeout`](https://github.com/expressjs/timeout): @ulisesGascon -- [`expressjs/vhost`](https://github.com/expressjs/vhost): @ulisesGascon -- [`jshttp/accepts`](https://github.com/jshttp/accepts): @blakeembrey -- [`jshttp/basic-auth`](https://github.com/jshttp/basic-auth): @blakeembrey -- [`jshttp/compressible`](https://github.com/jshttp/compressible): @blakeembrey -- [`jshttp/content-disposition`](https://github.com/jshttp/content-disposition): @blakeembrey -- [`jshttp/content-type`](https://github.com/jshttp/content-type): @blakeembrey -- [`jshttp/cookie`](https://github.com/jshttp/cookie): @blakeembrey -- [`jshttp/etag`](https://github.com/jshttp/etag): @blakeembrey -- [`jshttp/forwarded`](https://github.com/jshttp/forwarded): @blakeembrey -- [`jshttp/fresh`](https://github.com/jshttp/fresh): @blakeembrey -- [`jshttp/http-assert`](https://github.com/jshttp/http-assert): @wesleytodd, @jonchurch, @ulisesGascon -- [`jshttp/http-errors`](https://github.com/jshttp/http-errors): @wesleytodd, @jonchurch, @ulisesGascon -- [`jshttp/media-typer`](https://github.com/jshttp/media-typer): @blakeembrey -- [`jshttp/methods`](https://github.com/jshttp/methods): @blakeembrey -- [`jshttp/mime-db`](https://github.com/jshttp/mime-db): @blakeembrey, @UlisesGascon -- [`jshttp/mime-types`](https://github.com/jshttp/mime-types): @blakeembrey, @UlisesGascon -- [`jshttp/negotiator`](https://github.com/jshttp/negotiator): @blakeembrey -- [`jshttp/on-finished`](https://github.com/jshttp/on-finished): @wesleytodd, @ulisesGascon -- [`jshttp/on-headers`](https://github.com/jshttp/on-headers): @blakeembrey -- [`jshttp/proxy-addr`](https://github.com/jshttp/proxy-addr): @wesleytodd, @ulisesGascon -- [`jshttp/range-parser`](https://github.com/jshttp/range-parser): @blakeembrey -- [`jshttp/statuses`](https://github.com/jshttp/statuses): @blakeembrey -- [`jshttp/type-is`](https://github.com/jshttp/type-is): @blakeembrey -- [`jshttp/vary`](https://github.com/jshttp/vary): @blakeembrey -- [`pillarjs/cookies`](https://github.com/pillarjs/cookies): @blakeembrey -- [`pillarjs/csrf`](https://github.com/pillarjs/csrf): @ulisesGascon -- [`pillarjs/encodeurl`](https://github.com/pillarjs/encodeurl): @blakeembrey -- [`pillarjs/finalhandler`](https://github.com/pillarjs/finalhandler): @wesleytodd, @ulisesGascon -- [`pillarjs/hbs`](https://github.com/pillarjs/hbs): @ulisesGascon -- [`pillarjs/multiparty`](https://github.com/pillarjs/multiparty): @blakeembrey -- [`pillarjs/parseurl`](https://github.com/pillarjs/parseurl): @blakeembrey -- [`pillarjs/path-to-regexp`](https://github.com/pillarjs/path-to-regexp): @blakeembrey -- [`pillarjs/request`](https://github.com/pillarjs/request): @wesleytodd -- [`pillarjs/resolve-path`](https://github.com/pillarjs/resolve-path): @blakeembrey -- [`pillarjs/router`](https://github.com/pillarjs/router): @wesleytodd, @ulisesGascon -- [`pillarjs/send`](https://github.com/pillarjs/send): @blakeembrey -- [`pillarjs/understanding-csrf`](https://github.com/pillarjs/understanding-csrf): @ulisesGascon - -### Current Initiative Captains - -- Triage team [ref](https://github.com/expressjs/discussions/issues/227): @UlisesGascon - -## Developer's Certificate of Origin 1.1 - -```text -By making a contribution to this project, I certify that: - - (a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license - indicated in the file; or - - (b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source - license and I have the right under that license to submit that - work with modifications, whether created in whole or in part - by me, under the same open source license (unless I am - permitted to submit under a different license), as indicated - in the file; or - - (c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified - it. - - (d) I understand and agree that this project and the contribution - are public and that a record of the contribution (including all - personal information I submit with it, including my sign-off) is - maintained indefinitely and may be redistributed consistent with - this project or the open source license(s) involved. -``` diff --git a/Readme-Guide.md b/Readme-Guide.md deleted file mode 100644 index 34d4648b9c2..00000000000 --- a/Readme-Guide.md +++ /dev/null @@ -1,125 +0,0 @@ -# README guidelines - -Every module in the expressjs, pillarjs, and jshttp organizations should have -a README file named `README.md`. The purpose of the README is to: - -- Explain the purpose of the module and how to use it. -- Act as a landing page (both on GitHub and npmjs.com) for the module to help - people find it via search. Middleware module READMEs are also incorporated - into https://expressjs.com/en/resources/middleware.html. -- Encourage community contributions and participation. - -Use the [README template](https://github.com/expressjs/express/wiki/README-template) -to quickly create a new README file. - -## Top-level items - -**Badges** (optional): At the very top (with no subheading), include any -applicable badges, such as npm version/downloads, build status, test coverage, -and so on. Badges should resolve properly (not display a broken image). - -Possible badges include: -- npm version: `[![NPM Version][npm-image]][npm-url]` -- npm downloads: `[![NPM Downloads][downloads-image]][downloads-url]` -- Build status: `[![Build Status][travis-image]][travis-url]` -- Test coverage: `[![Test Coverage][coveralls-image]][coveralls-url]` -- Tips: `[![Gratipay][gratipay-image]][gratipay-url]` - -**Summary**: Following badges, provide a one- or two-sentence description of -what the module does. This should be the same as the npmjs.org blurb (which -comes from the description property of `package.json`). Since npm doesn't -handle markdown for the blurb, avoid using markdown in the summary sentence. - -**TOC** (Optional): For longer READMEs, provide a table of contents that has -a relative link to each section. A tool such as -[doctoc](https://www.npmjs.com/package/doctoc) makes it very easy to generate -a TOC. - -## Overview - -Optionally, include a section of one or two paragraphs with more high-level -information on what the module does, what problems it solves, why one would -use it and how. Don't just repeat what's in the summary. - -## Installation - -Required. This section is typically just: - -```sh -$ npm install module-name -``` - -But include any other steps or requirements. - -NOTE: Use the `sh` code block to make the shell command display properly on -the website. - -## Basic use - -- Provide a general description of how to use the module with code sample. - Include any important caveats or restrictions. -- Explain the most common use cases. -- Optional: a simple "hello world" type example (where applicable). This - example is in addition to the more comprehensive [example section](#examples) - later. - -## API - -Provide complete API documentation. - -Formatting conventions: Each function is listed in a 3rd-level heading (`###`), -like this: - -``` -### Function_name(arg, options [, optional_arg] ... ) -``` - -**Options objects** - -For arguments that are objects (for example, options object), describe the -properties in a table, as follows. This matches the formatting used in the -[Express API docs](https://expressjs.com/en/4x/api.html). - -|Property | Description | Type | Default| -|----------|-----------|------------|-------------| -|Name of the property in `monospace`. | Brief description | String, Number, Boolean, etc. | If applicable.| - -If all the properties are required (i.e. there are no defaults), then you -can omit the default column. - -Instead of very lengthy descriptions, link out to subsequent paragraphs for -more detailed explanation of specific cases (e.g. "When this property is set -to 'foobar', xyz happens; see <link to following section >.) - -If there are options properties that are themselves options, use additional -tables. See [`trust proxy` and `etag` properties](https://expressjs.com/en/4x/api.html#app.settings.table). - -## Examples - -Every README should have at least one example; ideally more. For code samples, -be sure to use the `js` code block, for proper display in the website, e.g.: - -```js -var csurf = require('csurf') -... -``` - -## Tests - -What tests are included. - -How to run them. - -The convention for running tests is `npm test`. All our projects should follow -this convention. - -## Contributors - -Names of module "owners" (lead developers) and other developers who have -contributed. - -## License - -Link to the license, with a short description of what it is, e.g. "MIT" or -whatever. Ideally, avoid putting the license text directly in the README; link -to it instead. diff --git a/Readme.md b/Readme.md index 7443b818591..d7e99de5c15 100644 --- a/Readme.md +++ b/Readme.md @@ -6,21 +6,28 @@ ## Table of contents -* [Installation](#Installation) -* [Features](#Features) -* [Docs & Community](#docs--community) -* [Quick Start](#Quick-Start) -* [Running Tests](#Running-Tests) -* [Philosophy](#Philosophy) -* [Examples](#Examples) -* [Contributing to Express](#Contributing) -* [TC (Technical Committee)](#tc-technical-committee) -* [Triagers](#triagers) -* [License](#license) +- [Table of contents](#table-of-contents) +- [Installation](#installation) +- [Features](#features) +- [Docs \& Community](#docs--community) +- [Quick Start](#quick-start) +- [Philosophy](#philosophy) +- [Examples](#examples) +- [Contributing](#contributing) + - [Security Issues](#security-issues) + - [Running Tests](#running-tests) +- [Current project team members](#current-project-team-members) + - [TC (Technical Committee)](#tc-technical-committee) + - [TC emeriti members](#tc-emeriti-members) + - [Triagers](#triagers) + - [Emeritus Triagers](#emeritus-triagers) +- [License](#license) [![NPM Version][npm-version-image]][npm-url] [![NPM Downloads][npm-downloads-image]][npm-downloads-url] +[![Linux Build][github-actions-ci-image]][github-actions-ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] [![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer] @@ -137,18 +144,15 @@ node examples/content-negotiation ## Contributing - [![Linux Build][github-actions-ci-image]][github-actions-ci-url] - [![Test Coverage][coveralls-image]][coveralls-url] - The Express.js project welcomes all constructive contributions. Contributions take many forms, from code for bug fixes and enhancements, to additions and fixes to documentation, additional tests, triaging incoming pull requests and issues, and more! -See the [Contributing Guide](Contributing.md) for more technical details on contributing. +See the [Contributing Guide](https://github.com/expressjs/.github/blob/HEAD/CONTRIBUTING.yml) for more technical details on contributing. ### Security Issues -If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). +If you discover a security vulnerability in Express, please see [Security Policies and Procedures](SECURITY.md). ### Running Tests @@ -164,7 +168,9 @@ Then run `npm test`: npm test ``` -## People +## Current project team members + +For information about the governance of the express.js project, see [GOVERNANCE.md](https://github.com/expressjs/discussions/blob/HEAD/docs/GOVERNANCE.md). The original author of Express is [TJ Holowaychuk](https://github.com/tj) @@ -245,7 +251,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him) * [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego** * [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin** - +
        diff --git a/Release-Process.md b/Release-Process.md deleted file mode 100644 index e332820f052..00000000000 --- a/Release-Process.md +++ /dev/null @@ -1,202 +0,0 @@ -# Express Release Process - -This document contains the technical aspects of the Express release process. The -intended audience is those who have been authorized by the Express Technical -Committee (TC) to create, promote and sign official release builds for Express, -as npm packages hosted on https://npmjs.com/package/express. - -## Who can make releases? - -Release authorization is given by the Express TC. Once authorized, an individual -must have the following access permissions: - -### 1. Github release access - -The individual making the release will need to be a member of the -expressjs/express team with Write permission level so they are able to tag the -release commit and push changes to the expressjs/express repository -(see Steps 4 and 5). - -### 2. npmjs.com release access - -The individual making the release will need to be made an owner on the -`express` package on npmjs.com so they are able to publish the release -(see Step 6). - -## How to publish a release - -Before publishing, the following preconditions should be met: - -- A release proposal issue or tracking pull request (see "Proposal branch" - below) will exist documenting: - - the proposed changes - - the type of release: patch, minor or major - - the version number (according to semantic versioning - https://semver.org) -- The proposed changes should be complete. - -There are two main release flows: patch and non-patch. - -The patch flow is for making **patch releases**. As per semantic versioning, -patch releases are for simple changes, eg: typo fixes, patch dependency updates, -and simple/low-risk bug fixes. Every other type of change is made via the -non-patch flow. - -### Branch terminology - -"Master branch" - -- There is a branch in git used for the current major version of Express, named - `master`. -- This branch contains the completed commits for the next patch release of the - current major version. -- Releases for the current major version are published from this branch. - -"Version branch" - -- For any given major version of Express (current, previous or next) there is - a branch in git for that release named `.x` (eg: `4.x`). -- This branch points to the commit of the latest tag for the given major version. - -"Release branch" - -- For any given major version of Express, there is a branch used for publishing - releases. -- For the current major version of Express, the release branch is the - "Master branch" named `master`. -- For all other major versions of Express, the release branch is the - "Version branch" named `.x`. - -"Proposal branch" - -- A branch in git representing a proposed new release of Express. This can be a - minor or major release, named `.0` for a major release, - `.` for a minor release. -- A tracking pull request should exist to document the proposed release, - targeted at the appropriate release branch. Prior to opening the tracking - pull request the content of the release may have be discussed in an issue. -- This branch contains the commits accepted so far that implement the proposal - in the tracking pull request. - -### Pre-release Versions - -Alpha and Beta releases are made from a proposal branch. The version number should be -incremented to the next minor version with a `-beta` or `-alpha` suffix. -For example, if the next beta release is `5.0.1`, the beta release would be `5.0.1-beta.0`. -The pre-releases are unstable and not suitable for production use. - -### Patch flow - -In the patch flow, simple changes are committed to the release branch which -acts as an ever-present branch for the next patch release of the associated -major version of Express. - -The release branch is usually kept in a state where it is ready to release. -Releases are made when sufficient time or change has been made to warrant it. -This is usually proposed and decided using a github issue. - -### Non-patch flow - -In the non-patch flow, changes are committed to a temporary proposal branch -created specifically for that release proposal. The branch is based on the -most recent release of the major version of Express that the release targets. - -Releases are made when all the changes on a proposal branch are complete and -approved. This is done by merging the proposal branch into the release branch -(using a fast-forward merge), tagging it with the new version number and -publishing the release package to npmjs.com. - -### Flow - -Below is a detailed description of the steps to publish a release. - -#### Step 1. Check the release is ready to publish - -Check any relevant information to ensure the release is ready, eg: any -milestone, label, issue or tracking pull request for the release. The release -is ready when all proposed code, tests and documentation updates are complete -(either merged, closed or re-targeted to another release). - -#### Step 2. (Non-patch flow only) Merge the proposal branch into the release branch - -In the patch flow: skip this step. - -In the non-patch flow: -```sh -$ git checkout -$ git merge --ff-only -``` - - - see "Release branch" of "Branches" above. - - see "Proposal branch" of "Non-patch flow" above. - -> [!NOTE] -> You may need to rebase the proposal branch to allow a fast-forward -> merge. Using a fast-forward merge keeps the history clean as it does -> not introduce merge commits. - -### Step 3. Update the History.md and package.json to the new version number - -The changes so far for the release should already be documented under the -"unreleased" section at the top of the History.md file, as per the usual -development practice. Change "unreleased" to the new release version / date. -Example diff fragment: - -```diff --unreleased --========== -+4.13.3 / 2015-08-02 -+=================== -``` - -The version property in the package.json should already contain the version of -the previous release. Change it to the new release version. - -Commit these changes together under a single commit with the message set to -the new release version (eg: `4.13.3`): - -```sh -$ git checkout -<..edit files..> -$ git add History.md package.json -$ git commit -m '' -``` - -### Step 4. Identify and tag the release commit with the new release version - -Create a lightweight tag (rather than an annotated tag) named after the new -release version (eg: `4.13.3`). - -```sh -$ git tag -``` - -### Step 5. Push the release branch changes and tag to github - -The branch and tag should be pushed directly to the main repository -(https://github.com/expressjs/express). - -```sh -$ git push origin -$ git push origin -``` - -### Step 6. Publish to npmjs.com - -Ensure your local working copy is completely clean (no extra or changed files). -You can use `git status` for this purpose. - -```sh -$ npm login -$ npm publish -``` - -> [!NOTE] -> The version number to publish will be picked up automatically from -> package.json. - -### Step 7. Update documentation website - -The documentation website https://expressjs.com/ documents the current release version in various places. To update these, follow these steps: - -1. Manually run the [`Update External Docs` workflow](https://github.com/expressjs/expressjs.com/actions/workflows/update-external-docs.yml) in expressjs.com repository. -2. Add a new section to the [changelog](https://github.com/expressjs/expressjs.com/blob/gh-pages/en/changelog/index.md) in the expressjs.com website. diff --git a/Security.md b/SECURITY.md similarity index 100% rename from Security.md rename to SECURITY.md diff --git a/Triager-Guide.md b/Triager-Guide.md deleted file mode 100644 index 65aff265f01..00000000000 --- a/Triager-Guide.md +++ /dev/null @@ -1,72 +0,0 @@ -# Express Triager Guide - -## Issue Triage Process - -When a new issue or pull request is opened the issue will be labeled with `needs triage`. -If a triage team member is available they can help make sure all the required information -is provided. Depending on the issue or PR there are several next labels they can add for further -classification: - -* `needs triage`: This can be kept if the triager is unsure which next steps to take -* `awaiting more info`: If more info has been requested from the author, apply this label. -* `bug`: Issues that present a reasonable conviction there is a reproducible bug. -* `enhancement`: Issues that are found to be a reasonable candidate feature additions. - -If the issue is a question or discussion, it should be moved to GitHub Discussions. - -### Moving Discussions and Questions to GitHub Discussions - -For issues labeled with `question` or `discuss`, it is recommended to move them to GitHub Discussions instead: - -* **Questions**: User questions that do not appear to be bugs or enhancements should be moved to GitHub Discussions. -* **Discussions**: Topics for discussion should be moved to GitHub Discussions. If the discussion leads to a new feature or bug identification, it can be moved back to Issues. - -In all cases, issues may be closed by maintainers if they don't receive a timely response when -further information is sought, or when additional questions are asked. - -## Approaches and Best Practices for getting into triage contributions - -Review the organization's [StatusBoard](https://expressjs.github.io/statusboard/), -pay special attention to these columns: stars, watchers, open issues, and contributors. -This gives you a general idea about the criticality and health of the repository. -Pick a few projects based on that criteria, your interests, and skills (existing or aspiring). - -Review the project's contribution guideline if present. In a nutshell, -commit to the community's standards and values. Review the -documentation, for most of the projects it is just the README.md, and -make sure you understand the key APIs, semantics, configurations, and use cases. - -It might be helpful to write your own test apps to re-affirm your -understanding of the key functions. This may identify some gaps in -documentation, record those as they might be good PR's to open. -Skim through the issue backlog; identify low hanging issues and mostly new ones. -From those, attempt to recreate issues based on the OP description and -ask questions if required. No question is a bad question! - -## Removal of Triage Role - -There are a few cases where members can be removed as triagers: - -- Breaking the CoC or project contributor guidelines -- Abuse or misuse of the role as deemed by the TC -- Lack of participation for more than 6 months - -If any of these happen we will discuss as a part of the triage portion of the regular TC meetings. -If you have questions feel free to reach out to any of the TC members. - -## Other Helpful Hints: - -- Everyone is welcome to attend the [Express Technical Committee Meetings](https://github.com/expressjs/discussions#expressjs-tc-meetings), and as a triager, it might help to get a better idea of what's happening with the project. -- When exploring the module's functionality there are a few helpful steps: - - Turn on `DEBUG=*` (see https://www.npmjs.com/package/debug) to get detailed log information - - It is also a good idea to do live debugging to follow the control flow, try using `node --inspect` - - It is a good idea to make at least one pass of reading through the entire source -- When reviewing the list of open issues there are some common types and suggested actions: - - New/unattended issues or simple questions: A good place to start - - Hard bugs & ongoing discussions: always feel free to chime in and help - - Issues that imply gaps in the documentation: open PRs with changes or help the user to do so -- For recurring issues, it is helpful to create functional examples to demonstrate (publish as gists or a repo) -- Review and identify the maintainers. If necessary, at-mention one or more of them if you are unsure what to do -- Make sure all your interactions are professional, welcoming, and respectful to the parties involved. -- When an issue refers to security concerns, responsibility is delegated to the repository captain or the security group in any public communication. - - If an issue has been open for a long time, the person in charge should be contacted internally through the private Slack chat. \ No newline at end of file From ffc562c7d1b7947f04009a710e503e3bc69b4b31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:36:20 +0200 Subject: [PATCH 862/889] build(deps): bump github/codeql-action from 3.28.16 to 3.28.18 (#6549) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.16 to 3.28.18. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/28deaeda66b76a05916b6923827895f2b14ab387...ff0a06e83cb2de871e5a09832bc6a81e7276941f) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.28.18 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 791a57f2c13..f37a495f243 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 + uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 with: languages: ${{ matrix.language }} config: | @@ -71,4 +71,4 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 + uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 6561d86d42b..88b19089e7d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 + uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 with: sarif_file: results.sarif From a039e4917501f20fb8db7ac342afa1742786832e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:36:52 +0200 Subject: [PATCH 863/889] build(deps): bump ossf/scorecard-action from 2.4.1 to 2.4.2 (#6548) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.1 to 2.4.2. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/f49aabe0b5af0936a0987cfb85d86b75731b0186...05b42c624433fc40578a4040d5cf5e36ddca8cde) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 88b19089e7d..070fc0e49aa 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif From 98c85eb0dd64f23940f1ac5b43d74d0eac659248 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Sat, 28 Jun 2025 06:40:36 +0530 Subject: [PATCH 864/889] chore: enforce explicit Buffer import and add lint rule (#6525) Signed-off-by: Shivam Sharma --- .eslintrc.yml | 4 ++++ lib/response.js | 1 + lib/utils.js | 1 + test/express.json.js | 1 + test/express.raw.js | 1 + test/express.static.js | 2 ++ test/express.text.js | 2 +- test/express.urlencoded.js | 1 + test/res.attachment.js | 2 ++ test/res.download.js | 1 + test/res.send.js | 1 + test/res.sendFile.js | 1 + test/support/utils.js | 1 + test/utils.js | 1 + 14 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 70bc9a6e7e1..f9359bf2892 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -8,3 +8,7 @@ rules: indent: [error, 2, { MemberExpression: "off", SwitchCase: 1 }] no-trailing-spaces: error no-unused-vars: [error, { vars: all, args: none, ignoreRestSiblings: true }] + no-restricted-globals: + - error + - name: Buffer + message: Use `import { Buffer } from "node:buffer"` instead of the global Buffer. diff --git a/lib/response.js b/lib/response.js index 9362d0ed5dd..09fa0611b4f 100644 --- a/lib/response.js +++ b/lib/response.js @@ -31,6 +31,7 @@ var send = require('send'); var extname = path.extname; var resolve = path.resolve; var vary = require('vary'); +const { Buffer } = require('node:buffer'); /** * Response prototype. diff --git a/lib/utils.js b/lib/utils.js index d53c5a13374..a466ec89f06 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -19,6 +19,7 @@ var mime = require('mime-types') var proxyaddr = require('proxy-addr'); var qs = require('qs'); var querystring = require('querystring'); +const { Buffer } = require('node:buffer'); /** * A list of lowercased HTTP methods that are supported by Node.js. diff --git a/test/express.json.js b/test/express.json.js index 6f7768afc23..28746bfebda 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -2,6 +2,7 @@ var assert = require('node:assert') var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage +const { Buffer } = require('node:buffer'); var express = require('..') var request = require('supertest') diff --git a/test/express.raw.js b/test/express.raw.js index aface9093d5..5576e225283 100644 --- a/test/express.raw.js +++ b/test/express.raw.js @@ -5,6 +5,7 @@ var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage var express = require('..') var request = require('supertest') +const { Buffer } = require('node:buffer'); describe('express.raw()', function () { before(function () { diff --git a/test/express.static.js b/test/express.static.js index 16a8ec0516f..a2035631d66 100644 --- a/test/express.static.js +++ b/test/express.static.js @@ -3,6 +3,8 @@ var assert = require('node:assert') var express = require('..') var path = require('node:path') +const { Buffer } = require('node:buffer'); + var request = require('supertest') var utils = require('./support/utils') diff --git a/test/express.text.js b/test/express.text.js index 2ce6052a07b..e96cc5efe52 100644 --- a/test/express.text.js +++ b/test/express.text.js @@ -2,7 +2,7 @@ var assert = require('node:assert') var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage - +const { Buffer } = require('node:buffer'); var express = require('..') var request = require('supertest') diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index 2f32f9fed1b..f4acf231989 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -2,6 +2,7 @@ var assert = require('node:assert') var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage +const { Buffer } = require('node:buffer'); var express = require('..') var request = require('supertest') diff --git a/test/res.attachment.js b/test/res.attachment.js index 68e611bbc79..8644bab5b2d 100644 --- a/test/res.attachment.js +++ b/test/res.attachment.js @@ -1,5 +1,7 @@ 'use strict' +const { Buffer } = require('node:buffer'); + var express = require('../') , request = require('supertest'); diff --git a/test/res.download.js b/test/res.download.js index db42662e2b2..e9966007eba 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -3,6 +3,7 @@ var after = require('after'); var assert = require('node:assert') var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage +const { Buffer } = require('node:buffer'); var express = require('..'); var path = require('node:path') diff --git a/test/res.send.js b/test/res.send.js index 78a69a5c666..8547b77648b 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -1,6 +1,7 @@ 'use strict' var assert = require('node:assert') +const { Buffer } = require('node:buffer'); var express = require('..'); var methods = require('../lib/utils').methods; var request = require('supertest'); diff --git a/test/res.sendFile.js b/test/res.sendFile.js index 9b0cd83cca3..16eea79761e 100644 --- a/test/res.sendFile.js +++ b/test/res.sendFile.js @@ -3,6 +3,7 @@ var after = require('after'); var assert = require('node:assert') var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage +const { Buffer } = require('node:buffer'); var express = require('../') , request = require('supertest') diff --git a/test/support/utils.js b/test/support/utils.js index a43ca0bb435..fb816b08000 100644 --- a/test/support/utils.js +++ b/test/support/utils.js @@ -5,6 +5,7 @@ */ var assert = require('node:assert'); +const { Buffer } = require('node:buffer'); /** * Module exports. diff --git a/test/utils.js b/test/utils.js index b11b26680bd..1c06036aa98 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,6 +1,7 @@ 'use strict' var assert = require('node:assert'); +const { Buffer } = require('node:buffer'); var utils = require('../lib/utils'); describe('utils.etag(body, encoding)', function(){ From 3910323d09809f3b553af47ffd7b568d8dfd9fd6 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Thu, 3 Jul 2025 08:03:10 +0530 Subject: [PATCH 865/889] chore: use node protocol for node builtin module (#6520) Co-authored-by: Sebastian Beltran --- lib/utils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index a466ec89f06..4f21e7ef1e3 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -18,9 +18,10 @@ var etag = require('etag'); var mime = require('mime-types') var proxyaddr = require('proxy-addr'); var qs = require('qs'); -var querystring = require('querystring'); +var querystring = require('node:querystring'); const { Buffer } = require('node:buffer'); + /** * A list of lowercased HTTP methods that are supported by Node.js. * @api private From b0ed15b4525cd68d4a94d1a71d1a34da6f2961d3 Mon Sep 17 00:00:00 2001 From: mountdisk Date: Fri, 4 Jul 2025 23:47:31 +0900 Subject: [PATCH 866/889] chore: fix typo (#6609) Signed-off-by: mountdisk --- test/res.append.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/res.append.js b/test/res.append.js index 325dd4d12e0..2dd17a3a1fb 100644 --- a/test/res.append.js +++ b/test/res.append.js @@ -108,7 +108,7 @@ function shouldHaveHeaderValues (key, values) { return function (res) { var headers = res.headers[key.toLowerCase()] assert.ok(headers, 'should have header "' + key + '"') - assert.strictEqual(headers.length, values.length, 'should have ' + values.length + ' occurances of "' + key + '"') + assert.strictEqual(headers.length, values.length, 'should have ' + values.length + ' occurrences of "' + key + '"') for (var i = 0; i < values.length; i++) { assert.strictEqual(headers[i], values[i]) } From 7a9311216adf81c49812eb8e645c4a3774424189 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 10:27:41 +0200 Subject: [PATCH 867/889] build(deps): bump github/codeql-action from 3.28.18 to 3.29.2 (#6618) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.18 to 3.29.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ff0a06e83cb2de871e5a09832bc6a81e7276941f...181d5eefc20863364f96762470ba6f862bdef56b) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f37a495f243..e28b741a49a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 with: languages: ${{ matrix.language }} config: | @@ -71,4 +71,4 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 070fc0e49aa..d29f6b60e99 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 with: sarif_file: results.sarif From c5b8d55a6a941fb5f8c783f7734a32f40142c4d9 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 14 Jul 2025 22:18:10 -0500 Subject: [PATCH 868/889] feat: add deprecation warnings for redirect arguments undefined (#6405) --- lib/response.js | 13 +++++++++++++ package.json | 1 + 2 files changed, 14 insertions(+) diff --git a/lib/response.js b/lib/response.js index 09fa0611b4f..7a2f0ecce56 100644 --- a/lib/response.js +++ b/lib/response.js @@ -14,6 +14,7 @@ var contentDisposition = require('content-disposition'); var createError = require('http-errors') +var deprecate = require('depd')('express'); var encodeUrl = require('encodeurl'); var escapeHtml = require('escape-html'); var http = require('node:http'); @@ -826,6 +827,18 @@ res.redirect = function redirect(url) { address = arguments[1] } + if (!address) { + deprecate('Provide a url argument'); + } + + if (typeof address !== 'string') { + deprecate('Url must be a string'); + } + + if (typeof status !== 'number') { + deprecate('Status must be a number'); + } + // Set location header address = this.location(address).get('Location'); diff --git a/package.json b/package.json index bdcd25e60fa..104528ab71d 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", + "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", From ef5f2e13ef64a1575ce8c2d77b180d593644ccfa Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 15 Jul 2025 21:27:50 -0500 Subject: [PATCH 869/889] ci: run CI when the markdown changes (#6632) --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c69b9c937e..606eb603bf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,8 +11,6 @@ on: paths-ignore: - '*.md' pull_request: - paths-ignore: - - '*.md' workflow_dispatch: permissions: From 9420cd3f9b5ee9ff5956db1173aff87eb7aa0316 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 21 Jul 2025 19:14:33 -0400 Subject: [PATCH 870/889] doc: fix the Contributing.md link (#6653) --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index d7e99de5c15..8c495df48d2 100644 --- a/Readme.md +++ b/Readme.md @@ -148,7 +148,7 @@ The Express.js project welcomes all constructive contributions. Contributions ta from code for bug fixes and enhancements, to additions and fixes to documentation, additional tests, triaging incoming pull requests and issues, and more! -See the [Contributing Guide](https://github.com/expressjs/.github/blob/HEAD/CONTRIBUTING.yml) for more technical details on contributing. +See the [Contributing Guide](https://github.com/expressjs/.github/blob/HEAD/CONTRIBUTING.md) for more technical details on contributing. ### Security Issues From b52ff7ca60103673367b2e04c3b48cfd09751388 Mon Sep 17 00:00:00 2001 From: shubham oulkar <91728992+ShubhamOulkar@users.noreply.github.com> Date: Wed, 30 Jul 2025 19:11:53 +0530 Subject: [PATCH 871/889] update contributing and COC links (#6601) --- Readme.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 8c495df48d2..778a952c35a 100644 --- a/Readme.md +++ b/Readme.md @@ -2,7 +2,7 @@ **Fast, unopinionated, minimalist web framework for [Node.js](https://nodejs.org).** -**This project has a [Code of Conduct][].** +**This project has a [Code of Conduct].** ## Table of contents @@ -148,7 +148,7 @@ The Express.js project welcomes all constructive contributions. Contributions ta from code for bug fixes and enhancements, to additions and fixes to documentation, additional tests, triaging incoming pull requests and issues, and more! -See the [Contributing Guide](https://github.com/expressjs/.github/blob/HEAD/CONTRIBUTING.md) for more technical details on contributing. +See the [Contributing Guide] for more technical details on contributing. ### Security Issues @@ -269,4 +269,5 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) [npm-version-image]: https://badgen.net/npm/v/express [ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/express/badge [ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/express -[Code of Conduct]: https://github.com/expressjs/express/blob/master/Code-Of-Conduct.md +[Code of Conduct]: https://github.com/expressjs/.github/blob/HEAD/CODE_OF_CONDUCT.md +[Contributing Guide]: https://github.com/expressjs/.github/blob/HEAD/CONTRIBUTING.md From ed64290e4a8a546be7b3fbe39edd4c3c03e46384 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 20:24:22 -0500 Subject: [PATCH 872/889] build(deps-dev): bump morgan from 1.10.0 to 1.10.1 (#6679) Bumps [morgan](https://github.com/expressjs/morgan) from 1.10.0 to 1.10.1. - [Release notes](https://github.com/expressjs/morgan/releases) - [Changelog](https://github.com/expressjs/morgan/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/morgan/compare/1.10.0...1.10.1) --- updated-dependencies: - dependency-name: morgan dependency-version: 1.10.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 104528ab71d..95d3dfac9e8 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "marked": "^15.0.3", "method-override": "3.0.0", "mocha": "^10.7.3", - "morgan": "1.10.0", + "morgan": "1.10.1", "nyc": "^17.1.0", "pbkdf2-password": "1.2.1", "supertest": "^6.3.0", From 6616e39d4dbce495c83bc71501b627f454d1858f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 20:24:48 -0500 Subject: [PATCH 873/889] build(deps-dev): bump cookie-session from 2.1.0 to 2.1.1 (#6678) Bumps [cookie-session](https://github.com/expressjs/cookie-session) from 2.1.0 to 2.1.1. - [Release notes](https://github.com/expressjs/cookie-session/releases) - [Changelog](https://github.com/expressjs/cookie-session/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/cookie-session/compare/v2.1.0...v2.1.1) --- updated-dependencies: - dependency-name: cookie-session dependency-version: 2.1.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 95d3dfac9e8..7bf3809207c 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "after": "0.8.2", "connect-redis": "^8.0.1", "cookie-parser": "1.4.7", - "cookie-session": "2.1.0", + "cookie-session": "2.1.1", "ejs": "^3.1.10", "eslint": "8.47.0", "express-session": "^1.18.1", From 8f21493cc57dc32fe059d47abb4210d5b383cc31 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 13 Aug 2025 04:28:13 +0530 Subject: [PATCH 874/889] lint: add --fix flag to automatic fix linting issue (#6644) * lint: add --fix flag to automatic fix linting issue * add dedicated lint script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 7bf3809207c..e1bab759a2c 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ ], "scripts": { "lint": "eslint .", + "lint:fix": "eslint . --fix", "test": "mocha --require test/support/env --reporter spec --check-leaks test/ test/acceptance/", "test-ci": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=lcovonly --reporter=text npm test", "test-cov": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=html --reporter=text npm test", From d9a62f983390da932c4f2e21e67a55fa33c164f4 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 20 Aug 2025 18:48:36 +0530 Subject: [PATCH 875/889] chore: update git rules to ignore `yarn.lock` file (#6588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ulises Gascón --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 1bd5c02b28b..768368cd652 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,10 @@ npm-shrinkwrap.json *.log *.gz +# Yarn +yarn-error.log +yarn.lock + # Coveralls .nyc_output coverage From 89f198c6a50ab0cb65b741767791dd1b647e3b2c Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 21 Aug 2025 10:05:29 -0500 Subject: [PATCH 876/889] lib: use req.socket over deprecated req.connection (#6705) Signed-off-by: Sebastian Beltran --- lib/request.js | 6 +++--- test/req.protocol.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/request.js b/lib/request.js index 63e0c1cd607..69990da39b6 100644 --- a/lib/request.js +++ b/lib/request.js @@ -282,12 +282,12 @@ req.is = function is(types) { */ defineGetter(req, 'protocol', function protocol(){ - var proto = this.connection.encrypted + var proto = this.socket.encrypted ? 'https' : 'http'; var trust = this.app.get('trust proxy fn'); - if (!trust(this.connection.remoteAddress, 0)) { + if (!trust(this.socket.remoteAddress, 0)) { return proto; } @@ -406,7 +406,7 @@ defineGetter(req, 'host', function host(){ var trust = this.app.get('trust proxy fn'); var val = this.get('X-Forwarded-Host'); - if (!val || !trust(this.connection.remoteAddress, 0)) { + if (!val || !trust(this.socket.remoteAddress, 0)) { val = this.get('Host'); } else if (val.indexOf(',') !== -1) { // Note: X-Forwarded-Host is normally only ever a diff --git a/test/req.protocol.js b/test/req.protocol.js index 61f76356b4c..def82eda922 100644 --- a/test/req.protocol.js +++ b/test/req.protocol.js @@ -39,7 +39,7 @@ describe('req', function(){ app.enable('trust proxy'); app.use(function(req, res){ - req.connection.encrypted = true; + req.socket.encrypted = true; res.end(req.protocol); }); From aa907945cd1727483a888a0a6481f9f4861593f8 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Fri, 22 Aug 2025 12:42:09 +0530 Subject: [PATCH 877/889] doc: update express app example (#6718) --- Readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 778a952c35a..d62b9821250 100644 --- a/Readme.md +++ b/Readme.md @@ -40,7 +40,9 @@ app.get('/', (req, res) => { res.send('Hello World') }) -app.listen(3000) +app.listen(3000, () => { + console.log('Server is running on http://localhost:3000') +}) ``` ## Installation From 2eb42059f33d9be6ead3bb813d05aa975283d592 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 14 Sep 2025 09:39:32 -0500 Subject: [PATCH 878/889] build(deps): bump github/codeql-action from 3.29.2 to 3.29.5 (#6675) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.2 to 3.29.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/181d5eefc20863364f96762470ba6f862bdef56b...51f77329afa6477de8c49fc9c7046c15b9a4e79d) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: bjohansebas <103585995+bjohansebas@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e28b741a49a..f1fd4bca971 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 + uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 with: languages: ${{ matrix.language }} config: | @@ -71,4 +71,4 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 + uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index d29f6b60e99..5f915be3a0e 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 + uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 with: sarif_file: results.sarif From 9a7afb2886247603ebd69a1c8ee5d2f29542a6c0 Mon Sep 17 00:00:00 2001 From: Jean Burellier Date: Thu, 25 Sep 2025 07:20:45 +0200 Subject: [PATCH 879/889] chore: remove history.md from being packaged on publish (#6780) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index e1bab759a2c..db7661de46d 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,6 @@ }, "files": [ "LICENSE", - "History.md", "Readme.md", "index.js", "lib/" From b9b9f52b2f7c7642b2325320edf633ec44d189a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:34:25 +0200 Subject: [PATCH 880/889] build(deps): bump actions/checkout from 4.2.2 to 5.0.0 (#6797) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/11bd71901bbe5b1630ceea73d27597364c9af683...08c6903cd8c0fde910a37f88322edcfb5dd907a8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 6 +++--- .github/workflows/codeql.yml | 2 +- .github/workflows/legacy.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 606eb603bf5..63adb89fca6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup Node.js @@ -53,7 +53,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -93,7 +93,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f1fd4bca971..1f2034cdc69 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 64074c95f66..d584a342895 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -37,7 +37,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -77,7 +77,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 5f915be3a0e..9717a97203b 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,7 +32,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false From ffa89f2ccfe45f7203aa52e9c5ee67ebd6d3a84e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:40:08 +0200 Subject: [PATCH 881/889] build(deps): bump github/codeql-action from 3.29.7 to 3.30.5 (#6796) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.7 to 3.30.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/51f77329afa6477de8c49fc9c7046c15b9a4e79d...3599b3baa15b485a2e49ef411a7a4bb2452e7f93) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1f2034cdc69..a8477b3b311 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 + uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5 with: languages: ${{ matrix.language }} config: | @@ -71,4 +71,4 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 + uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 9717a97203b..5b90778643f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 + uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5 with: sarif_file: results.sarif From 9e6760e186286f737b7211b46e705344b3ad5804 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:43:45 +0200 Subject: [PATCH 882/889] build(deps): bump ossf/scorecard-action from 2.4.2 to 2.4.3 (#6795) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.2 to 2.4.3. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/05b42c624433fc40578a4040d5cf5e36ddca8cde...4eaacf0543bb3f2c246792bd56e8cdeffafb205a) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 5b90778643f..00ae5f1506a 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif From 60d4c16cc992c80dc27763efa5362723b39ae00f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:43:54 +0200 Subject: [PATCH 883/889] build(deps): bump actions/setup-node from 4.4.0 to 5.0.0 (#6794) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.4.0 to 5.0.0. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/49933ea5288caeca8642d1e84afbd3f7d6820020...a0853c24544627f65ddf259abe73b1d18a591444) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/legacy.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63adb89fca6..d9881a8f4e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: 'lts/*' @@ -58,7 +58,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index d584a342895..0e7d75dcd4c 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -42,7 +42,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: ${{ matrix.node-version }} From e4fb370ad8c2965783b997ac8bfcfad63648453c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:44:02 +0200 Subject: [PATCH 884/889] build(deps): bump actions/download-artifact from 4.3.0 to 5.0.0 (#6793) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.3.0 to 5.0.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/d3f86a106a0bac45b974a628896c90dbdf5c8093...634f93cb2916e3fdff6788551b99b062d0335ce0) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/legacy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9881a8f4e2..13d3f6881aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,7 +102,7 @@ jobs: run: sudo apt-get -y install lcov - name: Collect coverage reports - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: path: ./coverage pattern: coverage-node-* diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 0e7d75dcd4c..b1c06532592 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -86,7 +86,7 @@ jobs: run: sudo apt-get -y install lcov - name: Collect coverage reports - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: path: ./coverage pattern: coverage-node-* From 64e7373d6976dd3ec32a92dbc31ff19700fe152a Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Thu, 16 Oct 2025 13:51:39 +0200 Subject: [PATCH 885/889] ci: add node.js 25 to test matrix (#6843) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13d3f6881aa..ee6159cc9ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - node-version: [18, 19, 20, 21, 22, 23, 24] + node-version: [18, 19, 20, 21, 22, 23, 24, 25] # Node.js release schedule: https://nodejs.org/en/about/releases/ name: Node.js ${{ matrix.node-version }} - ${{matrix.os}} From 1b196c8b82af8df18d40c66c30d958448ab5e2d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Nov 2025 10:44:12 +0100 Subject: [PATCH 886/889] build(deps): bump actions/download-artifact from 5.0.0 to 6.0.0 (#6871) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/legacy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee6159cc9ae..ffa33e2e24f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,7 +102,7 @@ jobs: run: sudo apt-get -y install lcov - name: Collect coverage reports - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: path: ./coverage pattern: coverage-node-* diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index b1c06532592..d0626e29947 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -86,7 +86,7 @@ jobs: run: sudo apt-get -y install lcov - name: Collect coverage reports - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: path: ./coverage pattern: coverage-node-* From 374fc1a0f9a8e4fe8e9c4993bf9f4814eff5bf9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Nov 2025 10:45:07 +0100 Subject: [PATCH 887/889] build(deps): bump actions/setup-node from 5.0.0 to 6.0.0 (#6870) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/legacy.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffa33e2e24f..ed8408bc3fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: 'lts/*' @@ -58,7 +58,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index d0626e29947..e5f90ea52b7 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -42,7 +42,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: ${{ matrix.node-version }} From db507669ca5dc559309eabe4f6df03bb28345078 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Nov 2025 10:45:51 +0100 Subject: [PATCH 888/889] build(deps): bump github/codeql-action from 3.30.5 to 4.31.2 (#6869) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a8477b3b311..1ac121c027f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5 + uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5 with: languages: ${{ matrix.language }} config: | @@ -71,4 +71,4 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5 + uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 00ae5f1506a..d6063614336 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5 + uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5 with: sarif_file: results.sarif From 4453d83ccaed5c80f0c10a23d01216eff612ee56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Nov 2025 10:46:37 +0100 Subject: [PATCH 889/889] build(deps): bump actions/upload-artifact from 4.6.2 to 5.0.0 (#6868) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/legacy.yml | 2 +- .github/workflows/scorecard.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed8408bc3fb..dab7815960c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,7 +80,7 @@ jobs: run: npm run test-ci - name: Upload code coverage - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }} path: ./coverage/lcov.info diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index e5f90ea52b7..1df70694732 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -64,7 +64,7 @@ jobs: run: npm run test-ci - name: Upload code coverage - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }} path: ./coverage/lcov.info diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index d6063614336..9cbd54487d8 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -59,7 +59,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: SARIF file path: results.sarif