Use let or const to avoid scope issues and hoisting
var after = require('after');
1'use strict'23var after = require('after');4var express = require('../')5 , request = require('supertest')6 , assert = require('node:assert')7 , methods = require('../lib/utils').methods;89var shouldSkipQuery = require('./support/utils').shouldSkipQuery1011describe('app.router', function () {12 it('should restore req.params after leaving router', function (done) {13 var app = express();14 var router = new express.Router();1516 function handler1(req, res, next) {17 res.setHeader('x-user-id', String(req.params.id));18 next()19 }2021 function handler2(req, res) {22 res.send(req.params.id);23 }2425 router.use(function (req, res, next) {26 res.setHeader('x-router', String(req.params.id));27 next();28 });2930 app.get('/user/:id', handler1, router, handler2);3132 request(app)33 .get('/user/1')34 .expect('x-router', 'undefined')35 .expect('x-user-id', '1')36 .expect(200, '1', done);37 })3839 describe('methods', function () {40 methods.forEach(function (method) {41 if (method === 'connect') return;4243 it('should include ' + method.toUpperCase(), function (done) {44 if (method === 'query' && shouldSkipQuery(process.versions.node)) {45 this.skip()46 }47 var app = express();4849 app[method]('/foo', function (req, res) {50 res.send(method)51 });5253 request(app)54 [method]('/foo')55 .expect(200, done)56 })5758 it('should reject numbers for app.' + method, function () {59 var app = express();60 assert.throws(app[method].bind(app, '/', 3), /argument handler must be a function/);61 })62 });6364 it('should re-route when method is altered', function (done) {65 var app = express();66 var cb = after(3, done);6768 app.use(function (req, res, next) {69 if (req.method !== 'POST') return next();70 req.method = 'DELETE';71 res.setHeader('X-Method-Altered', '1');72 next();73 });7475 app.delete('/', function (req, res) {76 res.end('deleted everything');77 });7879 request(app)80 .get('/')81 .expect(404, cb)8283 request(app)84 .delete('/')85 .expect(200, 'deleted everything', cb);8687 request(app)88 .post('/')89 .expect('X-Method-Altered', '1')90 .expect(200, 'deleted everything', cb);91 });92 })9394 describe('decode params', function () {95 it('should decode correct params', function (done) {96 var app = express();9798 app.get('/:name', function (req, res) {99 res.send(req.params.name);100 });101102 request(app)103 .get('/foo%2Fbar')104 .expect('foo/bar', done);105 })106107 it('should not accept params in malformed paths', function (done) {108 var app = express();109110 app.get('/:name', function (req, res) {111 res.send(req.params.name);112 });113114 request(app)115 .get('/%foobar')116 .expect(400, done);117 })118119 it('should not decode spaces', function (done) {120 var app = express();121122 app.get('/:name', function (req, res) {123 res.send(req.params.name);124 });125126 request(app)127 .get('/foo+bar')128 .expect('foo+bar', done);129 })130131 it('should work with unicode', function (done) {132 var app = express();133134 app.get('/:name', function (req, res) {135 res.send(req.params.name);136 });137138 request(app)139 .get('/%ce%b1')140 .expect('\u03b1', done);141 })142 })143144 it('should be .use()able', function (done) {145 var app = express();146147 var calls = [];148149 app.use(function (req, res, next) {150 calls.push('before');151 next();152 });153154 app.get('/', function (req, res, next) {155 calls.push('GET /')156 next();157 });158159 app.use(function (req, res, next) {160 calls.push('after');161 res.json(calls)162 });163164 request(app)165 .get('/')166 .expect(200, ['before', 'GET /', 'after'], done)167 })168169 describe('when given a regexp', function () {170 it('should match the pathname only', function (done) {171 var app = express();172173 app.get(/^\/user\/[0-9]+$/, function (req, res) {174 res.end('user');175 });176177 request(app)178 .get('/user/12?foo=bar')179 .expect('user', done);180 })181182 it('should populate req.params with the captures', function (done) {183 var app = express();184185 app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function (req, res) {186 var id = req.params[0]187 , op = req.params[1];188 res.end(op + 'ing user ' + id);189 });190191 request(app)192 .get('/user/10/edit')193 .expect('editing user 10', done);194 })195196 if (supportsRegexp('(?<foo>.*)')) {197 it('should populate req.params with named captures', function (done) {198 var app = express();199 var re = new RegExp('^/user/(?<userId>[0-9]+)/(view|edit)?$');200201 app.get(re, function (req, res) {202 var id = req.params.userId203 , op = req.params[0];204 res.end(op + 'ing user ' + id);205 });206207 request(app)208 .get('/user/10/edit')209 .expect('editing user 10', done);210 })211 }212213 it('should ensure regexp matches path prefix', function (done) {214 var app = express()215 var p = []216217 app.use(/\/api.*/, function (req, res, next) {218 p.push('a')219 next()220 })221 app.use(/api/, function (req, res, next) {222 p.push('b')223 next()224 })225 app.use(/\/test/, function (req, res, next) {226 p.push('c')227 next()228 })229 app.use(function (req, res) {230 res.end()231 })232233 request(app)234 .get('/test/api/1234')235 .expect(200, function (err) {236 if (err) return done(err)237 assert.deepEqual(p, ['c'])238 done()239 })240 })241 })242243 describe('case sensitivity', function () {244 it('should be disabled by default', function (done) {245 var app = express();246247 app.get('/user', function (req, res) {248 res.end('tj');249 });250251 request(app)252 .get('/USER')253 .expect('tj', done);254 })255256 describe('when "case sensitive routing" is enabled', function () {257 it('should match identical casing', function (done) {258 var app = express();259260 app.enable('case sensitive routing');261262 app.get('/uSer', function (req, res) {263 res.end('tj');264 });265266 request(app)267 .get('/uSer')268 .expect('tj', done);269 })270271 it('should not match otherwise', function (done) {272 var app = express();273274 app.enable('case sensitive routing');275276 app.get('/uSer', function (req, res) {277 res.end('tj');278 });279280 request(app)281 .get('/user')282 .expect(404, done);283 })284 })285 })286287 describe('params', function () {288 it('should overwrite existing req.params by default', function (done) {289 var app = express();290 var router = new express.Router();291292 router.get('/:action', function (req, res) {293 res.send(req.params);294 });295296 app.use('/user/:user', router);297298 request(app)299 .get('/user/1/get')300 .expect(200, '{"action":"get"}', done);301 })302303 it('should allow merging existing req.params', function (done) {304 var app = express();305 var router = new express.Router({ mergeParams: true });306307 router.get('/:action', function (req, res) {308 var keys = Object.keys(req.params).sort();309 res.send(keys.map(function (k) { return [k, req.params[k]] }));310 });311312 app.use('/user/:user', router);313314 request(app)315 .get('/user/tj/get')316 .expect(200, '[["action","get"],["user","tj"]]', done);317 })318319 it('should use params from router', function (done) {320 var app = express();321 var router = new express.Router({ mergeParams: true });322323 router.get('/:thing', function (req, res) {324 var keys = Object.keys(req.params).sort();325 res.send(keys.map(function (k) { return [k, req.params[k]] }));326 });327328 app.use('/user/:thing', router);329330 request(app)331 .get('/user/tj/get')332 .expect(200, '[["thing","get"]]', done);333 })334335 it('should merge numeric indices req.params', function (done) {336 var app = express();337 var router = new express.Router({ mergeParams: true });338339 router.get(/^\/(.*)\.(.*)/, function (req, res) {340 var keys = Object.keys(req.params).sort();341 res.send(keys.map(function (k) { return [k, req.params[k]] }));342 });343344 app.use(/^\/user\/id:(\d+)/, router);345346 request(app)347 .get('/user/id:10/profile.json')348 .expect(200, '[["0","10"],["1","profile"],["2","json"]]', done);349 })350351 it('should merge numeric indices req.params when more in parent', function (done) {352 var app = express();353 var router = new express.Router({ mergeParams: true });354355 router.get(/\/(.*)/, function (req, res) {356 var keys = Object.keys(req.params).sort();357 res.send(keys.map(function (k) { return [k, req.params[k]] }));358 });359360 app.use(/^\/user\/id:(\d+)\/name:(\w+)/, router);361362 request(app)363 .get('/user/id:10/name:tj/profile')364 .expect(200, '[["0","10"],["1","tj"],["2","profile"]]', done);365 })366367 it('should merge numeric indices req.params when parent has same number', function (done) {368 var app = express();369 var router = new express.Router({ mergeParams: true });370371 router.get(/\/name:(\w+)/, function (req, res) {372 var keys = Object.keys(req.params).sort();373 res.send(keys.map(function (k) { return [k, req.params[k]] }));374 });375376 app.use(/\/user\/id:(\d+)/, router);377378 request(app)379 .get('/user/id:10/name:tj')380 .expect(200, '[["0","10"],["1","tj"]]', done);381 })382383 it('should ignore invalid incoming req.params', function (done) {384 var app = express();385 var router = new express.Router({ mergeParams: true });386387 router.get('/:name', function (req, res) {388 var keys = Object.keys(req.params).sort();389 res.send(keys.map(function (k) { return [k, req.params[k]] }));390 });391392 app.use('/user/', function (req, res, next) {393 req.params = 3; // wat?394 router(req, res, next);395 });396397 request(app)398 .get('/user/tj')399 .expect(200, '[["name","tj"]]', done);400 })401402 it('should restore req.params', function (done) {403 var app = express();404 var router = new express.Router({ mergeParams: true });405406 router.get(/\/user:(\w+)\//, function (req, res, next) {407 next();408 });409410 app.use(/\/user\/id:(\d+)/, function (req, res, next) {411 router(req, res, function (err) {412 var keys = Object.keys(req.params).sort();413 res.send(keys.map(function (k) { return [k, req.params[k]] }));414 });415 });416417 request(app)418 .get('/user/id:42/user:tj/profile')419 .expect(200, '[["0","42"]]', done);420 })421 })422423 describe('trailing slashes', function () {424 it('should be optional by default', function (done) {425 var app = express();426427 app.get('/user', function (req, res) {428 res.end('tj');429 });430431 request(app)432 .get('/user/')433 .expect('tj', done);434 })435436 describe('when "strict routing" is enabled', function () {437 it('should match trailing slashes', function (done) {438 var app = express();439440 app.enable('strict routing');441442 app.get('/user/', function (req, res) {443 res.end('tj');444 });445446 request(app)447 .get('/user/')448 .expect('tj', done);449 })450451 it('should pass-though middleware', function (done) {452 var app = express();453454 app.enable('strict routing');455456 app.use(function (req, res, next) {457 res.setHeader('x-middleware', 'true');458 next();459 });460461 app.get('/user/', function (req, res) {462 res.end('tj');463 });464465 request(app)466 .get('/user/')467 .expect('x-middleware', 'true')468 .expect(200, 'tj', done);469 })470471 it('should pass-though mounted middleware', function (done) {472 var app = express();473474 app.enable('strict routing');475476 app.use('/user/', function (req, res, next) {477 res.setHeader('x-middleware', 'true');478 next();479 });480481 app.get('/user/test/', function (req, res) {482 res.end('tj');483 });484485 request(app)486 .get('/user/test/')487 .expect('x-middleware', 'true')488 .expect(200, 'tj', done);489 })490491 it('should match no slashes', function (done) {492 var app = express();493494 app.enable('strict routing');495496 app.get('/user', function (req, res) {497 res.end('tj');498 });499500 request(app)501 .get('/user')502 .expect('tj', done);503 })504505 it('should match middleware when omitting the trailing slash', function (done) {506 var app = express();507508 app.enable('strict routing');509510 app.use('/user/', function (req, res) {511 res.end('tj');512 });513514 request(app)515 .get('/user')516 .expect(200, 'tj', done);517 })518519 it('should match middleware', function (done) {520 var app = express();521522 app.enable('strict routing');523524 app.use('/user', function (req, res) {525 res.end('tj');526 });527528 request(app)529 .get('/user')530 .expect(200, 'tj', done);531 })532533 it('should match middleware when adding the trailing slash', function (done) {534 var app = express();535536 app.enable('strict routing');537538 app.use('/user', function (req, res) {539 res.end('tj');540 });541542 request(app)543 .get('/user/')544 .expect(200, 'tj', done);545 })546547 it('should fail when omitting the trailing slash', function (done) {548 var app = express();549550 app.enable('strict routing');551552 app.get('/user/', function (req, res) {553 res.end('tj');554 });555556 request(app)557 .get('/user')558 .expect(404, done);559 })560561 it('should fail when adding the trailing slash', function (done) {562 var app = express();563564 app.enable('strict routing');565566 app.get('/user', function (req, res) {567 res.end('tj');568 });569570 request(app)571 .get('/user/')572 .expect(404, done);573 })574 })575 })576577 it('should allow literal "."', function (done) {578 var app = express();579580 app.get('/api/users/:from..:to', function (req, res) {581 var from = req.params.from582 , to = req.params.to;583584 res.end('users from ' + from + ' to ' + to);585 });586587 request(app)588 .get('/api/users/1..50')589 .expect('users from 1 to 50', done);590 })591592 describe(':name', function () {593 it('should denote a capture group', function (done) {594 var app = express();595596 app.get('/user/:user', function (req, res) {597 res.end(req.params.user);598 });599600 request(app)601 .get('/user/tj')602 .expect('tj', done);603 })604605 it('should match a single segment only', function (done) {606 var app = express();607608 app.get('/user/:user', function (req, res) {609 res.end(req.params.user);610 });611612 request(app)613 .get('/user/tj/edit')614 .expect(404, done);615 })616617 it('should allow several capture groups', function (done) {618 var app = express();619620 app.get('/user/:user/:op', function (req, res) {621 res.end(req.params.op + 'ing ' + req.params.user);622 });623624 request(app)625 .get('/user/tj/edit')626 .expect('editing tj', done);627 })628629 it('should work following a partial capture group', function (done) {630 var app = express();631 var cb = after(2, done);632633 app.get('/user{s}/:user/:op', function (req, res) {634 res.end(req.params.op + 'ing ' + req.params.user + (req.url.startsWith('/users') ? ' (old)' : ''));635 });636637 request(app)638 .get('/user/tj/edit')639 .expect('editing tj', cb);640641 request(app)642 .get('/users/tj/edit')643 .expect('editing tj (old)', cb);644 })645646 it('should work inside literal parenthesis', function (done) {647 var app = express();648649 app.get('/:user\\(:op\\)', function (req, res) {650 res.end(req.params.op + 'ing ' + req.params.user);651 });652653 request(app)654 .get('/tj(edit)')655 .expect('editing tj', done);656 })657658 it('should work in array of paths', function (done) {659 var app = express();660 var cb = after(2, done);661662 app.get(['/user/:user/poke', '/user/:user/pokes'], function (req, res) {663 res.end('poking ' + req.params.user);664 });665666 request(app)667 .get('/user/tj/poke')668 .expect('poking tj', cb);669670 request(app)671 .get('/user/tj/pokes')672 .expect('poking tj', cb);673 })674 })675676 describe(':name?', function () {677 it('should denote an optional capture group', function (done) {678 var app = express();679680 app.get('/user/:user{/:op}', function (req, res) {681 var op = req.params.op || 'view';682 res.end(op + 'ing ' + req.params.user);683 });684685 request(app)686 .get('/user/tj')687 .expect('viewing tj', done);688 })689690 it('should populate the capture group', function (done) {691 var app = express();692693 app.get('/user/:user{/:op}', function (req, res) {694 var op = req.params.op || 'view';695 res.end(op + 'ing ' + req.params.user);696 });697698 request(app)699 .get('/user/tj/edit')700 .expect('editing tj', done);701 })702 })703704 describe(':name*', function () {705 it('should match one segment', function (done) {706 var app = express()707708 app.get('/user/*user', function (req, res) {709 res.end(req.params.user[0])710 })711712 request(app)713 .get('/user/122')714 .expect('122', done)715 })716717 it('should match many segments', function (done) {718 var app = express()719720 app.get('/user/*user', function (req, res) {721 res.end(req.params.user.join('/'))722 })723724 request(app)725 .get('/user/1/2/3/4')726 .expect('1/2/3/4', done)727 })728729 it('should match zero segments', function (done) {730 var app = express()731732 app.get('/user{/*user}', function (req, res) {733 res.end(req.params.user)734 })735736 request(app)737 .get('/user')738 .expect('', done)739 })740 })741742 describe(':name+', function () {743 it('should match one segment', function (done) {744 var app = express()745746 app.get('/user/*user', function (req, res) {747 res.end(req.params.user[0])748 })749750 request(app)751 .get('/user/122')752 .expect(200, '122', done)753 })754755 it('should match many segments', function (done) {756 var app = express()757758 app.get('/user/*user', function (req, res) {759 res.end(req.params.user.join('/'))760 })761762 request(app)763 .get('/user/1/2/3/4')764 .expect(200, '1/2/3/4', done)765 })766767 it('should not match zero segments', function (done) {768 var app = express()769770 app.get('/user/*user', function (req, res) {771 res.end(req.params.user)772 })773774 request(app)775 .get('/user')776 .expect(404, done)777 })778 })779780 describe('.:name', function () {781 it('should denote a format', function (done) {782 var app = express();783 var cb = after(2, done)784785 app.get('/:name.:format', function (req, res) {786 res.end(req.params.name + ' as ' + req.params.format);787 });788789 request(app)790 .get('/foo.json')791 .expect(200, 'foo as json', cb)792793 request(app)794 .get('/foo')795 .expect(404, cb)796 })797 })798799 describe('.:name?', function () {800 it('should denote an optional format', function (done) {801 var app = express();802 var cb = after(2, done)803804 app.get('/:name{.:format}', function (req, res) {805 res.end(req.params.name + ' as ' + (req.params.format || 'html'));806 });807808 request(app)809 .get('/foo')810 .expect(200, 'foo as html', cb)811812 request(app)813 .get('/foo.json')814 .expect(200, 'foo as json', cb)815 })816 })817818 describe('when next() is called', function () {819 it('should continue lookup', function (done) {820 var app = express()821 , calls = [];822823 app.get('/foo{/:bar}', function (req, res, next) {824 calls.push('/foo/:bar?');825 next();826 });827828 app.get('/bar', function () {829 assert(0);830 });831832 app.get('/foo', function (req, res, next) {833 calls.push('/foo');834 next();835 });836837 app.get('/foo', function (req, res) {838 calls.push('/foo 2');839 res.json(calls)840 });841842 request(app)843 .get('/foo')844 .expect(200, ['/foo/:bar?', '/foo', '/foo 2'], done)845 })846 })847848 describe('when next("route") is called', function () {849 it('should jump to next route', function (done) {850 var app = express()851852 function fn(req, res, next) {853 res.set('X-Hit', '1')854 next('route')855 }856857 app.get('/foo', fn, function (req, res) {858 res.end('failure')859 });860861 app.get('/foo', function (req, res) {862 res.end('success')863 })864865 request(app)866 .get('/foo')867 .expect('X-Hit', '1')868 .expect(200, 'success', done)869 })870 })871872 describe('when next("router") is called', function () {873 it('should jump out of router', function (done) {874 var app = express()875 var router = express.Router()876877 function fn(req, res, next) {878 res.set('X-Hit', '1')879 next('router')880 }881882 router.get('/foo', fn, function (req, res) {883 res.end('failure')884 })885886 router.get('/foo', function (req, res) {887 res.end('failure')888 })889890 app.use(router)891892 app.get('/foo', function (req, res) {893 res.end('success')894 })895896 request(app)897 .get('/foo')898 .expect('X-Hit', '1')899 .expect(200, 'success', done)900 })901 })902903 describe('when next(err) is called', function () {904 it('should break out of app.router', function (done) {905 var app = express()906 , calls = [];907908 app.get('/foo{/:bar}', function (req, res, next) {909 calls.push('/foo/:bar?');910 next();911 });912913 app.get('/bar', function () {914 assert(0);915 });916917 app.get('/foo', function (req, res, next) {918 calls.push('/foo');919 next(new Error('fail'));920 });921922 app.get('/foo', function () {923 assert(0);924 });925926 app.use(function (err, req, res, next) {927 res.json({928 calls: calls,929 error: err.message930 })931 })932933 request(app)934 .get('/foo')935 .expect(200, { calls: ['/foo/:bar?', '/foo'], error: 'fail' }, done)936 })937938 it('should call handler in same route, if exists', function (done) {939 var app = express();940941 function fn1(req, res, next) {942 next(new Error('boom!'));943 }944945 function fn2(req, res, next) {946 res.send('foo here');947 }948949 function fn3(err, req, res, next) {950 res.send('route go ' + err.message);951 }952953 app.get('/foo', fn1, fn2, fn3);954955 app.use(function (err, req, res, next) {956 res.end('error!');957 })958959 request(app)960 .get('/foo')961 .expect('route go boom!', done)962 })963 })964965 describe('promise support', function () {966 it('should pass rejected promise value', function (done) {967 var app = express()968 var router = new express.Router()969970 router.use(function createError(req, res, next) {971 return Promise.reject(new Error('boom!'))972 })973974 router.use(function sawError(err, req, res, next) {975 res.send('saw ' + err.name + ': ' + err.message)976 })977978 app.use(router)979980 request(app)981 .get('/')982 .expect(200, 'saw Error: boom!', done)983 })984985 it('should pass rejected promise without value', function (done) {986 var app = express()987 var router = new express.Router()988989 router.use(function createError(req, res, next) {990 return Promise.reject()991 })992993 router.use(function sawError(err, req, res, next) {994 res.send('saw ' + err.name + ': ' + err.message)995 })996997 app.use(router)998999 request(app)1000 .get('/')1001 .expect(200, 'saw Error: Rejected promise', done)1002 })10031004 it('should ignore resolved promise', function (done) {1005 var app = express()1006 var router = new express.Router()10071008 router.use(function createError(req, res, next) {1009 res.send('saw GET /foo')1010 return Promise.resolve('foo')1011 })10121013 router.use(function () {1014 done(new Error('Unexpected middleware invoke'))1015 })10161017 app.use(router)10181019 request(app)1020 .get('/foo')1021 .expect(200, 'saw GET /foo', done)1022 })10231024 describe('error handling', function () {1025 it('should pass rejected promise value', function (done) {1026 var app = express()1027 var router = new express.Router()10281029 router.use(function createError(req, res, next) {1030 return Promise.reject(new Error('boom!'))1031 })10321033 router.use(function handleError(err, req, res, next) {1034 return Promise.reject(new Error('caught: ' + err.message))1035 })10361037 router.use(function sawError(err, req, res, next) {1038 res.send('saw ' + err.name + ': ' + err.message)1039 })10401041 app.use(router)10421043 request(app)1044 .get('/')1045 .expect(200, 'saw Error: caught: boom!', done)1046 })10471048 it('should pass rejected promise without value', function (done) {1049 var app = express()1050 var router = new express.Router()10511052 router.use(function createError(req, res, next) {1053 return Promise.reject()1054 })10551056 router.use(function handleError(err, req, res, next) {1057 return Promise.reject(new Error('caught: ' + err.message))1058 })10591060 router.use(function sawError(err, req, res, next) {1061 res.send('saw ' + err.name + ': ' + err.message)1062 })10631064 app.use(router)10651066 request(app)1067 .get('/')1068 .expect(200, 'saw Error: caught: Rejected promise', done)1069 })10701071 it('should ignore resolved promise', function (done) {1072 var app = express()1073 var router = new express.Router()10741075 router.use(function createError(req, res, next) {1076 return Promise.reject(new Error('boom!'))1077 })10781079 router.use(function handleError(err, req, res, next) {1080 res.send('saw ' + err.name + ': ' + err.message)1081 return Promise.resolve('foo')1082 })10831084 router.use(function () {1085 done(new Error('Unexpected middleware invoke'))1086 })10871088 app.use(router)10891090 request(app)1091 .get('/foo')1092 .expect(200, 'saw Error: boom!', done)1093 })1094 })1095 })10961097 it('should allow rewriting of the url', function (done) {1098 var app = express();10991100 app.get('/account/edit', function (req, res, next) {1101 req.user = { id: 12 }; // faux authenticated user1102 req.url = '/user/' + req.user.id + '/edit';1103 next();1104 });11051106 app.get('/user/:id/edit', function (req, res) {1107 res.send('editing user ' + req.params.id);1108 });11091110 request(app)1111 .get('/account/edit')1112 .expect('editing user 12', done);1113 })11141115 it('should run in order added', function (done) {1116 var app = express();1117 var path = [];11181119 app.get('/*path', function (req, res, next) {1120 path.push(0);1121 next();1122 });11231124 app.get('/user/:id', function (req, res, next) {1125 path.push(1);1126 next();1127 });11281129 app.use(function (req, res, next) {1130 path.push(2);1131 next();1132 });11331134 app.all('/user/:id', function (req, res, next) {1135 path.push(3);1136 next();1137 });11381139 app.get('/*splat', function (req, res, next) {1140 path.push(4);1141 next();1142 });11431144 app.use(function (req, res, next) {1145 path.push(5);1146 res.end(path.join(','))1147 });11481149 request(app)1150 .get('/user/1')1151 .expect(200, '0,1,2,3,4,5', done);1152 })11531154 it('should be chainable', function () {1155 var app = express();1156 assert.strictEqual(app.get('/', function () { }), app)1157 })11581159 it('should not use disposed router/middleware', function (done) {1160 // more context: https://github.com/expressjs/express/issues/5743#issuecomment-227714841211611162 var app = express();1163 var router = new express.Router();11641165 router.use(function (req, res, next) {1166 res.setHeader('old', 'foo');1167 next();1168 });11691170 app.use(function (req, res, next) {1171 return router.handle(req, res, next);1172 });11731174 app.get('/', function (req, res, next) {1175 res.send('yee');1176 next();1177 });11781179 request(app)1180 .get('/')1181 .expect('old', 'foo')1182 .expect(function (res) {1183 if (typeof res.headers['new'] !== 'undefined') {1184 throw new Error('`new` header should not be present');1185 }1186 })1187 .expect(200, 'yee', function (err, res) {1188 if (err) return done(err);11891190 router = new express.Router();11911192 router.use(function (req, res, next) {1193 res.setHeader('new', 'bar');1194 next();1195 });11961197 request(app)1198 .get('/')1199 .expect('new', 'bar')1200 .expect(function (res) {1201 if (typeof res.headers['old'] !== 'undefined') {1202 throw new Error('`old` header should not be present');1203 }1204 })1205 .expect(200, 'yee', done);1206 });1207 })1208})12091210function supportsRegexp(source) {1211 try {1212 new RegExp(source)1213 return true1214 } catch (e) {1215 return false1216 }1217}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.