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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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/256] 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 943f28f05f11f789e4156bf7dcb37f548c96b6aa Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 21 Jan 2016 21:26:03 -0500 Subject: [PATCH 027/256] 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 028/256] 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 a856456a956f294d24b37710d0e6971897c97b5b Mon Sep 17 00:00:00 2001 From: Mike Tunnicliffe Date: Mon, 14 Mar 2016 13:11:00 +0000 Subject: [PATCH 029/256] 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 030/256] 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 031/256] 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 07077c44570b4f4faf27b9c92e6d22e81c0d11fb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sat, 28 Jan 2017 21:54:42 -0500 Subject: [PATCH 032/256] 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 033/256] 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 034/256] 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 035/256] 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 06f423d4f56bad350690ebf0f9fe7b79961dbc96 Mon Sep 17 00:00:00 2001 From: Wes Date: Mon, 20 Feb 2017 18:34:45 -0600 Subject: [PATCH 036/256] 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 037/256] 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 21f725e0ef9e1e9a8ea51e8486e9cadeae956774 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 6 Mar 2017 08:43:58 -0500 Subject: [PATCH 038/256] 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 e3bd14dcca6128afc8ba7f11a4f7e2b34923d66e Mon Sep 17 00:00:00 2001 From: Mike Tunnicliffe Date: Mon, 14 Mar 2016 12:32:35 +0000 Subject: [PATCH 039/256] 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 040/256] 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 f4120a645301366891775d1f03925449239a2cb7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 25 Sep 2017 01:28:00 -0400 Subject: [PATCH 041/256] 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 8fabed82aa636e10951b6a95f933b07217649e1e Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 13 Oct 2017 22:12:14 -0400 Subject: [PATCH 042/256] Remove path-to-regexp dependency --- History.md | 6 ++++++ package.json | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 1bd1cb6c5be..ef932de9fa7 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +5.x +=== + + * remove: + - `path-to-regexp` dependency + 5.0.0-alpha.6 / 2017-09-24 ========================== diff --git a/package.json b/package.json index de1a1dbb002..436251ace99 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.1", "path-is-absolute": "1.0.1", - "path-to-regexp": "0.1.7", "proxy-addr": "~1.1.5", "qs": "6.5.0", "range-parser": "~1.2.0", From a163e2cdf488c57706eca419285ef782b2a19e29 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 13 Oct 2017 22:57:58 -0400 Subject: [PATCH 043/256] deps: debug@3.1.0 --- History.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 54683c71ccd..0fc4e059f25 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,12 @@ This incorporates all changes after 4.15.5 up to 4.16.2. * remove: - `path-to-regexp` dependency + * deps: debug@3.1.0 + - Add `DEBUG_HIDE_DATE` environment variable + - Change timer to per-namespace instead of global + - Change non-TTY date format + - Remove `DEBUG_FD` environment variable support + - Support 256 namespace colors 5.0.0-alpha.6 / 2017-09-24 ========================== diff --git a/package.json b/package.json index de4edcf562b..dcbdbe1e5f8 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", - "debug": "2.6.9", + "debug": "3.1.0", "depd": "~1.1.1", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", From 659fcc1598ec6778faa75534595ca8e5a2b14b27 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 13 Oct 2017 22:59:21 -0400 Subject: [PATCH 044/256] deps: router@~1.3.2 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0fc4e059f25..684b1bace23 100644 --- a/History.md +++ b/History.md @@ -11,6 +11,11 @@ This incorporates all changes after 4.15.5 up to 4.16.2. - Change non-TTY date format - Remove `DEBUG_FD` environment variable support - Support 256 namespace colors + * deps: router@~1.3.2 + - deps: debug@2.6.9 + - deps: parseurl@~1.3.2 + - deps: setprototypeof@1.1.0 + - deps: utils-merge@1.0.1 5.0.0-alpha.6 / 2017-09-24 ========================== diff --git a/package.json b/package.json index dcbdbe1e5f8..365b1d46c11 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "proxy-addr": "~2.0.2", "qs": "6.5.1", "range-parser": "~1.2.0", - "router": "~1.3.1", + "router": "~1.3.2", "safe-buffer": "5.1.1", "send": "0.16.1", "serve-static": "1.13.1", From fa22245cc652a41009d2f339e769ed72dad2fc0f Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 23 Oct 2018 21:02:44 -0400 Subject: [PATCH 045/256] deps: router@2.0.0-alpha.1 --- History.md | 6 ++++-- package.json | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index b53a26343f8..59a7a976177 100644 --- a/History.md +++ b/History.md @@ -11,8 +11,10 @@ This incorporates all changes after 4.15.5 up to 4.16.4. - Change non-TTY date format - Remove `DEBUG_FD` environment variable support - Support 256 namespace colors - * deps: router@~1.3.2 - - deps: debug@2.6.9 + * deps: router@2.0.0-alpha.1 + - Add basic support for returned, rejected Promises + - Fix JSDoc for `Router` constructor + - deps: debug@3.1.0 - deps: parseurl@~1.3.2 - deps: setprototypeof@1.1.0 - deps: utils-merge@1.0.1 diff --git a/package.json b/package.json index b0f5ea21391..eddafffd919 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "proxy-addr": "~2.0.4", "qs": "6.5.2", "range-parser": "~1.2.0", - "router": "~1.3.2", + "router": "2.0.0-alpha.1", "safe-buffer": "5.1.2", "send": "0.16.2", "serve-static": "1.13.2", From c82fa194475edabb04535914ddc12a622a495b64 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 26 Oct 2018 21:31:28 -0400 Subject: [PATCH 046/256] tests: add router promise tests --- test/app.route.js | 135 +++++++++++++++++++++++++++++++++++++++++++++ test/app.router.js | 134 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) diff --git a/test/app.route.js b/test/app.route.js index 75e5e0b8421..29131a9ec42 100644 --- a/test/app.route.js +++ b/test/app.route.js @@ -1,6 +1,8 @@ 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(); @@ -59,4 +61,137 @@ describe('app.route', function(){ .get('/test') .expect(404, done); }); + + describePromises('promise support', function () { + it('should pass rejected promise value', function (done) { + var app = express() + var route = app.route('/foo') + + route.all(function createError (req, res, next) { + return Promise.reject(new Error('boom!')) + }) + + route.all(function helloWorld (req, res) { + res.send('hello, world!') + }) + + route.all(function handleError (err, req, res, next) { + res.status(500) + res.send('caught: ' + err.message) + }) + + request(app) + .get('/foo') + .expect(500, 'caught: boom!', done) + }) + + it('should pass rejected promise without value', function (done) { + var app = express() + var route = app.route('/foo') + + route.all(function createError (req, res, next) { + return Promise.reject() + }) + + route.all(function helloWorld (req, res) { + res.send('hello, world!') + }) + + route.all(function handleError (err, req, res, next) { + res.status(500) + res.send('caught: ' + err.message) + }) + + request(app) + .get('/foo') + .expect(500, 'caught: Rejected promise', done) + }) + + it('should ignore resolved promise', function (done) { + var app = express() + var route = app.route('/foo') + + route.all(function createError (req, res, next) { + res.send('saw GET /foo') + return Promise.resolve('foo') + }) + + route.all(function () { + done(new Error('Unexpected route invoke')) + }) + + request(app) + .get('/foo') + .expect(200, 'saw GET /foo', done) + }) + + describe('error handling', function () { + it('should pass rejected promise value', function (done) { + var app = express() + var route = app.route('/foo') + + route.all(function createError (req, res, next) { + return Promise.reject(new Error('boom!')) + }) + + route.all(function handleError (err, req, res, next) { + return Promise.reject(new Error('caught: ' + err.message)) + }) + + route.all(function handleError (err, req, res, next) { + res.status(500) + res.send('caught again: ' + err.message) + }) + + request(app) + .get('/foo') + .expect(500, 'caught again: caught: boom!', done) + }) + + it('should pass rejected promise without value', function (done) { + var app = express() + var route = app.route('/foo') + + route.all(function createError (req, res, next) { + return Promise.reject(new Error('boom!')) + }) + + route.all(function handleError (err, req, res, next) { + return Promise.reject() + }) + + route.all(function handleError (err, req, res, next) { + res.status(500) + res.send('caught again: ' + err.message) + }) + + request(app) + .get('/foo') + .expect(500, 'caught again: Rejected promise', done) + }) + + it('should ignore resolved promise', function (done) { + var app = express() + var route = app.route('/foo') + + route.all(function createError (req, res, next) { + return Promise.reject(new Error('boom!')) + }) + + route.all(function handleError (err, req, res, next) { + res.status(500) + res.send('caught: ' + err.message) + return Promise.resolve('foo') + }) + + route.all(function () { + done(new Error('Unexpected route invoke')) + }) + + request(app) + .get('/foo') + .expect(500, 'caught: boom!', done) + }) + }) + }) }); diff --git a/test/app.router.js b/test/app.router.js index 4c097ed7717..581cf0d9e09 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -5,6 +5,8 @@ var express = require('../') , assert = require('assert') , methods = require('methods'); +var describePromises = global.Promise ? describe : describe.skip + describe('app.router', function(){ it('should restore req.params after leaving router', function(done){ var app = express(); @@ -1020,6 +1022,138 @@ describe('app.router', function(){ }) }) + describePromises('promise support', function () { + it('should pass rejected promise value', function (done) { + var app = express() + var router = new express.Router() + + router.use(function createError (req, res, next) { + return Promise.reject(new Error('boom!')) + }) + + 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) + }) + + it('should pass rejected promise without value', function (done) { + var app = express() + var router = new express.Router() + + router.use(function createError (req, res, next) { + return Promise.reject() + }) + + 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) + }) + + it('should ignore resolved promise', function (done) { + var app = express() + var router = new express.Router() + + router.use(function createError (req, res, next) { + res.send('saw GET /foo') + return Promise.resolve('foo') + }) + + router.use(function () { + done(new Error('Unexpected middleware invoke')) + }) + + app.use(router) + + request(app) + .get('/foo') + .expect(200, 'saw GET /foo', done) + }) + + describe('error handling', function () { + it('should pass rejected promise value', function (done) { + var app = express() + var router = new express.Router() + + router.use(function createError (req, res, next) { + return Promise.reject(new Error('boom!')) + }) + + router.use(function handleError (err, req, res, next) { + return Promise.reject(new Error('caught: ' + err.message)) + }) + + 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) + }) + + it('should pass rejected promise without value', function (done) { + var app = express() + var router = new express.Router() + + router.use(function createError (req, res, next) { + return Promise.reject() + }) + + router.use(function handleError (err, req, res, next) { + return Promise.reject(new Error('caught: ' + err.message)) + }) + + 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) + }) + + it('should ignore resolved promise', function (done) { + var app = express() + var router = new express.Router() + + router.use(function createError (req, res, next) { + return Promise.reject(new Error('boom!')) + }) + + router.use(function handleError (err, req, res, next) { + res.send('saw ' + err.name + ': ' + err.message) + return Promise.resolve('foo') + }) + + router.use(function () { + done(new Error('Unexpected middleware invoke')) + }) + + app.use(router) + + request(app) + .get('/foo') + .expect(200, 'saw Error: boom!', done) + }) + }) + }) + it('should allow rewriting of the url', function(done){ var app = express(); From 5f0c829d7ca7da746ee859f13a54631000f8a9b5 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 26 Oct 2018 22:29:15 -0400 Subject: [PATCH 047/256] 5.0.0-alpha.7 --- History.md | 10 +++++++--- package.json | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 59a7a976177..f2190ace3d1 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,11 @@ -5.x -=== +5.0.0-alpha.7 / 2018-10-26 +========================== + +This is the seventh Express 5.0 alpha release, based off 4.16.4 and includes +changes from 5.0.0-alpha.6. -This incorporates all changes after 4.15.5 up to 4.16.4. +The major change with this alpha is the basic support for returned, rejected +Promises in the router. * remove: - `path-to-regexp` dependency diff --git a/package.json b/package.json index eddafffd919..eae872acd33 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-alpha.6", + "version": "5.0.0-alpha.7", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From bd04d8a87fbe22e6fabaa6a5451a885c0790043a Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 25 Mar 2020 20:14:47 -0400 Subject: [PATCH 048/256] 5.0.0-alpha.8 --- History.md | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index f918ba25894..7e86b1647b9 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,8 @@ -5.x -=== +5.0.0-alpha.8 / 2020-03-25 +========================== -This incorporates all changes after 4.16.4 up to 4.17.1. +This is the sixth Express 5.0 alpha release, based off 4.17.1 and includes +changes from 5.0.0-alpha.7. 5.0.0-alpha.7 / 2018-10-26 ========================== diff --git a/package.json b/package.json index 6f3cd3abe8f..013629f530b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-alpha.7", + "version": "5.0.0-alpha.8", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 8aabecaf1f6343ec9a39fcdeff2deb3b4544f35f Mon Sep 17 00:00:00 2001 From: Alexander Belov Date: Sat, 27 Jun 2020 00:42:49 +0300 Subject: [PATCH 049/256] docs: fix typo in history closes #4286 closes #4327 --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 7e86b1647b9..09eb6dca1e7 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,7 @@ 5.0.0-alpha.8 / 2020-03-25 ========================== -This is the sixth Express 5.0 alpha release, based off 4.17.1 and includes +This is the eighth Express 5.0 alpha release, based off 4.17.1 and includes changes from 5.0.0-alpha.7. 5.0.0-alpha.7 / 2018-10-26 From 1574925cad7fd07143f96e8667e7af41b6866eaa Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Wed, 15 Dec 2021 21:35:34 -0500 Subject: [PATCH 050/256] deps: router@2.0.0-beta.1 closes #4321 --- History.md | 13 ++ examples/downloads/index.js | 2 +- package.json | 2 +- test/Router.js | 18 --- test/app.router.js | 270 +++++++++++------------------------- 5 files changed, 97 insertions(+), 208 deletions(-) diff --git a/History.md b/History.md index 371fa7292e1..3b811bc0228 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,19 @@ This incorporates all changes after 4.17.1 up to 4.17.2. + * deps: router@2.0.0-beta.1 + - Add new `?`, `*`, and `+` parameter modifiers + - Internalize private `router.process_params` method + - Matching group expressions are only RegExp syntax + - Named matching groups no longer available by position in `req.params` + - Regular expressions can only be used in a matching group + - Remove `debug` dependency + - Special `*` path segment behavior removed + - deps: array-flatten@3.0.0 + - deps: parseurl@~1.3.3 + - deps: path-to-regexp@3.2.0 + - deps: setprototypeof@1.2.0 + 5.0.0-alpha.8 / 2020-03-25 ========================== diff --git a/examples/downloads/index.js b/examples/downloads/index.js index 9321f3bf951..dc59532c40d 100644 --- a/examples/downloads/index.js +++ b/examples/downloads/index.js @@ -17,7 +17,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){ +app.get('/files/:file+', function (req, res, next) { var filePath = path.join(__dirname, 'files', req.params.file); res.download(filePath, function (err) { diff --git a/package.json b/package.json index ca0740add38..30f06d5a141 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "proxy-addr": "~2.0.7", "qs": "6.9.6", "range-parser": "~1.2.1", - "router": "2.0.0-alpha.1", + "router": "2.0.0-beta.1", "safe-buffer": "5.2.1", "send": "0.17.2", "serve-static": "1.14.2", diff --git a/test/Router.js b/test/Router.js index a2194981463..30837ff1237 100644 --- a/test/Router.js +++ b/test/Router.js @@ -344,24 +344,6 @@ 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() { diff --git a/test/app.router.js b/test/app.router.js index 6ec27d87def..fc004300cee 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -189,7 +189,7 @@ describe('app.router', function(){ .expect('editing user 10', done); }) - it.skip('should ensure regexp matches path prefix', function (done) { + it('should ensure regexp matches path prefix', function (done) { var app = express() var p = [] @@ -315,7 +315,7 @@ 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]] })); }); @@ -331,7 +331,7 @@ 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]] })); }); @@ -553,23 +553,6 @@ describe('app.router', function(){ }) }) - it('should allow escaped regexp', function(done){ - var app = express(); - - app.get('/user/\\d+', function(req, res){ - res.end('woot'); - }); - - request(app) - .get('/user/10') - .expect(200, function (err) { - if (err) return done(err) - request(app) - .get('/user/tj') - .expect(404, done); - }); - }) - it('should allow literal "."', function(done){ var app = express(); @@ -585,171 +568,6 @@ describe('app.router', function(){ .expect('users from 1 to 50', done); }) - 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 decode 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(); - - app.get('/user/*.json', function(req, res){ - res.end(req.params[0]); - }); - - request(app) - .get('/user/tj.json') - .expect('tj', done); - }) - - it('should work with several', function(done){ - var app = express(); - - app.get('/api/*.*', function(req, res){ - var resource = req.params[0] - , format = req.params[1]; - res.end(resource + ' as ' + format); - }); - - request(app) - .get('/api/users/foo.bar.json') - .expect('users/foo.bar as json', done); - }) - - it('should work cross-segment', function(done){ - var app = express(); - - app.get('/api*', function(req, res){ - res.send(req.params[0]); - }); - - request(app) - .get('/api') - .expect('', function(){ - request(app) - .get('/api/hey') - .expect('/hey', done); - }); - }) - - it('should allow naming', function(done){ - var app = express(); - - app.get('/api/:resource(*)', function(req, res){ - var resource = req.params.resource; - res.end(resource); - }); - - request(app) - .get('/api/users/0.json') - .expect('users/0.json', done); - }) - - it('should not be greedy immediately after param', function(done){ - var app = express(); - - app.get('/user/:user*', function(req, res){ - res.end(req.params.user); - }); - - request(app) - .get('/user/122') - .expect('122', done); - }) - - it('should eat everything after /', function(done){ - var app = express(); - - app.get('/user/:user*', function(req, res){ - res.end(req.params.user); - }); - - request(app) - .get('/user/122/aaa') - .expect('122', done); - }) - - it('should span multiple segments', function(done){ - var app = express(); - - app.get('/file/*', function(req, res){ - res.end(req.params[0]); - }); - - request(app) - .get('/file/javascripts/jquery.js') - .expect('javascripts/jquery.js', done); - }) - - it('should be optional', function(done){ - var app = express(); - - app.get('/file/*', function(req, res){ - res.end(req.params[0]); - }); - - request(app) - .get('/file/') - .expect('', done); - }) - - it('should require a preceding /', function(done){ - var app = express(); - - app.get('/file/*', function(req, res){ - res.end(req.params[0]); - }); - - request(app) - .get('/file') - .expect(404, done); - }) - - it('should keep correct parameter indexes', function(done){ - var app = express(); - - app.get('/*/user/:id', function (req, res) { - res.send(req.params); - }); - - request(app) - .get('/1/user/2') - .expect(200, '{"0":"1","id":"2"}', done); - }) - - it('should work within arrays', function(done){ - var app = express(); - - app.get(['/user/:id', '/foo/*', '/:bar'], function (req, res) { - res.send(req.params.bar); - }); - - request(app) - .get('/test') - .expect(200, 'test', done); - }) - }) - describe(':name', function(){ it('should denote a capture group', function(done){ var app = express(); @@ -791,7 +609,7 @@ describe('app.router', function(){ 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.params[0] ? ' (old)' : '')); }); @@ -862,6 +680,82 @@ describe('app.router', function(){ }) }) + describe(':name*', function () { + it('should match one segment', function (done) { + var app = express() + + app.get('/user/:user*', function (req, res) { + res.end(req.params.user) + }) + + request(app) + .get('/user/122') + .expect('122', done) + }) + + it('should match many segments', function (done) { + var app = express() + + app.get('/user/:user*', function (req, res) { + res.end(req.params.user) + }) + + request(app) + .get('/user/1/2/3/4') + .expect('1/2/3/4', done) + }) + + it('should match zero segments', function (done) { + var app = express() + + app.get('/user/:user*', function (req, res) { + res.end(req.params.user) + }) + + request(app) + .get('/user') + .expect('', done) + }) + }) + + describe(':name+', function () { + it('should match one segment', function (done) { + var app = express() + + app.get('/user/:user+', function (req, res) { + res.end(req.params.user) + }) + + request(app) + .get('/user/122') + .expect(200, '122', done) + }) + + it('should match many segments', function (done) { + var app = express() + + app.get('/user/:user+', function (req, res) { + res.end(req.params.user) + }) + + request(app) + .get('/user/1/2/3/4') + .expect(200, '1/2/3/4', done) + }) + + it('should not match zero segments', function (done) { + var app = express() + + app.get('/user/:user+', function (req, res) { + res.end(req.params.user) + }) + + request(app) + .get('/user') + .expect(404, done) + }) + }) + describe('.:name', function(){ it('should denote a format', function(done){ var app = express(); @@ -1199,7 +1093,7 @@ describe('app.router', function(){ var app = express(); var path = []; - app.get('*', function(req, res, next){ + app.get('/:path+', function (req, res, next) { path.push(0); next(); }); @@ -1219,7 +1113,7 @@ describe('app.router', function(){ next(); }); - app.get('*', function(req, res, next){ + app.get('/(.*)', function (req, res, next) { path.push(4); next(); }); From af341b0f098393cb85a123b51b308f760937e6b8 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 17 Dec 2021 23:02:38 -0500 Subject: [PATCH 051/256] deps: body-parser@2.0.0-beta.1 --- History.md | 4 ++++ examples/auth/index.js | 3 ++- examples/cookies/index.js | 8 ++++++-- package.json | 2 +- test/express.json.js | 4 ++-- test/express.raw.js | 4 ++-- test/express.text.js | 4 ++-- test/express.urlencoded.js | 8 ++++---- 8 files changed, 23 insertions(+), 14 deletions(-) diff --git a/History.md b/History.md index 3b811bc0228..9e5d35ce59d 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,10 @@ This incorporates all changes after 4.17.1 up to 4.17.2. + * deps: body-parser@2.0.0-beta.1 + - `req.body` is no longer always initialized to `{}` + - `urlencoded` parser now defaults `extended` to `false` + - Use `on-finished` to determine when body read * deps: router@2.0.0-beta.1 - Add new `?`, `*`, and `+` parameter modifiers - Internalize private `router.process_params` method diff --git a/examples/auth/index.js b/examples/auth/index.js index b8e854300cb..2f05d5ff8dd 100644 --- a/examples/auth/index.js +++ b/examples/auth/index.js @@ -16,7 +16,7 @@ app.set('views', path.join(__dirname, 'views')); // middleware -app.use(express.urlencoded({ extended: false })) +app.use(express.urlencoded()) app.use(session({ resave: false, // don't save session if unmodified saveUninitialized: false, // don't create session until something stored @@ -100,6 +100,7 @@ app.get('/login', function(req, res){ }); app.post('/login', function(req, res){ + if (!req.body) return res.sendStatus(400) authenticate(req.body.username, req.body.password, function(err, user){ if (user) { // Regenerate session when signing in diff --git a/examples/cookies/index.js b/examples/cookies/index.js index 93515e59612..7d6264a143c 100644 --- a/examples/cookies/index.js +++ b/examples/cookies/index.js @@ -17,7 +17,7 @@ if (process.env.NODE_ENV !== 'test') app.use(logger(':method :url')) app.use(cookieParser('my secret here')); // parses x-www-form-urlencoded -app.use(express.urlencoded({ extended: false })) +app.use(express.urlencoded()) app.get('/', function(req, res){ if (req.cookies.remember) { @@ -36,7 +36,11 @@ app.get('/forget', function(req, res){ app.post('/', function(req, res){ var minute = 60000; - if (req.body.remember) res.cookie('remember', 1, { maxAge: minute }); + + if (req.body && req.body.remember) { + res.cookie('remember', 1, { maxAge: minute }) + } + res.redirect('back'); }); diff --git a/package.json b/package.json index 30f06d5a141..d40c3ca6649 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "accepts": "~1.3.7", "array-flatten": "2.1.1", - "body-parser": "1.19.1", + "body-parser": "2.0.0-beta.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.4.1", diff --git a/test/express.json.js b/test/express.json.js index 907fa0cfeb8..16ac328addf 100644 --- a/test/express.json.js +++ b/test/express.json.js @@ -312,7 +312,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/json') .send('{"user":"tobi"}') - .expect(200, '{}', done) + .expect(200, '', done) }) }) @@ -344,7 +344,7 @@ describe('express.json()', function () { .post('/') .set('Content-Type', 'application/x-json') .send('{"user":"tobi"}') - .expect(200, '{}', done) + .expect(200, '', done) }) }) diff --git a/test/express.raw.js b/test/express.raw.js index 571c29ca9bc..fbe52576de8 100644 --- a/test/express.raw.js +++ b/test/express.raw.js @@ -182,7 +182,7 @@ describe('express.raw()', function () { var test = request(this.app).post('/') test.set('Content-Type', 'application/octet-stream') test.write(Buffer.from('000102', 'hex')) - test.expect(200, '{}', done) + test.expect(200, '', done) }) }) @@ -211,7 +211,7 @@ describe('express.raw()', function () { var test = request(this.app).post('/') test.set('Content-Type', 'application/x-foo') test.write(Buffer.from('000102', 'hex')) - test.expect(200, '{}', done) + test.expect(200, '', done) }) }) diff --git a/test/express.text.js b/test/express.text.js index 7c92f90e5aa..ef95d3aa9b2 100644 --- a/test/express.text.js +++ b/test/express.text.js @@ -195,7 +195,7 @@ describe('express.text()', function () { .post('/') .set('Content-Type', 'text/plain') .send('user is tobi') - .expect(200, '{}', done) + .expect(200, '', done) }) }) @@ -225,7 +225,7 @@ describe('express.text()', function () { .post('/') .set('Content-Type', 'text/xml') .send('tobi') - .expect(200, '{}', done) + .expect(200, '', done) }) }) diff --git a/test/express.urlencoded.js b/test/express.urlencoded.js index 6011de05f7a..ef94cec9423 100644 --- a/test/express.urlencoded.js +++ b/test/express.urlencoded.js @@ -73,12 +73,12 @@ describe('express.urlencoded()', function () { .expect(200, '{"user":"tobi"}', done) }) - it('should parse extended syntax', function (done) { + it('should not parse extended syntax', function (done) { request(this.app) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send('user[name][first]=Tobi') - .expect(200, '{"user":{"name":{"first":"Tobi"}}}', done) + .expect(200, '{"user[name][first]":"Tobi"}', done) }) describe('with extended option', function () { @@ -441,7 +441,7 @@ describe('express.urlencoded()', function () { .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send('user=tobi') - .expect(200, '{}', done) + .expect(200, '', done) }) }) @@ -473,7 +473,7 @@ describe('express.urlencoded()', function () { .post('/') .set('Content-Type', 'application/x-foo') .send('user=tobi') - .expect(200, '{}', done) + .expect(200, '', done) }) }) From 450c468d0469ea79c878084c623cd18642d7ad7d Mon Sep 17 00:00:00 2001 From: Czarek Date: Sun, 15 Apr 2018 10:29:03 +0200 Subject: [PATCH 052/256] Change query parser setting default to 'simple' closes #3361 closes #3621 --- History.md | 2 ++ lib/application.js | 2 +- test/req.query.js | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 9e5d35ce59d..028317d933d 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,8 @@ This incorporates all changes after 4.17.1 up to 4.17.2. + * change: + - query parser setting defaults to `'simple'` * deps: body-parser@2.0.0-beta.1 - `req.body` is no longer always initialized to `{}` - `urlencoded` parser now defaults `extended` to `false` diff --git a/lib/application.js b/lib/application.js index c4d69e9ed6f..85967249c49 100644 --- a/lib/application.js +++ b/lib/application.js @@ -89,7 +89,7 @@ app.defaultConfiguration = function defaultConfiguration() { this.enable('x-powered-by'); this.set('etag', 'weak'); this.set('env', env); - this.set('query parser', 'extended'); + this.set('query parser', 'simple') this.set('subdomain offset', 2); this.set('trust proxy', false); diff --git a/test/req.query.js b/test/req.query.js index 869fbc360b4..067d4521075 100644 --- a/test/req.query.js +++ b/test/req.query.js @@ -12,12 +12,12 @@ describe('req', function(){ .expect(200, '{}', done); }); - it('should default to parse complex keys', function (done) { + it('should default to parse simple keys', function (done) { var app = createApp(); request(app) .get('/?user[name]=tj') - .expect(200, '{"user":{"name":"tj"}}', done); + .expect(200, '{"user[name]":"tj"}', done); }); describe('when "query parser" is extended', function () { From 3d05e85b0cfe76ed0c70f842dbdbf27d9a7c8d39 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 1 Feb 2022 21:51:28 -0500 Subject: [PATCH 053/256] deps: array-flatten@3.0.0 --- History.md | 1 + lib/application.js | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 028317d933d..b10b2cfe4f9 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ This incorporates all changes after 4.17.1 up to 4.17.2. * change: - query parser setting defaults to `'simple'` + * deps: array-flatten@3.0.0 * deps: body-parser@2.0.0-beta.1 - `req.body` is no longer always initialized to `{}` - `urlencoded` parser now defaults `extended` to `false` diff --git a/lib/application.js b/lib/application.js index 85967249c49..ae050c9fa16 100644 --- a/lib/application.js +++ b/lib/application.js @@ -21,7 +21,7 @@ var http = require('http'); var compileETag = require('./utils').compileETag; var compileQueryParser = require('./utils').compileQueryParser; var compileTrust = require('./utils').compileTrust; -var flatten = require('array-flatten'); +var flatten = require('array-flatten').flatten var merge = require('utils-merge'); var resolve = require('path').resolve; var Router = require('router'); diff --git a/package.json b/package.json index d40c3ca6649..50dc8e1dcd0 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ ], "dependencies": { "accepts": "~1.3.7", - "array-flatten": "2.1.1", + "array-flatten": "3.0.0", "body-parser": "2.0.0-beta.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", From a0276c6c91b3b119acc045640e8f4e0616734526 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Sun, 6 Feb 2022 10:26:18 -0500 Subject: [PATCH 054/256] Use mime-types for file to content type mapping --- History.md | 1 + lib/response.js | 23 +++++++++-------------- lib/utils.js | 4 ++-- package.json | 1 + 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/History.md b/History.md index b10b2cfe4f9..66f59388ebc 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ This incorporates all changes after 4.17.1 up to 4.17.2. * change: - query parser setting defaults to `'simple'` + - Use `mime-types` for file to content type mapping * deps: array-flatten@3.0.0 * deps: body-parser@2.0.0-beta.1 - `req.body` is no longer always initialized to `{}` diff --git a/lib/response.js b/lib/response.js index 8949f9dbbc6..d3c8a45b5cd 100644 --- a/lib/response.js +++ b/lib/response.js @@ -18,6 +18,7 @@ var encodeUrl = require('encodeurl'); var escapeHtml = require('escape-html'); 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 statuses = require('statuses') @@ -29,7 +30,6 @@ var setCharset = require('./utils').setCharset; var cookie = require('cookie'); var send = require('send'); var extname = path.extname; -var mime = send.mime; var resolve = path.resolve; var vary = require('vary'); @@ -47,13 +47,6 @@ var res = Object.create(http.ServerResponse.prototype) module.exports = res -/** - * Module variables. - * @private - */ - -var charsetRegExp = /;\s*charset\s*=/; - /** * Set status `code`. * @@ -451,8 +444,10 @@ res.download = function download (path, filename, options, callback) { }; /** - * Set _Content-Type_ response header with `type` through `mime.lookup()` + * Set _Content-Type_ response header with `type` through `mime.contentType()` * when it does not contain "/", or set the Content-Type to `type` otherwise. + * When no mapping is found though `mime.contentType()`, the type is set to + * "application/octet-stream". * * Examples: * @@ -470,7 +465,7 @@ res.download = function download (path, filename, options, callback) { res.contentType = res.type = function contentType(type) { var ct = type.indexOf('/') === -1 - ? mime.lookup(type) + ? (mime.contentType(type) || 'application/octet-stream') : type; return this.set('Content-Type', ct); @@ -621,6 +616,9 @@ res.append = function append(field, val) { * * Aliased as `res.header()`. * + * When the set header is "Content-Type", the type is expanded to include + * the charset if not present using `mime.contentType()`. + * * @param {String|Object} field * @param {String|Array} val * @return {ServerResponse} for chaining @@ -639,10 +637,7 @@ res.header = function header(field, val) { 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(); - } + value = mime.contentType(value) } this.setHeader(field, value); diff --git a/lib/utils.js b/lib/utils.js index 9dd361a222a..43cf47ada88 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -14,8 +14,8 @@ var Buffer = require('safe-buffer').Buffer var contentType = require('content-type'); -var mime = require('send').mime; var etag = require('etag'); +var mime = require('mime-types') var proxyaddr = require('proxy-addr'); var qs = require('qs'); var querystring = require('querystring'); @@ -53,7 +53,7 @@ exports.wetag = createETagGenerator({ weak: true }) exports.normalizeType = function(type){ return ~type.indexOf('/') ? acceptParams(type) - : { value: mime.lookup(type), params: {} }; + : { value: (mime.lookup(type) || 'application/octet-stream'), params: {} } }; /** diff --git a/package.json b/package.json index 50dc8e1dcd0..85ecc68011b 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "~1.1.2", + "mime-types": "~2.1.34", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-is-absolute": "1.0.1", From f6db4ee805a62edb066c5290f4c9c444f2aff6fb Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 8 Feb 2022 09:48:54 -0500 Subject: [PATCH 055/256] Drop support for Node.js below 4 --- .eslintrc.yml | 4 +++- .github/workflows/ci.yml | 28 ++++------------------------ History.md | 1 + appveyor.yml | 15 ++------------- package.json | 2 +- 5 files changed, 11 insertions(+), 39 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 587169c5330..9e282530d50 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,5 +1,7 @@ root: true - +env: + es6: true + node: true rules: eol-last: error eqeqeq: [error, allow-null] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80248fab691..2a143eed638 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,11 +11,7 @@ jobs: 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.0 - Node.js 4.x - Node.js 5.x - Node.js 6.x @@ -29,25 +25,9 @@ jobs: - Node.js 14.x include: - - name: Node.js 0.10 - node-version: "0.10" - npm-i: mocha@3.5.3 supertest@2.0.0 - - - name: Node.js 0.12 - node-version: "0.12" - npm-i: mocha@3.5.3 supertest@2.0.0 - - - name: io.js 1.x - node-version: "1.8" - npm-i: mocha@3.5.3 supertest@2.0.0 - - - name: io.js 2.x - node-version: "2.5" - npm-i: mocha@3.5.3 supertest@2.0.0 - - - name: io.js 3.x - node-version: "3.3" - npm-i: mocha@3.5.3 supertest@2.0.0 + - name: Node.js 4.0 + node-version: "4.0" + npm-i: mocha@5.2.0 supertest@3.4.2 - name: Node.js 4.x node-version: "4.9" diff --git a/History.md b/History.md index 66f59388ebc..c12379180e0 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ This incorporates all changes after 4.17.1 up to 4.17.2. * change: - query parser setting defaults to `'simple'` + - Requires Node.js 4+ - Use `mime-types` for file to content type mapping * deps: array-flatten@3.0.0 * deps: body-parser@2.0.0-beta.1 diff --git a/appveyor.yml b/appveyor.yml index 785c799e8fe..433729652b6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,10 +1,5 @@ environment: matrix: - - nodejs_version: "0.10" - - nodejs_version: "0.12" - - nodejs_version: "1.8" - - nodejs_version: "2.5" - - nodejs_version: "3.3" - nodejs_version: "4.9" - nodejs_version: "5.12" - nodejs_version: "6.17" @@ -38,14 +33,11 @@ install: # Setup Node.js version-specific dependencies - ps: | # mocha for testing - # - use 3.x for Node.js < 4 # - 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 - 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) { + if ([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 @@ -56,11 +48,8 @@ install: } - ps: | # supertest for http calls - # - use 2.0.0 for Node.js < 4 # - use 3.4.2 for Node.js < 6 - 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) { + if ([int]$env:nodejs_version.split(".")[0] -lt 6) { npm install --silent --save-dev supertest@3.4.2 } # Update Node.js modules diff --git a/package.json b/package.json index 85ecc68011b..214263c3f91 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "vhost": "~3.0.2" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 4" }, "files": [ "LICENSE", From 620df0e35e447d39c7f2b9e9909fa1a793851be7 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 8 Feb 2022 09:55:19 -0500 Subject: [PATCH 056/256] deps: serve-static@2.0.0-beta.1 --- History.md | 5 +++++ package.json | 2 +- test/express.static.js | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index c12379180e0..495c903a7c6 100644 --- a/History.md +++ b/History.md @@ -24,6 +24,11 @@ This incorporates all changes after 4.17.1 up to 4.17.2. - deps: parseurl@~1.3.3 - deps: path-to-regexp@3.2.0 - deps: setprototypeof@1.2.0 + * deps: serve-static@2.0.0-beta.1 + - Change `dotfiles` option default to `'ignore'` + - Remove `hidden` option; use `dotfiles` option instead + - Use `mime-types` for file to content type mapping + - deps: send@1.0.0-beta.1 5.0.0-alpha.8 / 2020-03-25 ========================== diff --git a/package.json b/package.json index 214263c3f91..008627d6367 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "router": "2.0.0-beta.1", "safe-buffer": "5.2.1", "send": "0.17.2", - "serve-static": "1.14.2", + "serve-static": "2.0.0-beta.1", "setprototypeof": "1.2.0", "statuses": "~1.5.0", "type-is": "~1.6.18", diff --git a/test/express.static.js b/test/express.static.js index 56d3657bff0..e130a0861ef 100644 --- a/test/express.static.js +++ b/test/express.static.js @@ -40,7 +40,7 @@ describe('express.static()', function () { it('should set Content-Type', function (done) { request(this.app) .get('/todo.txt') - .expect('Content-Type', 'text/plain; charset=UTF-8') + .expect('Content-Type', 'text/plain; charset=utf-8') .expect(200, done) }) From 669c8056154a70d1dd4e29eae9a211df745ba803 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 8 Feb 2022 09:57:29 -0500 Subject: [PATCH 057/256] deps: send@1.0.0-beta.1 --- History.md | 5 +++++ package.json | 2 +- test/res.download.js | 10 +++++----- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index 495c903a7c6..0eb74e885cf 100644 --- a/History.md +++ b/History.md @@ -24,6 +24,11 @@ This incorporates all changes after 4.17.1 up to 4.17.2. - deps: parseurl@~1.3.3 - deps: path-to-regexp@3.2.0 - deps: setprototypeof@1.2.0 + * deps: send@1.0.0-beta.1 + - Change `dotfiles` option default to `'ignore'` + - Remove `hidden` option; use `dotfiles` option instead + - Use `mime-types` for file to content type mapping + - deps: debug@3.1.0 * deps: serve-static@2.0.0-beta.1 - Change `dotfiles` option default to `'ignore'` - Remove `hidden` option; use `dotfiles` option instead diff --git a/package.json b/package.json index 008627d6367..eb0a44a14dc 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "range-parser": "~1.2.1", "router": "2.0.0-beta.1", "safe-buffer": "5.2.1", - "send": "0.17.2", + "send": "1.0.0-beta.1", "serve-static": "2.0.0-beta.1", "setprototypeof": "1.2.0", "statuses": "~1.5.0", diff --git a/test/res.download.js b/test/res.download.js index cf3b3ca53e1..4f3de6fd969 100644 --- a/test/res.download.js +++ b/test/res.download.js @@ -16,7 +16,7 @@ describe('res', function(){ request(app) .get('/') - .expect('Content-Type', 'text/html; charset=UTF-8') + .expect('Content-Type', 'text/html; charset=utf-8') .expect('Content-Disposition', 'attachment; filename="user.html"') .expect(200, '

{{user.name}}

', done) }) @@ -32,7 +32,7 @@ describe('res', function(){ request(app) .get('/') - .expect('Content-Type', 'text/html; charset=UTF-8') + .expect('Content-Type', 'text/html; charset=utf-8') .expect('Content-Disposition', 'attachment; filename="document"') .expect(200, done) }) @@ -49,7 +49,7 @@ describe('res', function(){ request(app) .get('/') - .expect('Content-Type', 'text/html; charset=UTF-8') + .expect('Content-Type', 'text/html; charset=utf-8') .expect('Content-Disposition', 'attachment; filename="user.html"') .expect(200, cb); }) @@ -66,7 +66,7 @@ describe('res', function(){ request(app) .get('/') - .expect('Content-Type', 'text/html; charset=UTF-8') + .expect('Content-Type', 'text/html; charset=utf-8') .expect('Content-Disposition', 'attachment; filename="document"') .expect(200, cb); }) @@ -85,7 +85,7 @@ describe('res', function(){ request(app) .get('/') .expect(200) - .expect('Content-Type', 'text/html; charset=UTF-8') + .expect('Content-Type', 'text/html; charset=utf-8') .expect('Content-Disposition', 'attachment; filename="document"') .end(cb) }) From 5213bd9fe78a0c414966a79846ad58df413e754d Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Tue, 8 Feb 2022 18:55:09 -0500 Subject: [PATCH 058/256] docs: fix entry in history --- History.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/History.md b/History.md index 0eb74e885cf..c9735c8916b 100644 --- a/History.md +++ b/History.md @@ -4,7 +4,7 @@ This incorporates all changes after 4.17.1 up to 4.17.2. * change: - - query parser setting defaults to `'simple'` + - Default "query parser" setting to `'simple'` - Requires Node.js 4+ - Use `mime-types` for file to content type mapping * deps: array-flatten@3.0.0 From 6faf26d59f00637e5c09c1d320df966ee28349ad Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Mon, 14 Feb 2022 19:13:14 -0500 Subject: [PATCH 059/256] 5.0.0-beta.1 --- History.md | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index c9735c8916b..d89efef4e67 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,8 @@ -5.x -=== +5.0.0-beta.1 / 2022-02-14 +========================= -This incorporates all changes after 4.17.1 up to 4.17.2. +This is the first Express 5.0 beta release, based off 4.17.2 and includes +changes from 5.0.0-alpha.8. * change: - Default "query parser" setting to `'simple'` diff --git a/package.json b/package.json index eb0a44a14dc..e22f640d57b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.0.0-alpha.8", + "version": "5.0.0-beta.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 060/256] 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 061/256] 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 062/256] 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 063/256] 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 064/256] 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 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 065/256] 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 066/256] 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 14439731f968c1ec6015227d747ede32d3fbf676 Mon Sep 17 00:00:00 2001 From: Evan Hahn Date: Thu, 17 Mar 2022 12:34:13 -0500 Subject: [PATCH 067/256] 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 068/256] 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 ee40a881f5d8cb4ce71bc45262fde8e4b7640d05 Mon Sep 17 00:00:00 2001 From: Wes Date: Mon, 20 Feb 2017 17:36:39 -0600 Subject: [PATCH 069/256] 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 088856c3f82d5101d2831db8516e1ec991eb426a Mon Sep 17 00:00:00 2001 From: ctcpip Date: Thu, 25 Jul 2024 12:30:07 -0500 Subject: [PATCH 070/256] =?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 723b5451bbcbab69bc8ded50ccd6545a79b8fe64 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Tue, 30 Jul 2024 17:49:13 -0400 Subject: [PATCH 071/256] 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 072/256] 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 073/256] 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 074/256] =?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 075/256] 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 076/256] 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 077/256] 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 078/256] 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 0b243b1aee0d8774f2b97da2e8ac4340adaed1b3 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Fri, 23 Aug 2024 22:37:27 +0200 Subject: [PATCH 079/256] 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 65b62065d2b4308212fc3b19ab4986a9fa10ca41 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Fri, 23 Aug 2024 16:07:45 -0500 Subject: [PATCH 080/256] 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 081/256] 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 082/256] 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 083/256] 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 084/256] 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 085/256] 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 086/256] 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 087/256] 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 4d713d2b767e13bfbd4f91f4dc9fd442e9896bcd Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 9 Sep 2024 18:03:32 -0400 Subject: [PATCH 088/256] 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 089/256] 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 6c98f80b6ac95b90cff5da6857be4fe21d5e9c4e Mon Sep 17 00:00:00 2001 From: ctcpip Date: Mon, 9 Sep 2024 21:32:49 -0500 Subject: [PATCH 090/256] =?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 091/256] 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 092/256] 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 093/256] 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 094/256] 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 095/256] 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 096/256] 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 097/256] 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 098/256] 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 099/256] 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 100/256] 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 101/256] 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 102/256] 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 103/256] 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 104/256] 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 105/256] 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 106/256] 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 107/256] 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 108/256] 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 109/256] 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 110/256] 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 111/256] 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 112/256] 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 113/256] 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 114/256] 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 115/256] 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 116/256] 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 117/256] 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 118/256] 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 119/256] 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 120/256] 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 121/256] 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 122/256] 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 123/256] 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 124/256] 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 125/256] 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 126/256] 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 127/256] 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 128/256] 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 129/256] 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 130/256] 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 131/256] 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 132/256] 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 133/256] 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 134/256] 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 135/256] 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 136/256] 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 137/256] 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 138/256] 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 139/256] 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 140/256] 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 141/256] 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 142/256] 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 143/256] 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 144/256] 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 145/256] 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 146/256] 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 147/256] 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 148/256] 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 149/256] 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 150/256] 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 151/256] 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 152/256] 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 153/256] 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 154/256] 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 155/256] 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 156/256] 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 157/256] 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 158/256] 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 159/256] 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 160/256] 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 161/256] 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 162/256] 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 163/256] 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 164/256] 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 165/256] 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 166/256] 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 167/256] 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 168/256] 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 169/256] 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 170/256] 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 171/256] 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 172/256] 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 173/256] 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 174/256] 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 175/256] 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 176/256] 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 177/256] 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 178/256] 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 179/256] =?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 180/256] 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 181/256] 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 182/256] 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 183/256] 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 184/256] 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 185/256] 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 186/256] 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 187/256] 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 188/256] 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 189/256] 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 190/256] 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 191/256] 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 192/256] 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 193/256] 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 194/256] 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 195/256] 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 196/256] 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 197/256] 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 198/256] 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 199/256] 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 200/256] 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 201/256] 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 202/256] 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 203/256] 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 204/256] 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 205/256] 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 206/256] 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 207/256] 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 From 2551a7d8afd82e41b9282bd0235190a847a59f44 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Tue, 18 Nov 2025 10:42:56 +0100 Subject: [PATCH 208/256] docs: switch badges from badgen.net to shields.io (#6900) --- Readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index d62b9821250..bdafdda90eb 100644 --- a/Readme.md +++ b/Readme.md @@ -261,14 +261,14 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) [MIT](LICENSE) -[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/express/master +[coveralls-image]: https://img.shields.io/coverallsCoverage/github/expressjs/express?branch=master [coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master -[github-actions-ci-image]: https://badgen.net/github/checks/expressjs/express/master?label=CI +[github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/expressjs/express/ci.yml?branch=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-image]: https://img.shields.io/npm/dm/express [npm-downloads-url]: https://npmcharts.com/compare/express?minimal=true [npm-url]: https://npmjs.org/package/express -[npm-version-image]: https://badgen.net/npm/v/express +[npm-version-image]: https://img.shields.io/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/.github/blob/HEAD/CODE_OF_CONDUCT.md From 54af593b739ea44674e4a445efa15b8024f093da Mon Sep 17 00:00:00 2001 From: TheMysterious <48478887+Tacit1@users.noreply.github.com> Date: Mon, 24 Nov 2025 04:52:16 +0500 Subject: [PATCH 209/256] refactor: use cached slice in app.listen (#6897) Signed-off-by: Tacit1 --- lib/application.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/application.js b/lib/application.js index cf6d78c741e..838b882aaae 100644 --- a/lib/application.js +++ b/lib/application.js @@ -597,7 +597,7 @@ app.render = function render(name, options, callback) { app.listen = function listen() { var server = http.createServer(this) - var args = Array.prototype.slice.call(arguments) + var args = 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) From f33caf1f89a028f0ea98ff5a156a68e65a2eabdd Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 24 Nov 2025 22:32:28 -0500 Subject: [PATCH 210/256] Nominate to @efekrskl for triage team (#6888) * Nominate to @efekrskl for triage team * Update Readme.md --- Readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index bdafdda90eb..c2729766d24 100644 --- a/Readme.md +++ b/Readme.md @@ -214,7 +214,8 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [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) +* [rxmarbles](https://github.com/rxmarbles) - **Rick Markins** (He/him) +* [efekrskl](https://github.com/efekrskl) - **Efe Karasakal**
Triagers emeriti members From 77bcd5274a87047e5b3fe2f17f6c342db3909c53 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Tue, 25 Nov 2025 05:32:32 -0500 Subject: [PATCH 211/256] docs: update emeritus triagers (#6890) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: update emeritus triagers --------- Co-authored-by: Ulises Gascón --- Readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index c2729766d24..4c5b6f757f4 100644 --- a/Readme.md +++ b/Readme.md @@ -208,15 +208,12 @@ 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) -* [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** -* [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger** -* [rxmarbles](https://github.com/rxmarbles) - **Rick Markins** (He/him) * [efekrskl](https://github.com/efekrskl) - **Efe Karasakal** +
Triagers emeriti members @@ -254,6 +251,9 @@ 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** + * [dpopp07](https://github.com/dpopp07) - **Dustin Popp** + * [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger** + * [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi**
From 758d4355d45322b4c8cd347ebcefbf3b154c7e7f Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 26 Nov 2025 19:49:57 +0530 Subject: [PATCH 212/256] deps: body-parser@^2.2.1 (#6922) Includes the security patch for CVE-2025-13466 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 5b6cba51ed8..44914404760 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +UNRELEASED +======================= + +* deps: `body-parser@^2.2.1` + 5.1.0 / 2025-03-31 ======================== diff --git a/package.json b/package.json index db7661de46d..5492eb215e9 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ ], "dependencies": { "accepts": "^2.0.0", - "body-parser": "^2.2.0", + "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", From 30bae810279b2ea162bed5b14ce6c35a110a87f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:12:08 +0100 Subject: [PATCH 213/256] build(deps): bump coverallsapp/github-action from 2.3.6 to 2.3.7 (#6930) Bumps [coverallsapp/github-action](https://github.com/coverallsapp/github-action) from 2.3.6 to 2.3.7. - [Release notes](https://github.com/coverallsapp/github-action/releases) - [Commits](https://github.com/coverallsapp/github-action/compare/648a8eb78e6d50909eff900e4ec85cab4524a45b...5cbfd81b66ca5d10c19b062c04de0199c215fb6e) --- updated-dependencies: - dependency-name: coverallsapp/github-action dependency-version: 2.3.7 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/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 dab7815960c..a801d8faf48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,6 +112,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@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6 + uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7 with: file: ./lcov.info diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 1df70694732..2c56108973e 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -96,6 +96,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@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6 + uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7 with: file: ./lcov.info From 8eace4603cb2547608578a4fbb259dc984216f71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:12:52 +0100 Subject: [PATCH 214/256] build(deps): bump github/codeql-action from 4.31.2 to 4.31.6 (#6929) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.2 to 4.31.6. - [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/0499de31b99561a6d14a36a5f662c2a54f91beee...fe4161a26a8629af62121b670040955b330f9af2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.6 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 1ac121c027f..31a9f32663a 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@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5 + uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # 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@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5 + uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 9cbd54487d8..4128cc3b954 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@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5 + uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 with: sarif_file: results.sarif From ed0ba3f1dc905d6b62eabf23bd383abcae4901ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:13:45 +0100 Subject: [PATCH 215/256] build(deps): bump actions/checkout from 5.0.0 to 6.0.0 (#6928) Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 6.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/08c6903cd8c0fde910a37f88322edcfb5dd907a8...1af3b93b6815bc44a9784bd300feb67ff0d1eeb3) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.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 a801d8faf48..69240c41658 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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false - name: Setup Node.js @@ -53,7 +53,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false @@ -93,7 +93,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 31a9f32663a..eeca7329246 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 2c56108973e..5a784c018f6 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -37,7 +37,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false @@ -77,7 +77,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 4128cc3b954..c6e36f28e05 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,7 +32,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false From 2f64f68c37c64ae333e41ff38032d21860f22255 Mon Sep 17 00:00:00 2001 From: Chris de Almeida Date: Mon, 1 Dec 2025 10:12:41 -0600 Subject: [PATCH 216/256] sec: security patch for CVE-2024-51999 --- lib/utils.js | 2 +- test/req.query.js | 91 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 4f21e7ef1e3..4b227f0057c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -266,6 +266,6 @@ function createETagGenerator (options) { function parseExtendedQueryString(str) { return qs.parse(str, { - allowPrototypes: true + plainObjects: true }); } diff --git a/test/req.query.js b/test/req.query.js index c0d3c8376e9..176dc991b5a 100644 --- a/test/req.query.js +++ b/test/req.query.js @@ -3,6 +3,7 @@ var assert = require('node:assert') var express = require('../') , request = require('supertest'); +var qs = require('qs'); describe('req', function(){ describe('.query', function(){ @@ -38,6 +39,22 @@ describe('req', function(){ .get('/?user.name=tj') .expect(200, '{"user.name":"tj"}', done); }); + + it('should not be able to access object prototype properties', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?foo=yee') + .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); + }); + + it('should be able to use object prototype property names as keys', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?hasOwnProperty=yee') + .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); + }); }); describe('when "query parser" is simple', function () { @@ -48,6 +65,22 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"user[name]":"tj"}', done); }); + + it('should not be able to access object prototype properties', function (done) { + var app = createApp('simple', true); + + request(app) + .get('/?foo=yee') + .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); + }); + + it('should be able to use object prototype property names as keys', function (done) { + var app = createApp('simple', true); + + request(app) + .get('/?hasOwnProperty=yee') + .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); + }); }); describe('when "query parser" is a function', function () { @@ -60,6 +93,18 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"length":17}', done); }); + + // test exists to verify behavior for folks wishing to workaround our qs defaults + it('should drop object prototype property names and be able to access object prototype properties', function (done) { + var app = createApp( + function (str) { + return qs.parse(str) + }, true); + + request(app) + .get('/?hasOwnProperty=biscuits') + .expect(200, '{"query":{},"hasOwnProperty":false}', done); + }); }); describe('when "query parser" disabled', function () { @@ -70,6 +115,22 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{}', done); }); + + it('should not be able to access object prototype properties', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?foo=yee') + .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); + }); + + it('should be able to use object prototype property names as keys', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?hasOwnProperty=yee') + .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); + }); }); describe('when "query parser" enabled', function () { @@ -80,6 +141,22 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"user[name]":"tj"}', done); }); + + it('should not be able to access object prototype properties', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?foo=yee') + .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); + }); + + it('should be able to use object prototype property names as keys', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?hasOwnProperty=yee') + .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); + }); }); describe('when "query parser" an unknown value', function () { @@ -91,7 +168,7 @@ describe('req', function(){ }) }) -function createApp(setting) { +function createApp(setting, isPrototypePropertyTest) { var app = express(); if (setting !== undefined) { @@ -99,7 +176,17 @@ function createApp(setting) { } app.use(function (req, res) { - res.send(req.query); + if(isPrototypePropertyTest) { + try { + var hasOwnProperty = req.query.hasOwnProperty('✨ express ✨'); + res.send({ query: req.query, hasOwnProperty: hasOwnProperty }); + } catch (error) { + res.send({ query: req.query, error: error.toString() }); + } + } + else { + res.send(req.query); + } }); return app; From 4007ad103ba29f6426b2ec9eccfb1ceb792682a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Mon, 1 Dec 2025 17:17:31 +0100 Subject: [PATCH 217/256] Release: 5.2.0 (#6920) --- History.md | 6 ++++-- package.json | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 44914404760..287a8522d63 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,9 @@ -UNRELEASED -======================= +5.2.0 / 2025-12-01 +======================== +* Security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6)) * deps: `body-parser@^2.2.1` +* A deprecation warning was added when using `res.redirect` with undefined arguments, Express now emits a warning to help detect calls that pass undefined as the status or URL and make them easier to fix. 5.1.0 / 2025-03-31 ======================== diff --git a/package.json b/package.json index 5492eb215e9..ade9ed9d6af 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.1.0", + "version": "5.2.0", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 697547cde621d8b0a47b4fff6e98b29337f8c980 Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Mon, 1 Dec 2025 19:33:09 +0100 Subject: [PATCH 218/256] Revert "sec: security patch for CVE-2024-51999" This reverts commit 2f64f68c37c64ae333e41ff38032d21860f22255. --- lib/utils.js | 2 +- test/req.query.js | 91 ++--------------------------------------------- 2 files changed, 3 insertions(+), 90 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 4b227f0057c..4f21e7ef1e3 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -266,6 +266,6 @@ function createETagGenerator (options) { function parseExtendedQueryString(str) { return qs.parse(str, { - plainObjects: true + allowPrototypes: true }); } diff --git a/test/req.query.js b/test/req.query.js index 176dc991b5a..c0d3c8376e9 100644 --- a/test/req.query.js +++ b/test/req.query.js @@ -3,7 +3,6 @@ var assert = require('node:assert') var express = require('../') , request = require('supertest'); -var qs = require('qs'); describe('req', function(){ describe('.query', function(){ @@ -39,22 +38,6 @@ describe('req', function(){ .get('/?user.name=tj') .expect(200, '{"user.name":"tj"}', done); }); - - it('should not be able to access object prototype properties', function (done) { - var app = createApp('extended', true); - - request(app) - .get('/?foo=yee') - .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); - }); - - it('should be able to use object prototype property names as keys', function (done) { - var app = createApp('extended', true); - - request(app) - .get('/?hasOwnProperty=yee') - .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); - }); }); describe('when "query parser" is simple', function () { @@ -65,22 +48,6 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"user[name]":"tj"}', done); }); - - it('should not be able to access object prototype properties', function (done) { - var app = createApp('simple', true); - - request(app) - .get('/?foo=yee') - .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); - }); - - it('should be able to use object prototype property names as keys', function (done) { - var app = createApp('simple', true); - - request(app) - .get('/?hasOwnProperty=yee') - .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); - }); }); describe('when "query parser" is a function', function () { @@ -93,18 +60,6 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"length":17}', done); }); - - // test exists to verify behavior for folks wishing to workaround our qs defaults - it('should drop object prototype property names and be able to access object prototype properties', function (done) { - var app = createApp( - function (str) { - return qs.parse(str) - }, true); - - request(app) - .get('/?hasOwnProperty=biscuits') - .expect(200, '{"query":{},"hasOwnProperty":false}', done); - }); }); describe('when "query parser" disabled', function () { @@ -115,22 +70,6 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{}', done); }); - - it('should not be able to access object prototype properties', function (done) { - var app = createApp('extended', true); - - request(app) - .get('/?foo=yee') - .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); - }); - - it('should be able to use object prototype property names as keys', function (done) { - var app = createApp('extended', true); - - request(app) - .get('/?hasOwnProperty=yee') - .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); - }); }); describe('when "query parser" enabled', function () { @@ -141,22 +80,6 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"user[name]":"tj"}', done); }); - - it('should not be able to access object prototype properties', function (done) { - var app = createApp('extended', true); - - request(app) - .get('/?foo=yee') - .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); - }); - - it('should be able to use object prototype property names as keys', function (done) { - var app = createApp('extended', true); - - request(app) - .get('/?hasOwnProperty=yee') - .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); - }); }); describe('when "query parser" an unknown value', function () { @@ -168,7 +91,7 @@ describe('req', function(){ }) }) -function createApp(setting, isPrototypePropertyTest) { +function createApp(setting) { var app = express(); if (setting !== undefined) { @@ -176,17 +99,7 @@ function createApp(setting, isPrototypePropertyTest) { } app.use(function (req, res) { - if(isPrototypePropertyTest) { - try { - var hasOwnProperty = req.query.hasOwnProperty('✨ express ✨'); - res.send({ query: req.query, hasOwnProperty: hasOwnProperty }); - } catch (error) { - res.send({ query: req.query, error: error.toString() }); - } - } - else { - res.send(req.query); - } + res.send(req.query); }); return app; From dbac741a49a5a64336b70c06e85c2e2706e36336 Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Mon, 1 Dec 2025 19:35:03 +0100 Subject: [PATCH 219/256] 5.2.1 --- History.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 287a8522d63..57128776594 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +5.2.1 / 2025-12-01 +======================= + +* Revert security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6)) + 5.2.0 / 2025-12-01 ======================== diff --git a/package.json b/package.json index ade9ed9d6af..8f358830d97 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", - "version": "5.2.0", + "version": "5.2.1", "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", From 9eb700151b688c5d6c9c26b8194220b45dbf12ce Mon Sep 17 00:00:00 2001 From: ctcpip Date: Wed, 3 Dec 2025 16:08:09 -0600 Subject: [PATCH 220/256] =?UTF-8?q?=F0=9F=93=9D=20add=20note=20to=20histor?= =?UTF-8?q?y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History.md | 1 + 1 file changed, 1 insertion(+) diff --git a/History.md b/History.md index 57128776594..facdf5b7ab2 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ ======================= * Revert security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6)) + * The prior release (5.2.0) included an erroneous breaking change related to the extended query parser. There is no actual security vulnerability associated with this behavior (CVE-2024-51999 has been rejected). The change has been fully reverted in this release. 5.2.0 / 2025-12-01 ======================== From c2fb76e99f7379b706a5510b4b2dd08a1b710b7b Mon Sep 17 00:00:00 2001 From: Rick Markins Date: Fri, 19 Dec 2025 02:44:49 -0700 Subject: [PATCH 221/256] docs: add @rxmarbles to triagers (#6953) --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 4c5b6f757f4..9719bcd3e15 100644 --- a/Readme.md +++ b/Readme.md @@ -212,6 +212,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him) * [Phillip9587](https://github.com/Phillip9587) - **Phillip Barta** * [efekrskl](https://github.com/efekrskl) - **Efe Karasakal** +* [rxmarbles](https://github.com/rxmarbles) - **Rick Markins** (he/him)
From b8fc000f3116237b2bcc0df41b5b999f95da37ae Mon Sep 17 00:00:00 2001 From: Ulises Gascon Date: Fri, 13 Jun 2025 11:29:27 +0200 Subject: [PATCH 222/256] docs: use global Security policy We should inherit https://github.com/expressjs/.github/blob/master/SECURITY.md directly. --- SECURITY.md | 56 ----------------------------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index ff106d62104..00000000000 --- a/SECURITY.md +++ /dev/null @@ -1,56 +0,0 @@ -# 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) - * [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 `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 -link or an attachment. - -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 -announcement, and may ask for additional information or guidance. - -Report security bugs in third-party modules to the person or team maintaining -the module. - -## Pre-release Versions - -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 guaranteed that any fixes will be released in the next pre-release. - -## 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. - -## 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/docs/ThreatModel.md) - -## Comments on this Policy - -If you have suggestions on how this process could be improved please submit a -pull request. From b5aae87594502d543e8ac393847a6f091e9b8321 Mon Sep 17 00:00:00 2001 From: Jon Church Date: Mon, 5 Jan 2026 17:51:23 -0500 Subject: [PATCH 223/256] doc: fix security.md link to point to security tab --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 9719bcd3e15..9dd1725c285 100644 --- a/Readme.md +++ b/Readme.md @@ -154,7 +154,7 @@ See the [Contributing Guide] 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](https://github.com/expressjs/express?tab=security-ov-file). ### Running Tests From 3e81873b52e107898ed7ba45874959fb0546df3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:38:53 -0500 Subject: [PATCH 224/256] build(deps): bump actions/download-artifact from 6.0.0 to 7.0.0 (#6961) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6.0.0 to 7.0.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/018cc2cf5baa6db3ef3c5f8a56943fffe632ef53...37930b1c2abaa49bbe596cd826c3c89aef350131) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 7.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 69240c41658..6e474a623cf 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@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: path: ./coverage pattern: coverage-node-* diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 5a784c018f6..307385ee57e 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@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: path: ./coverage pattern: coverage-node-* From 6cd404eb28ff861180f435b3015f8d0c8c0b44d4 Mon Sep 17 00:00:00 2001 From: AbdelMonaam Aouini <52112750+Abdel-Monaam-Aouini@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:41:34 +0100 Subject: [PATCH 225/256] fix: enhance req.acceptsCharsets method (#6088) * fix: enhance req.acceptsCharsets method * Update req.acceptsCharsets.js --------- Co-authored-by: Monaam Aouini Co-authored-by: Sebastian Beltran --- lib/request.js | 31 ++++++++++++++++++++++++------- test/req.acceptsCharsets.js | 13 +++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/lib/request.js b/lib/request.js index 69990da39b6..9f517721c3e 100644 --- a/lib/request.js +++ b/lib/request.js @@ -147,17 +147,34 @@ req.acceptsEncodings = function(){ }; /** - * Check if the given `charset`s are acceptable, - * otherwise you should respond with 406 "Not Acceptable". + * Checks if the specified `charset`s are acceptable based on the request's `Accept-Charset` header. + * Returns the best matching charset or an array of acceptable charsets. * - * @param {String} ...charset - * @return {String|Array} + * The `charset` argument(s) can be: + * - A single charset string (e.g., "utf-8") + * - Multiple charset strings as arguments (e.g., `"utf-8", "iso-8859-1"`) + * - A comma-delimited list of charsets (e.g., `"utf-8, iso-8859-1"`) + * + * Examples: + * + * // Accept-Charset: utf-8, iso-8859-1 + * req.acceptsCharsets('utf-8'); + * // => "utf-8" + * + * req.acceptsCharsets('utf-8', 'iso-8859-1'); + * // => "utf-8" + * + * req.acceptsCharsets('utf-8, utf-16'); + * // => "utf-8" + * + * @param {...String} charsets - The charset(s) to check against the `Accept-Charset` header. + * @return {String|Array} - The best matching charset, or an array of acceptable charsets. * @public */ -req.acceptsCharsets = function(){ - var accept = accepts(this); - return accept.charsets.apply(accept, arguments); +req.acceptsCharsets = function(...charsets) { + const accept = accepts(this); + return accept.charsets(...charsets); }; /** diff --git a/test/req.acceptsCharsets.js b/test/req.acceptsCharsets.js index 360a9878a78..2df68ae1097 100644 --- a/test/req.acceptsCharsets.js +++ b/test/req.acceptsCharsets.js @@ -45,6 +45,19 @@ describe('req', function(){ .set('Accept-Charset', 'foo, bar') .expect('no', done); }) + + it('should return the best matching charset from multiple inputs', function (done) { + var app = express(); + + app.use(function(req, res, next){ + res.end(req.acceptsCharsets('utf-8', 'iso-8859-1')); + }); + + request(app) + .get('/') + .set('Accept-Charset', 'iso-8859-1, utf-8') + .expect('iso-8859-1', done); + }) }) }) }) From 4ae96bdf5e981fab914237120d6df8aa98f8c5ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:45:47 -0500 Subject: [PATCH 226/256] build(deps): bump actions/upload-artifact from 5.0.0 to 6.0.0 (#6965) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/330a01c490aca151604b8cf639adc76d48f6c5d4...b7c566a772e6b6bfb58ed0dc250532a479d7789f) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 6.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 +- .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 6e474a623cf..e0a5d595f64 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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.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 307385ee57e..5bff77df2b0 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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.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 c6e36f28e05..623ffacdbce 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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: SARIF file path: results.sarif From 3c0ad4e8dcae078dcd73c7118eeca3b1de485415 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:46:20 -0500 Subject: [PATCH 227/256] build(deps): bump github/codeql-action from 4.31.6 to 4.31.9 (#6964) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.6 to 4.31.9. - [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/fe4161a26a8629af62121b670040955b330f9af2...5d4e8d1aca955e8d8589aabd499c5cae939e33c7) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.9 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 eeca7329246..6950e5bcaac 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@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 + uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # 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@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 + uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 623ffacdbce..71980b13700 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@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5 + uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5 with: sarif_file: results.sarif From 00bb633ca6d1970e02d9ea893384efa155f15513 Mon Sep 17 00:00:00 2001 From: Gabriel Alves Date: Wed, 7 Jan 2026 11:46:37 -0300 Subject: [PATCH 228/256] deps: qs@^6.14.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f358830d97..aa2afbcb543 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", - "qs": "^6.14.0", + "qs": "^6.14.1", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", From bc7d155f53ef6457140dc2070b0b959869dd36da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:47:41 -0500 Subject: [PATCH 229/256] build(deps): bump actions/checkout from 6.0.0 to 6.0.1 (#6963) Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1. - [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/1af3b93b6815bc44a9784bd300feb67ff0d1eeb3...8e8c483db84b4bee98b60c0593521ed34d9990e8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.1 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/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 e0a5d595f64..7dcc4904e67 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Setup Node.js @@ -53,7 +53,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -93,7 +93,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6950e5bcaac..b080ea25b38 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 5bff77df2b0..4920c2b43fa 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -37,7 +37,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -77,7 +77,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 71980b13700..28b34e01196 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,7 +32,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false From 04d3a4997607f78afacd3ed6e5f0145336c4fe39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:48:47 -0500 Subject: [PATCH 230/256] build(deps): bump actions/setup-node from 6.0.0 to 6.1.0 (#6962) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.0.0 to 6.1.0. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/2028fbc5c25fe9cf00d9f06a71cc4710d4507903...395ad3262231945c25e8478fd5baf05154b1d79f) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 6.1.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 7dcc4904e67..7a9797e098e 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@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version: 'lts/*' @@ -58,7 +58,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 4920c2b43fa..e31f55e363e 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@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version: ${{ matrix.node-version }} From 2cd372e34cd6613f4d00836c2ee122f28bddfcb3 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 12 Jan 2026 04:28:54 -0500 Subject: [PATCH 231/256] docs: add @krzysdz to the triage team (#6482) --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 9dd1725c285..e7649d5b9b2 100644 --- a/Readme.md +++ b/Readme.md @@ -213,7 +213,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [Phillip9587](https://github.com/Phillip9587) - **Phillip Barta** * [efekrskl](https://github.com/efekrskl) - **Efe Karasakal** * [rxmarbles](https://github.com/rxmarbles) - **Rick Markins** (he/him) - +* [krzysdz](https://github.com/krzysdz)
Triagers emeriti members From 9a3f7ff4120d7920a2d13809ff5ae78648c8a3d6 Mon Sep 17 00:00:00 2001 From: Bernice Wu <78245731+Bernice55231@users.noreply.github.com> Date: Fri, 16 Jan 2026 23:29:01 +0800 Subject: [PATCH 232/256] Polish HTML structure of the response in the res.redirect() function (#5167) * structure the DOM body * structure the DOM body * test: add html title to redirect test * fix: update HTML structure for include body and head tags * docs: improve HTML structure in res.redirect() responses for better browser compatibility --------- Co-authored-by: Sebastian Beltran --- History.md | 6 ++++++ lib/response.js | 3 ++- test/res.redirect.js | 8 ++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/History.md b/History.md index facdf5b7ab2..689c08a9fe9 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +# Unreleased Changes + +## 🚀 Improvements + +- Improve HTML structure in `res.redirect()` responses when HTML format is accepted by adding ``, ``, and `<body>` tags for better browser compatibility - by [@Bernice55231](https://github.com/Bernice55231) in [#5167](https://github.com/expressjs/express/pull/5167) + 5.2.1 / 2025-12-01 ======================= diff --git a/lib/response.js b/lib/response.js index 7a2f0ecce56..731afb7846f 100644 --- a/lib/response.js +++ b/lib/response.js @@ -850,7 +850,8 @@ res.redirect = function redirect(url) { html: function(){ var u = escapeHtml(address); - body = '<p>' + statuses.message[status] + '. Redirecting to ' + u + '</p>' + body = '<!DOCTYPE html><head><title>' + statuses.message[status] + '' + + '

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

' }, default: function(){ diff --git a/test/res.redirect.js b/test/res.redirect.js index 264e0f2b8f3..8d2b164e4a2 100644 --- a/test/res.redirect.js +++ b/test/res.redirect.js @@ -91,7 +91,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

Found. Redirecting to http://google.com

', done) }) it('should escape the url', function(done){ @@ -107,7 +107,7 @@ 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

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

', done) }) it('should not render evil javascript links in anchor href (prevent XSS)', function(done){ @@ -125,7 +125,7 @@ describe('res', function(){ .set('Accept', 'text/html') .expect('Content-Type', /html/) .expect('Location', encodedXss) - .expect(302, '

Found. Redirecting to ' + encodedXss +'

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

Found. Redirecting to ' + encodedXss +'

', done); }); it('should include the redirect type', function(done){ @@ -140,7 +140,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

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

', done); }) }) From ae265a90c7f6534231b621a846be6c60c54658f5 Mon Sep 17 00:00:00 2001 From: Marcos Molina Date: Fri, 16 Jan 2026 23:19:39 +0200 Subject: [PATCH 233/256] docs: fix JSDoc for req.accepts() return value and parameter format (#6936) * fixed request accept jsdoc * reverted format * reverted format * updated jsdoc * updated the rest of the documentation --- lib/request.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/request.js b/lib/request.js index 9f517721c3e..e7a451df6d9 100644 --- a/lib/request.js +++ b/lib/request.js @@ -83,16 +83,13 @@ req.header = function header(name) { }; /** - * To do: update docs. - * * Check if the given `type(s)` is acceptable, returning - * the best match when true, otherwise `undefined`, in which + * the best match when true, otherwise `false`, in which * case you should respond with 406 "Not Acceptable". * * The `type` value may be a single MIME type string * such as "application/json", an extension name - * such as "json", a comma-delimited list such as "json, html, text/plain", - * an argument list such as `"json", "html", "text/plain"`, + * such as "json", an argument list such as `"json", "html", "text/plain"`, * or an array `["json", "html", "text/plain"]`. When a list * or array is given, the _best_ match, if any is returned. * @@ -107,7 +104,7 @@ req.header = function header(name) { * // => "html" * req.accepts('text/html'); * // => "text/html" - * req.accepts('json, text'); + * req.accepts('json', 'text'); * // => "json" * req.accepts('application/json'); * // => "application/json" @@ -115,12 +112,11 @@ req.header = function header(name) { * // Accept: text/*, application/json * req.accepts('image/png'); * req.accepts('png'); - * // => undefined + * // => false * * // Accept: text/*;q=.5, application/json * req.accepts(['html', 'json']); * req.accepts('html', 'json'); - * req.accepts('html, json'); * // => "json" * * @param {String|Array} type(s) From 912893c07cac79cc0b761f3a0c1061b8e8cde87e Mon Sep 17 00:00:00 2001 From: sukdev24 Date: Sat, 17 Jan 2026 03:27:22 +0100 Subject: [PATCH 234/256] test: added unit tests for utils.compileETag to cover valid and invalid inputs (#6534) * Added unit tests for utils.compileETag to cover valid and invalid inputs * test: enhance compileETag tests for various input types --------- Co-authored-by: sucem029 Co-authored-by: Sebastian Beltran --- test/utils.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/utils.js b/test/utils.js index 1c06036aa98..fbbf9fff89f 100644 --- a/test/utils.js +++ b/test/utils.js @@ -81,3 +81,28 @@ describe('utils.wetag(body, encoding)', function(){ 'W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"') }) }) + +describe('utils.compileETag()', function () { + it('should return generateETag for true', function () { + const fn = utils.compileETag(true); + assert.strictEqual(fn('express!'), utils.wetag('express!')); + }); + + it('should return undefined for false', function () { + assert.strictEqual(utils.compileETag(false), undefined); + }); + + it('should return generateETag for string values "strong" and "weak"', function () { + assert.strictEqual(utils.compileETag('strong')("express"), utils.etag("express")); + assert.strictEqual(utils.compileETag('weak')("express"), utils.wetag("express")); + }); + + it('should throw for unknown string values', function () { + assert.throws(() => utils.compileETag('foo'), TypeError); + }); + + it('should throw for unsupported types like arrays and objects', function () { + assert.throws(() => utils.compileETag([]), TypeError); + assert.throws(() => utils.compileETag({}), TypeError); + }); +}); From 5a4568abfe05f71d5559e1db9321627af501ebe3 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sat, 17 Jan 2026 17:36:22 -0500 Subject: [PATCH 235/256] chore: remove benchmarks directory (#6992) --- benchmarks/Makefile | 17 ----------------- benchmarks/README.md | 34 ---------------------------------- benchmarks/middleware.js | 20 -------------------- benchmarks/run | 18 ------------------ 4 files changed, 89 deletions(-) delete mode 100644 benchmarks/Makefile delete mode 100644 benchmarks/README.md delete mode 100644 benchmarks/middleware.js delete mode 100755 benchmarks/run diff --git a/benchmarks/Makefile b/benchmarks/Makefile deleted file mode 100644 index ed1ddfc4f34..00000000000 --- a/benchmarks/Makefile +++ /dev/null @@ -1,17 +0,0 @@ - -all: - @./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/README.md b/benchmarks/README.md deleted file mode 100644 index 1894c527d63..00000000000 --- a/benchmarks/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# 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`. diff --git a/benchmarks/middleware.js b/benchmarks/middleware.js deleted file mode 100644 index fed97ba8ce4..00000000000 --- a/benchmarks/middleware.js +++ /dev/null @@ -1,20 +0,0 @@ - -var express = require('..'); -var app = express(); - -// number of middleware - -var n = parseInt(process.env.MW || '1', 10); -console.log(' %s middleware', n); - -while (n--) { - app.use(function(req, res, next){ - next(); - }); -} - -app.use(function(req, res){ - res.send('Hello World') -}); - -app.listen(3333); diff --git a/benchmarks/run b/benchmarks/run deleted file mode 100755 index ec8f55d5643..00000000000 --- a/benchmarks/run +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -echo -MW=$1 node $2 & -pid=$! - -echo " $3 connections" - -sleep 2 - -wrk 'http://localhost:3333/?foo[bar]=baz' \ - -d 3 \ - -c $3 \ - -t 8 \ - | grep 'Requests/sec\|Latency' \ - | awk '{ print " " $2 }' - -kill $pid From a479419b16f5b97eb20f5dbae5848708ff30ce2d Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Mon, 19 Jan 2026 09:56:53 -0500 Subject: [PATCH 236/256] feat: do not modify the Content-Type twice when sending strings (#6991) * fix: improve content-type handling in res.send method * fix: ensure content-type is a string before setting charset in res.send * fix: refactor content-type handling in res.send to use const and improve clarity * Apply suggestion from @bjohansebas * docs: update History.md --- History.md | 6 +++++- lib/response.js | 19 ++++++------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/History.md b/History.md index 689c08a9fe9..0c5334c17e9 100644 --- a/History.md +++ b/History.md @@ -2,7 +2,11 @@ ## 🚀 Improvements -- Improve HTML structure in `res.redirect()` responses when HTML format is accepted by adding ``, ``, and `<body>` tags for better browser compatibility - by [@Bernice55231](https://github.com/Bernice55231) in [#5167](https://github.com/expressjs/express/pull/5167) +* Improve HTML structure in `res.redirect()` responses when HTML format is accepted by adding `<!DOCTYPE html>`, `<title>`, and `<body>` tags for better browser compatibility - by [@Bernice55231](https://github.com/Bernice55231) in [#5167](https://github.com/expressjs/express/pull/5167) + +## ⚡ Performance + +* Avoid duplicate Content-Type header processing in `res.send()` when sending string responses without an explicit Content-Type header - by [@bjohansebas](https://github.com/bjohansebas) in [#6991](https://github.com/expressjs/express/pull/6991) 5.2.1 / 2025-12-01 ======================= diff --git a/lib/response.js b/lib/response.js index 731afb7846f..f965e539dd2 100644 --- a/lib/response.js +++ b/lib/response.js @@ -126,7 +126,6 @@ res.send = function send(body) { var chunk = body; var encoding; var req = this.req; - var type; // settings var app = this.app; @@ -134,7 +133,12 @@ res.send = function send(body) { switch (typeof chunk) { // string defaulting to html case 'string': - if (!this.get('Content-Type')) { + encoding = 'utf8'; + const type = this.get('Content-Type'); + + if (typeof type === 'string') { + this.set('Content-Type', setCharset(type, 'utf-8')); + } else { this.type('html'); } break; @@ -153,17 +157,6 @@ res.send = function send(body) { break; } - // write strings in utf-8 - if (typeof chunk === 'string') { - encoding = 'utf8'; - type = this.get('Content-Type'); - - // reflect this in content-type - if (typeof type === 'string') { - this.set('Content-Type', setCharset(type, 'utf-8')); - } - } - // determine if ETag should be generated var etagFn = app.get('etag fn') var generateETag = !this.get('ETag') && typeof etagFn === 'function' From c9ecf7b658388ccaa2b8470aabad92aabde458a2 Mon Sep 17 00:00:00 2001 From: AkaHarshit <104684660+AkaHarshit@users.noreply.github.com> Date: Sun, 1 Feb 2026 08:21:17 +0530 Subject: [PATCH 237/256] feat: Allow passing null or undefined as the value for options in app.render (#6903) * fix: allow null options in app.render * fix: ensure options are initialized to an empty object in app.render * docs: add history entry --------- Co-authored-by: Sebastian Beltran <bjohansebas@gmail.com> --- History.md | 6 ++++++ lib/application.js | 2 +- test/app.render.js | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 0c5334c17e9..571cd0e47c5 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,12 @@ * Improve HTML structure in `res.redirect()` responses when HTML format is accepted by adding `<!DOCTYPE html>`, `<title>`, and `<body>` tags for better browser compatibility - by [@Bernice55231](https://github.com/Bernice55231) in [#5167](https://github.com/expressjs/express/pull/5167) +* When calling `app.render` with options set to null, the locals object is handled correctly, preventing unexpected errors and making the method behave the same as when options is omitted or an empty object is passed - by [AkaHarshit](https://github.com/AkaHarshit) in [#6903](https://github.com/expressjs/express/pull/6903) + + ```js + app.render('index', null, callback); // now works as expected + ``` + ## ⚡ Performance * Avoid duplicate Content-Type header processing in `res.send()` when sending string responses without an explicit Content-Type header - by [@bjohansebas](https://github.com/bjohansebas) in [#6991](https://github.com/expressjs/express/pull/6991) diff --git a/lib/application.js b/lib/application.js index 838b882aaae..47be2a20c1a 100644 --- a/lib/application.js +++ b/lib/application.js @@ -523,7 +523,7 @@ app.render = function render(name, options, callback) { var cache = this.cache; var done = callback; var engines = this.engines; - var opts = options; + var opts = options || {}; var view; // support callback function as second arg diff --git a/test/app.render.js b/test/app.render.js index ca15e761d35..bd65ce1035b 100644 --- a/test/app.render.js +++ b/test/app.render.js @@ -331,6 +331,24 @@ describe('app', function(){ }) }) + it('should accept null or undefined options', function (done) { + var app = createApp() + + app.set('views', path.join(__dirname, 'fixtures')) + app.locals.user = { name: 'tobi' } + + app.render('user.tmpl', null, function (err, str) { + if (err) return done(err); + assert.strictEqual(str, '<p>tobi</p>') + + app.render('user.tmpl', undefined, function (err2, str2) { + if (err2) return done(err2); + assert.strictEqual(str2, '<p>tobi</p>') + done() + }) + }) + }) + describe('caching', function(){ it('should cache with cache option', function(done){ var app = express(); From 6b7ccfcf120e77f20aa22ff96ccf98a994c7d35b Mon Sep 17 00:00:00 2001 From: Ayoub Mabrouk <77799760+Ayoub-Mabrouk@users.noreply.github.com> Date: Sun, 1 Feb 2026 03:53:38 +0100 Subject: [PATCH 238/256] test: add test for normalizeType fallback when mime lookup fails (#6894) Add test to verify that utils.normalizeType correctly defaults to 'application/octet-stream' when mime.lookup() returns null/undefined for unknown file extensions. This covers the fallback behavior on line 64 of lib/utils.js and ensures proper handling of unrecognized MIME types. Co-authored-by: bjohansebas <103585995+bjohansebas@users.noreply.github.com> --- test/utils.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/utils.js b/test/utils.js index fbbf9fff89f..d1174d014cf 100644 --- a/test/utils.js +++ b/test/utils.js @@ -35,8 +35,15 @@ describe('utils.normalizeType acceptParams method', () => { params: {} // No parameters are added since "invalid" has no "=" }); }); -}); + it('should default to application/octet-stream when mime lookup fails', () => { + const result = utils.normalizeType('unknown-extension-xyz'); + assert.deepEqual(result, { + value: 'application/octet-stream', + params: {} + }); + }); +}); describe('utils.setCharset(type, charset)', function () { it('should do anything without type', function () { From d12772393c8249666e0fcc11e298f48ce4632a11 Mon Sep 17 00:00:00 2001 From: Viny Brun Kriesang <viniciusbrun.dev@gmail.com> Date: Sun, 1 Feb 2026 03:12:23 +0000 Subject: [PATCH 239/256] fix: search example to support Redis v4+ and Express 4/5 (#6274) * Fix Redis example to support Redis v4+ and Express 4/5 * update optional route syntax to /{:query} and refactor Redis initialization into dedicated function to guarantee that it is complete before server starts --------- Co-authored-by: Sebastian Beltran <bjohansebas@gmail.com> --- examples/search/index.js | 60 +++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/examples/search/index.js b/examples/search/index.js index 951e0d440a6..b995b8fab16 100644 --- a/examples/search/index.js +++ b/examples/search/index.js @@ -16,31 +16,47 @@ var path = require('node:path'); var redis = require('redis'); var db = redis.createClient(); +var app = express(); + +app.use(express.static(path.join(__dirname, 'public'))); // npm install redis -var app = express(); +/** + * Redis Initialization + */ -app.use(express.static(path.join(__dirname, 'public'))); +async function initializeRedis() { + try { + // connect to Redis -// populate search + await db.connect(); -db.sadd('ferret', 'tobi'); -db.sadd('ferret', 'loki'); -db.sadd('ferret', 'jane'); -db.sadd('cat', 'manny'); -db.sadd('cat', 'luna'); + // populate search + + await db.sAdd('ferret', 'tobi'); + await db.sAdd('ferret', 'loki'); + await db.sAdd('ferret', 'jane'); + await db.sAdd('cat', 'manny'); + await db.sAdd('cat', 'luna'); + } catch (err) { + console.error('Error initializing Redis:', err); + process.exit(1); + } +} /** * GET search for :query. */ -app.get('/search/:query?', function(req, res, next){ - var query = req.params.query; - db.smembers(query, function(err, vals){ - if (err) return next(err); - res.send(vals); - }); +app.get('/search/{:query}', function (req, res, next) { + var query = req.params.query || ''; + db.sMembers(query) + .then((vals) => res.send(vals)) + .catch((err) => { + console.error(`Redis error for query "${query}":`, err); + next(err); + }); }); /** @@ -54,8 +70,14 @@ app.get('/client.js', function(req, res){ res.sendFile(path.join(__dirname, 'client.js')); }); -/* istanbul ignore next */ -if (!module.parent) { - app.listen(3000); - console.log('Express started on port 3000'); -} +/** + * Start the Server + */ + +(async () => { + await initializeRedis(); + if (!module.parent) { + app.listen(3000); + console.log('Express started on port 3000'); + } +})(); From 66404b347a1690c0b783f47a8cf04a37caea8de5 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran <bjohansebas@gmail.com> Date: Sun, 1 Feb 2026 07:04:08 -0500 Subject: [PATCH 240/256] docs: Add @GroophyLifefor to the triage team (#6995) --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index e7649d5b9b2..eedd4c69046 100644 --- a/Readme.md +++ b/Readme.md @@ -214,6 +214,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [efekrskl](https://github.com/efekrskl) - **Efe Karasakal** * [rxmarbles](https://github.com/rxmarbles) - **Rick Markins** (he/him) * [krzysdz](https://github.com/krzysdz) +* [GroophyLifefor](https://github.com/GroophyLifefor) - **Murat Kirazkaya** <details> <summary>Triagers emeriti members</summary> From 2d4192ebb325315c6dd7bb2743ea65a7eb30a049 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 00:04:00 +0100 Subject: [PATCH 241/256] build(deps): bump actions/checkout from 6.0.1 to 6.0.2 (#7011) Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2. - [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/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> 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 7a9797e098e..d4e7eb7b1e9 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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Setup Node.js @@ -53,7 +53,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -93,7 +93,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b080ea25b38..060f0f6904f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index e31f55e363e..ae127e3951e 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -37,7 +37,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -77,7 +77,7 @@ jobs: contents: read checks: write steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 28b34e01196..546f1ee582e 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,7 +32,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false From c76ed5ae05a0b4174374482a6534ce96023597bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 00:05:17 +0100 Subject: [PATCH 242/256] build(deps): bump actions/setup-node from 6.1.0 to 6.2.0 (#7012) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.1.0 to 6.2.0. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/395ad3262231945c25e8478fd5baf05154b1d79f...6044e13b5dc448c55e2357c09f80417699197238) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 6.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> 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 d4e7eb7b1e9..75ec50fe7a7 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@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: node-version: 'lts/*' @@ -58,7 +58,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index ae127e3951e..78fdb2e9019 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@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: node-version: ${{ matrix.node-version }} From 1140301f6a0ed5a05bc1ef38d48294f75a49580c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 00:10:13 +0100 Subject: [PATCH 243/256] build(deps): bump github/codeql-action from 4.31.9 to 4.32.0 (#7013) * build(deps): bump github/codeql-action from 4.31.9 to 4.32.0 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.9 to 4.32.0. - [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/5d4e8d1aca955e8d8589aabd499c5cae939e33c7...b20883b0cd1f46c72ae0ba6d1090936928f9fa30) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.32.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix version tag comments --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Phillip Barta <barta.phillip@gmail.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 060f0f6904f..ce96039dc9a 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@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5 + uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 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@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5 + uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 546f1ee582e..1aba84c6916 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@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5 + uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: sarif_file: results.sarif From 9c85a25c02e83ad16e1561d02c8ede652f0ef15b Mon Sep 17 00:00:00 2001 From: Murat Kirazkaya <77299279+GroophyLifefor@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:25:36 +0300 Subject: [PATCH 244/256] Remove duplicate tests in res.location and res.jsonp (#6996) * test: remove duplicated tests * test: fix typo in data URI encoding test description --- test/res.jsonp.js | 14 -------------- test/res.location.js | 14 +------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/test/res.jsonp.js b/test/res.jsonp.js index c1f90f11092..e043a3b07f2 100644 --- a/test/res.jsonp.js +++ b/test/res.jsonp.js @@ -327,18 +327,4 @@ describe('res', function(){ }) }) }) - - it('should not override previous Content-Types', function(done){ - var app = express(); - - app.get('/', function(req, res){ - res.type('application/vnd.example+json'); - res.jsonp({ hello: 'world' }); - }); - - request(app) - .get('/') - .expect('content-type', 'application/vnd.example+json; charset=utf-8') - .expect(200, '{"hello":"world"}', done) - }) }) diff --git a/test/res.location.js b/test/res.location.js index b81c6f07d8d..a5ceed76279 100644 --- a/test/res.location.js +++ b/test/res.location.js @@ -46,19 +46,7 @@ describe('res', function(){ .expect(200, done) }) - it('should encode data uri1', 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 uri2', function (done) { + it('should encode data uri', function (done) { var app = express() app.use(function (req, res) { res.location('data:text/javascript,export default () => { }').end(); From 925a1dff1e42f1b393c977b8b77757fcf633e09f Mon Sep 17 00:00:00 2001 From: Dave Tashner <5702882+davetashner@users.noreply.github.com> Date: Sat, 21 Feb 2026 22:11:08 -0500 Subject: [PATCH 245/256] fix: bump qs minimum to ^6.14.2 for CVE-2026-2391 (#7057) qs versions before 6.14.2 have an arrayLimit bypass in comma parsing that allows denial of service (GHSA-w7fw-mjwx-w883). While the existing ^6.14.1 semver range allows 6.14.2 on fresh installs, bumping the minimum ensures the vulnerable version cannot be resolved. Signed-off-by: davetashner <5702882+davetashner@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aa2afbcb543..8c9efb5609d 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", - "qs": "^6.14.1", + "qs": "^6.14.2", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", From c4cc78bdf55ae657536239aad2077425f7d79045 Mon Sep 17 00:00:00 2001 From: Pavan Shinde <pavann97@gmail.com> Date: Sun, 22 Feb 2026 08:45:11 +0530 Subject: [PATCH 246/256] docs: fix README security policy link (#7029) --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index eedd4c69046..57dbc367aee 100644 --- a/Readme.md +++ b/Readme.md @@ -154,7 +154,7 @@ See the [Contributing Guide] for more technical details on contributing. ### Security Issues -If you discover a security vulnerability in Express, please see [Security Policies and Procedures](https://github.com/expressjs/express?tab=security-ov-file). +If you discover a security vulnerability in Express, please see [Security Policies and Procedures](https://github.com/expressjs/express/security/policy). ### Running Tests From b4ab7d65d7724d9309b6faaaf82ad492da2a6d35 Mon Sep 17 00:00:00 2001 From: Ishita Singh <127220309+IshitaSingh0822@users.noreply.github.com> Date: Mon, 23 Feb 2026 15:28:26 +0530 Subject: [PATCH 247/256] test: include edge case tests for `res.type()` (#7037) --- test/res.type.js | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/test/res.type.js b/test/res.type.js index 09285af3914..e438956313a 100644 --- a/test/res.type.js +++ b/test/res.type.js @@ -42,5 +42,74 @@ describe('res', function(){ .get('/') .expect('Content-Type', 'application/vnd.amazon.ebook', done); }) + + describe('edge cases', function(){ + it('should handle empty string gracefully', function(done){ + var app = express(); + + app.use(function(req, res){ + res.type('').end('test'); + }); + + request(app) + .get('/') + .expect('Content-Type', 'application/octet-stream') + .end(done); + }) + + it('should handle file extension with dots', function(done){ + var app = express(); + + app.use(function(req, res){ + res.type('.json').end('{"test": true}'); + }); + + request(app) + .get('/') + .expect('Content-Type', 'application/json; charset=utf-8') + .end(done); + }) + + it('should handle multiple file extensions', function(done){ + var app = express(); + + app.use(function(req, res){ + res.type('file.tar.gz').end('compressed'); + }); + + request(app) + .get('/') + .expect('Content-Type', 'application/gzip') + .end(done); + }) + + it('should handle uppercase extensions', function(done){ + var app = express(); + + app.use(function(req, res){ + res.type('FILE.JSON').end('{"test": true}'); + }); + + request(app) + .get('/') + .expect('Content-Type', 'application/json; charset=utf-8') + .end(done); + }) + + it('should handle extension with special characters', function(done){ + var app = express(); + + app.use(function(req, res){ + res.type('file@test.json').end('{"test": true}'); + }); + + request(app) + .get('/') + .expect('Content-Type', 'application/json; charset=utf-8') + .end(done); + }) + }) }) }) + + From 411061d94e7180343ebf1c86afd30dfb8746cbe7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:21:45 +0100 Subject: [PATCH 248/256] build(deps): bump github/codeql-action from 4.32.0 to 4.32.4 (#7072) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.0 to 4.32.4. - [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/b20883b0cd1f46c72ae0ba6d1090936928f9fa30...89a39a4e59826350b863aa6b6252a07ad50cf83e) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.32.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> 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 ce96039dc9a..b74c4363c45 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@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 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@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 1aba84c6916..a8462ce4aed 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@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: sarif_file: results.sarif From e3b962c558cc1c24fb69da285f42c3aa0c1c1da2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:23:27 +0100 Subject: [PATCH 249/256] build(deps): bump actions/download-artifact from 7.0.0 to 8.0.0 (#7073) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7.0.0 to 8.0.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/37930b1c2abaa49bbe596cd826c3c89aef350131...70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 8.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> 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 75ec50fe7a7..9405bb08155 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@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: path: ./coverage pattern: coverage-node-* diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 78fdb2e9019..9a5f93ff20b 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@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: path: ./coverage pattern: coverage-node-* From 06e2367f91490f241e8932b56ffda042ec0debb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:24:13 +0100 Subject: [PATCH 250/256] build(deps): bump actions/upload-artifact from 6.0.0 to 7.0.0 (#7074) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/b7c566a772e6b6bfb58ed0dc250532a479d7789f...bbbca2ddaa5d8feaa63e36b76fdaad77386f024f) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> 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 9405bb08155..41036559082 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@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.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 9a5f93ff20b..a66fb48d3b1 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@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.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 a8462ce4aed..884d0e3ee93 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@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: SARIF file path: results.sarif From 6c4249feec8ab40631817c8e7001baf2ed022224 Mon Sep 17 00:00:00 2001 From: Sam Tucker-Davis <126325182+stuckvgn@users.noreply.github.com> Date: Sun, 1 Mar 2026 13:55:02 +0000 Subject: [PATCH 251/256] docs: replace dummy with placeholder in example comments (#7064) * docs: replace 'dummy' with 'placeholder' in example comments Use more inclusive language in code comments across example files. The term 'dummy' can be replaced with the clearer, more neutral term 'placeholder' without any change in meaning. Files changed: - examples/ejs/index.js - examples/route-middleware/index.js - examples/auth/index.js * ci: re-trigger coverage after transient coveralls.io error --------- Co-authored-by: stuckvgn <stuckvgn@users.noreply.github.com> --- examples/auth/index.js | 2 +- examples/ejs/index.js | 2 +- examples/route-middleware/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/auth/index.js b/examples/auth/index.js index 40b73e6de16..7c4a572f9d3 100644 --- a/examples/auth/index.js +++ b/examples/auth/index.js @@ -38,7 +38,7 @@ app.use(function(req, res, next){ next(); }); -// dummy database +// placeholder database var users = { tj: { name: 'tj' } diff --git a/examples/ejs/index.js b/examples/ejs/index.js index 0940d0624fb..05b451b664b 100644 --- a/examples/ejs/index.js +++ b/examples/ejs/index.js @@ -35,7 +35,7 @@ app.use(express.static(path.join(__dirname, 'public'))); // ex: res.render('users.html'). app.set('view engine', 'html'); -// Dummy users +// Placeholder users var users = [ { name: 'tobi', email: 'tobi@learnboost.com' }, { name: 'loki', email: 'loki@learnboost.com' }, diff --git a/examples/route-middleware/index.js b/examples/route-middleware/index.js index 44ec13a95b8..66df511347b 100644 --- a/examples/route-middleware/index.js +++ b/examples/route-middleware/index.js @@ -15,7 +15,7 @@ var app = express(); // curl http://localhost:3000/user/1/edit (unauthorized since this is not you) // curl -X DELETE http://localhost:3000/user/0 (unauthorized since you are not an admin) -// Dummy users +// Placeholder users var users = [ { id: 0, name: 'tj', email: 'tj@vision-media.ca', role: 'member' } , { id: 1, name: 'ciaran', email: 'ciaranj@gmail.com', role: 'member' } From e5099198b292a565f8583d70caf12d7afed3607f Mon Sep 17 00:00:00 2001 From: Ayush Shukla <Ayush.Shukla@adypu.edu.in> Date: Tue, 31 Mar 2026 10:09:23 +0530 Subject: [PATCH 252/256] docs: remove dead link from Readme (#7136) * docs: remove dead link for import-brain * Update Readme.md Co-authored-by: krzysdz <12915102+krzysdz@users.noreply.github.com> --------- Co-authored-by: Sebastian Beltran <bjohansebas@gmail.com> Co-authored-by: krzysdz <12915102+krzysdz@users.noreply.github.com> --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 57dbc367aee..74f5fbcd264 100644 --- a/Readme.md +++ b/Readme.md @@ -249,7 +249,7 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj) * [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) + * [ejcheng](https://github.com/ejcheng)- **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 8e022edc9185f540a3fcecaf5e56b850d919cdac Mon Sep 17 00:00:00 2001 From: Vansh Sharma <s.vansh1811@gmail.com> Date: Tue, 7 Apr 2026 02:28:04 +0530 Subject: [PATCH 253/256] docs: update npm install docs URL in Readme.md (#7159) The link for the npm install command pointed to the old/broken URL path (/getting-started/installing-npm-packages-locally). Updated to the current correct URL (/downloading-and-installing-packages-locally). --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 74f5fbcd264..3fb257a8d4a 100644 --- a/Readme.md +++ b/Readme.md @@ -57,7 +57,7 @@ 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). Installation is done using the -[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): +[`npm install` command](https://docs.npmjs.com/downloading-and-installing-packages-locally): ```bash npm install express From e7fd63a3878596154dd0693e92a8e5e41a45647c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 19:48:35 +0200 Subject: [PATCH 254/256] build(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 (#7148) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 8.0.0 to 8.0.1. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 8.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> 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 41036559082..1fd75fab12c 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@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: ./coverage pattern: coverage-node-* diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index a66fb48d3b1..4cb60f857b4 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@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: ./coverage pattern: coverage-node-* From 8cc3afa8e35e1a62ccf48276d456278455eb784d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 19:49:19 +0200 Subject: [PATCH 255/256] build(deps): bump actions/setup-node from 6.2.0 to 6.3.0 (#7149) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/6044e13b5dc448c55e2357c09f80417699197238...53b83947a5a98c8d113130e565377fae1a50d02f) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 6.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> 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 1fd75fab12c..3c9ad9cc12e 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@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 'lts/*' @@ -58,7 +58,7 @@ jobs: persist-credentials: false - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 4cb60f857b4..145a08178a7 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@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} From 6340c1eaaedc0ddcae8be8df2cdb1d2e961cbf2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 19:50:02 +0200 Subject: [PATCH 256/256] build(deps): bump github/codeql-action from 4.32.4 to 4.35.1 (#7150) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.4 to 4.35.1. - [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/89a39a4e59826350b863aa6b6252a07ad50cf83e...c10b8064de6f491fea524254123dbe5e09572f13) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.35.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> 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 b74c4363c45..3530bbb0bc9 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@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 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@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 884d0e3ee93..3658736ea9d 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@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: sarif_file: results.sarif