diff --git a/History.md b/History.md index fcb2fa5069..63efe1234f 100644 --- a/History.md +++ b/History.md @@ -1,11 +1,26 @@ 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 * 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 +* deps: cookie-signature@^1.2.1 +* deps: debug@4.3.6 +* deps: merge-descriptors@^2.0.0 +* 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` +* 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/examples/downloads/index.js b/examples/downloads/index.js index 5e48ac3970..c47dddd738 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 ff1f6fe11f..627ab24c5a 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 5d48381111..a471a4b091 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/lib/request.js b/lib/request.js index c528186aa1..372a9915e9 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/lib/response.js b/lib/response.js index b9b27097ae..4035d4fb06 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 f6ec0b0f65..0367f40337 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,7 @@ { "name": "express", "description": "Fast, unopinionated, minimalist web framework", -<<<<<<< HEAD "version": "5.0.0-beta.3", -======= - "version": "4.20.0", ->>>>>>> master "author": "TJ Holowaychuk ", "contributors": [ "Aaron Heckmann ", @@ -32,37 +28,36 @@ "api" ], "dependencies": { - "accepts": "~1.3.8", + "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.0.6", - "debug": "3.1.0", + "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", - "finalhandler": "1.2.0", - "fresh": "0.5.2", + "finalhandler": "^2.0.0", + "fresh": "2.0.0", "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", + "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", - "path-is-absolute": "1.0.1", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "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-beta.2", - "serve-static": "2.0.0-beta.2", + "send": "^1.0.0", + "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" }, diff --git a/test/app.all.js b/test/app.all.js index 185a8332fe..e4afca7d73 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 73957eabfa..11742d98a7 100644 --- a/test/app.router.js +++ b/test/app.router.js @@ -337,12 +337,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') @@ -353,12 +353,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') @@ -369,12 +369,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') @@ -404,11 +404,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]] })); @@ -631,8 +631,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) @@ -678,7 +678,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); }); @@ -691,7 +691,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); }); @@ -706,8 +706,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) @@ -718,8 +718,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) @@ -730,7 +730,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) }) @@ -744,8 +744,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) @@ -756,8 +756,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) @@ -768,7 +768,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) }) @@ -802,7 +802,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')); }); @@ -821,7 +821,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(); }); @@ -906,7 +906,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(); }); @@ -1117,7 +1117,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(); }); @@ -1137,7 +1137,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.fresh.js b/test/req.fresh.js index 9160e2caaf..3bf6a1f65a 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); + }) + }) }) diff --git a/test/req.route.js b/test/req.route.js index 6c17fbb1c8..9bd7ed923b 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) }) diff --git a/test/res.type.js b/test/res.type.js index 980717a6e3..09285af391 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) })