test/app.router.js JAVASCRIPT 1,218 lines View on github.com → Search inside
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}

Code quality findings 100

Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var after = require('after');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var express = require('../')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var shouldSkipQuery = require('./support/utils').shouldSkipQuery
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router();
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (method === 'connect') return;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (method === 'query' && shouldSkipQuery(process.versions.node)) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var cb = after(3, done);
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (req.method !== 'POST') return next();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var calls = [];
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var id = req.params[0]
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var re = new RegExp('^/user/(?<userId>[0-9]+)/(view|edit)?$');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var id = req.params.userId
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var p = []
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router({ mergeParams: true });
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var keys = Object.keys(req.params).sort();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router({ mergeParams: true });
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var keys = Object.keys(req.params).sort();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router({ mergeParams: true });
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var keys = Object.keys(req.params).sort();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router({ mergeParams: true });
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var keys = Object.keys(req.params).sort();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router({ mergeParams: true });
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var keys = Object.keys(req.params).sort();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router({ mergeParams: true });
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var keys = Object.keys(req.params).sort();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router({ mergeParams: true });
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var keys = Object.keys(req.params).sort();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var from = req.params.from
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var cb = after(2, done);
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var cb = after(2, done);
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var op = req.params.op || 'view';
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var op = req.params.op || 'view';
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var cb = after(2, done)
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var cb = after(2, done)
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = express.Router()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express();
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = new express.Router()

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.