test/express.urlencoded.js JAVASCRIPT 829 lines View on github.com → Search inside
1'use strict'23var assert = require('node:assert')4var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage5const { Buffer } = require('node:buffer');67var express = require('..')8var request = require('supertest')910describe('express.urlencoded()', function () {11  before(function () {12    this.app = createApp()13  })1415  it('should parse x-www-form-urlencoded', function (done) {16    request(this.app)17      .post('/')18      .set('Content-Type', 'application/x-www-form-urlencoded')19      .send('user=tobi')20      .expect(200, '{"user":"tobi"}', done)21  })2223  it('should 400 when invalid content-length', function (done) {24    var app = express()2526    app.use(function (req, res, next) {27      req.headers['content-length'] = '20' // bad length28      next()29    })3031    app.use(express.urlencoded())3233    app.post('/', function (req, res) {34      res.json(req.body)35    })3637    request(app)38      .post('/')39      .set('Content-Type', 'application/x-www-form-urlencoded')40      .send('str=')41      .expect(400, /content length/, done)42  })4344  it('should handle Content-Length: 0', function (done) {45    request(this.app)46      .post('/')47      .set('Content-Type', 'application/x-www-form-urlencoded')48      .set('Content-Length', '0')49      .send('')50      .expect(200, '{}', done)51  })5253  it('should handle empty message-body', function (done) {54    request(createApp({ limit: '1kb' }))55      .post('/')56      .set('Content-Type', 'application/x-www-form-urlencoded')57      .set('Transfer-Encoding', 'chunked')58      .send('')59      .expect(200, '{}', done)60  })6162  it('should handle duplicated middleware', function (done) {63    var app = express()6465    app.use(express.urlencoded())66    app.use(express.urlencoded())6768    app.post('/', function (req, res) {69      res.json(req.body)70    })7172    request(app)73      .post('/')74      .set('Content-Type', 'application/x-www-form-urlencoded')75      .send('user=tobi')76      .expect(200, '{"user":"tobi"}', done)77  })7879  it('should not parse extended syntax', function (done) {80    request(this.app)81      .post('/')82      .set('Content-Type', 'application/x-www-form-urlencoded')83      .send('user[name][first]=Tobi')84      .expect(200, '{"user[name][first]":"Tobi"}', done)85  })8687  describe('with extended option', function () {88    describe('when false', function () {89      before(function () {90        this.app = createApp({ extended: false })91      })9293      it('should not parse extended syntax', function (done) {94        request(this.app)95          .post('/')96          .set('Content-Type', 'application/x-www-form-urlencoded')97          .send('user[name][first]=Tobi')98          .expect(200, '{"user[name][first]":"Tobi"}', done)99      })100101      it('should parse multiple key instances', function (done) {102        request(this.app)103          .post('/')104          .set('Content-Type', 'application/x-www-form-urlencoded')105          .send('user=Tobi&user=Loki')106          .expect(200, '{"user":["Tobi","Loki"]}', done)107      })108    })109110    describe('when true', function () {111      before(function () {112        this.app = createApp({ extended: true })113      })114115      it('should parse multiple key instances', function (done) {116        request(this.app)117          .post('/')118          .set('Content-Type', 'application/x-www-form-urlencoded')119          .send('user=Tobi&user=Loki')120          .expect(200, '{"user":["Tobi","Loki"]}', done)121      })122123      it('should parse extended syntax', function (done) {124        request(this.app)125          .post('/')126          .set('Content-Type', 'application/x-www-form-urlencoded')127          .send('user[name][first]=Tobi')128          .expect(200, '{"user":{"name":{"first":"Tobi"}}}', done)129      })130131      it('should parse parameters with dots', function (done) {132        request(this.app)133          .post('/')134          .set('Content-Type', 'application/x-www-form-urlencoded')135          .send('user.name=Tobi')136          .expect(200, '{"user.name":"Tobi"}', done)137      })138139      it('should parse fully-encoded extended syntax', function (done) {140        request(this.app)141          .post('/')142          .set('Content-Type', 'application/x-www-form-urlencoded')143          .send('user%5Bname%5D%5Bfirst%5D=Tobi')144          .expect(200, '{"user":{"name":{"first":"Tobi"}}}', done)145      })146147      it('should parse array index notation', function (done) {148        request(this.app)149          .post('/')150          .set('Content-Type', 'application/x-www-form-urlencoded')151          .send('foo[0]=bar&foo[1]=baz')152          .expect(200, '{"foo":["bar","baz"]}', done)153      })154155      it('should parse array index notation with large array', function (done) {156        var str = 'f[0]=0'157158        for (var i = 1; i < 500; i++) {159          str += '&f[' + i + ']=' + i.toString(16)160        }161162        request(this.app)163          .post('/')164          .set('Content-Type', 'application/x-www-form-urlencoded')165          .send(str)166          .expect(function (res) {167            var obj = JSON.parse(res.text)168            assert.strictEqual(Object.keys(obj).length, 1)169            assert.strictEqual(Array.isArray(obj.f), true)170            assert.strictEqual(obj.f.length, 500)171          })172          .expect(200, done)173      })174175      it('should parse array of objects syntax', function (done) {176        request(this.app)177          .post('/')178          .set('Content-Type', 'application/x-www-form-urlencoded')179          .send('foo[0][bar]=baz&foo[0][fizz]=buzz&foo[]=done!')180          .expect(200, '{"foo":[{"bar":"baz","fizz":"buzz"},"done!"]}', done)181      })182183      it('should parse deep object', function (done) {184        var str = 'foo'185186        for (var i = 0; i < 32; i++) {187          str += '[p]'188        }189190        str += '=bar'191192        request(this.app)193          .post('/')194          .set('Content-Type', 'application/x-www-form-urlencoded')195          .send(str)196          .expect(function (res) {197            var obj = JSON.parse(res.text)198            assert.strictEqual(Object.keys(obj).length, 1)199            assert.strictEqual(typeof obj.foo, 'object')200201            var depth = 0202            var ref = obj.foo203            while ((ref = ref.p)) { depth++ }204            assert.strictEqual(depth, 32)205          })206          .expect(200, done)207      })208    })209  })210211  describe('with inflate option', function () {212    describe('when false', function () {213      before(function () {214        this.app = createApp({ inflate: false })215      })216217      it('should not accept content-encoding', function (done) {218        var test = request(this.app).post('/')219        test.set('Content-Encoding', 'gzip')220        test.set('Content-Type', 'application/x-www-form-urlencoded')221        test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))222        test.expect(415, '[encoding.unsupported] content encoding unsupported', done)223      })224    })225226    describe('when true', function () {227      before(function () {228        this.app = createApp({ inflate: true })229      })230231      it('should accept content-encoding', function (done) {232        var test = request(this.app).post('/')233        test.set('Content-Encoding', 'gzip')234        test.set('Content-Type', 'application/x-www-form-urlencoded')235        test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))236        test.expect(200, '{"name":"论"}', done)237      })238    })239  })240241  describe('with limit option', function () {242    it('should 413 when over limit with Content-Length', function (done) {243      var buf = Buffer.alloc(1024, '.')244      request(createApp({ limit: '1kb' }))245        .post('/')246        .set('Content-Type', 'application/x-www-form-urlencoded')247        .set('Content-Length', '1028')248        .send('str=' + buf.toString())249        .expect(413, done)250    })251252    it('should 413 when over limit with chunked encoding', function (done) {253      var app = createApp({ limit: '1kb' })254      var buf = Buffer.alloc(1024, '.')255      var test = request(app).post('/')256      test.set('Content-Type', 'application/x-www-form-urlencoded')257      test.set('Transfer-Encoding', 'chunked')258      test.write('str=')259      test.write(buf.toString())260      test.expect(413, done)261    })262263    it('should 413 when inflated body over limit', function (done) {264      var app = createApp({ limit: '1kb' })265      var test = request(app).post('/')266      test.set('Content-Encoding', 'gzip')267      test.set('Content-Type', 'application/x-www-form-urlencoded')268      test.write(Buffer.from('1f8b080000000000000a2b2e29b2d51b05a360148c580000a0351f9204040000', 'hex'))269      test.expect(413, done)270    })271272    it('should accept number of bytes', function (done) {273      var buf = Buffer.alloc(1024, '.')274      request(createApp({ limit: 1024 }))275        .post('/')276        .set('Content-Type', 'application/x-www-form-urlencoded')277        .send('str=' + buf.toString())278        .expect(413, done)279    })280281    it('should not change when options altered', function (done) {282      var buf = Buffer.alloc(1024, '.')283      var options = { limit: '1kb' }284      var app = createApp(options)285286      options.limit = '100kb'287288      request(app)289        .post('/')290        .set('Content-Type', 'application/x-www-form-urlencoded')291        .send('str=' + buf.toString())292        .expect(413, done)293    })294295    it('should not hang response', function (done) {296      var app = createApp({ limit: '8kb' })297      var buf = Buffer.alloc(10240, '.')298      var test = request(app).post('/')299      test.set('Content-Type', 'application/x-www-form-urlencoded')300      test.write(buf)301      test.write(buf)302      test.write(buf)303      test.expect(413, done)304    })305306    it('should not error when inflating', function (done) {307      var app = createApp({ limit: '1kb' })308      var test = request(app).post('/')309      test.set('Content-Encoding', 'gzip')310      test.set('Content-Type', 'application/x-www-form-urlencoded')311      test.write(Buffer.from('1f8b080000000000000a2b2e29b2d51b05a360148c580000a0351f92040400', 'hex'))312      test.expect(413, done)313    })314  })315316  describe('with parameterLimit option', function () {317    describe('with extended: false', function () {318      it('should reject 0', function () {319        assert.throws(createApp.bind(null, { extended: false, parameterLimit: 0 }),320          /TypeError: option parameterLimit must be a positive number/)321      })322323      it('should reject string', function () {324        assert.throws(createApp.bind(null, { extended: false, parameterLimit: 'beep' }),325          /TypeError: option parameterLimit must be a positive number/)326      })327328      it('should 413 if over limit', function (done) {329        request(createApp({ extended: false, parameterLimit: 10 }))330          .post('/')331          .set('Content-Type', 'application/x-www-form-urlencoded')332          .send(createManyParams(11))333          .expect(413, '[parameters.too.many] too many parameters', done)334      })335336      it('should work when at the limit', function (done) {337        request(createApp({ extended: false, parameterLimit: 10 }))338          .post('/')339          .set('Content-Type', 'application/x-www-form-urlencoded')340          .send(createManyParams(10))341          .expect(expectKeyCount(10))342          .expect(200, done)343      })344345      it('should work if number is floating point', function (done) {346        request(createApp({ extended: false, parameterLimit: 10.1 }))347          .post('/')348          .set('Content-Type', 'application/x-www-form-urlencoded')349          .send(createManyParams(11))350          .expect(413, /too many parameters/, done)351      })352353      it('should work with large limit', function (done) {354        request(createApp({ extended: false, parameterLimit: 5000 }))355          .post('/')356          .set('Content-Type', 'application/x-www-form-urlencoded')357          .send(createManyParams(5000))358          .expect(expectKeyCount(5000))359          .expect(200, done)360      })361362      it('should work with Infinity limit', function (done) {363        request(createApp({ extended: false, parameterLimit: Infinity }))364          .post('/')365          .set('Content-Type', 'application/x-www-form-urlencoded')366          .send(createManyParams(10000))367          .expect(expectKeyCount(10000))368          .expect(200, done)369      })370    })371372    describe('with extended: true', function () {373      it('should reject 0', function () {374        assert.throws(createApp.bind(null, { extended: true, parameterLimit: 0 }),375          /TypeError: option parameterLimit must be a positive number/)376      })377378      it('should reject string', function () {379        assert.throws(createApp.bind(null, { extended: true, parameterLimit: 'beep' }),380          /TypeError: option parameterLimit must be a positive number/)381      })382383      it('should 413 if over limit', function (done) {384        request(createApp({ extended: true, parameterLimit: 10 }))385          .post('/')386          .set('Content-Type', 'application/x-www-form-urlencoded')387          .send(createManyParams(11))388          .expect(413, '[parameters.too.many] too many parameters', done)389      })390391      it('should work when at the limit', function (done) {392        request(createApp({ extended: true, parameterLimit: 10 }))393          .post('/')394          .set('Content-Type', 'application/x-www-form-urlencoded')395          .send(createManyParams(10))396          .expect(expectKeyCount(10))397          .expect(200, done)398      })399400      it('should work if number is floating point', function (done) {401        request(createApp({ extended: true, parameterLimit: 10.1 }))402          .post('/')403          .set('Content-Type', 'application/x-www-form-urlencoded')404          .send(createManyParams(11))405          .expect(413, /too many parameters/, done)406      })407408      it('should work with large limit', function (done) {409        request(createApp({ extended: true, parameterLimit: 5000 }))410          .post('/')411          .set('Content-Type', 'application/x-www-form-urlencoded')412          .send(createManyParams(5000))413          .expect(expectKeyCount(5000))414          .expect(200, done)415      })416417      it('should work with Infinity limit', function (done) {418        request(createApp({ extended: true, parameterLimit: Infinity }))419          .post('/')420          .set('Content-Type', 'application/x-www-form-urlencoded')421          .send(createManyParams(10000))422          .expect(expectKeyCount(10000))423          .expect(200, done)424      })425    })426  })427428  describe('with type option', function () {429    describe('when "application/vnd.x-www-form-urlencoded"', function () {430      before(function () {431        this.app = createApp({ type: 'application/vnd.x-www-form-urlencoded' })432      })433434      it('should parse for custom type', function (done) {435        request(this.app)436          .post('/')437          .set('Content-Type', 'application/vnd.x-www-form-urlencoded')438          .send('user=tobi')439          .expect(200, '{"user":"tobi"}', done)440      })441442      it('should ignore standard type', function (done) {443        request(this.app)444          .post('/')445          .set('Content-Type', 'application/x-www-form-urlencoded')446          .send('user=tobi')447          .expect(200, '', done)448      })449    })450451    describe('when ["urlencoded", "application/x-pairs"]', function () {452      before(function () {453        this.app = createApp({454          type: ['urlencoded', 'application/x-pairs']455        })456      })457458      it('should parse "application/x-www-form-urlencoded"', function (done) {459        request(this.app)460          .post('/')461          .set('Content-Type', 'application/x-www-form-urlencoded')462          .send('user=tobi')463          .expect(200, '{"user":"tobi"}', done)464      })465466      it('should parse "application/x-pairs"', function (done) {467        request(this.app)468          .post('/')469          .set('Content-Type', 'application/x-pairs')470          .send('user=tobi')471          .expect(200, '{"user":"tobi"}', done)472      })473474      it('should ignore application/x-foo', function (done) {475        request(this.app)476          .post('/')477          .set('Content-Type', 'application/x-foo')478          .send('user=tobi')479          .expect(200, '', done)480      })481    })482483    describe('when a function', function () {484      it('should parse when truthy value returned', function (done) {485        var app = createApp({ type: accept })486487        function accept (req) {488          return req.headers['content-type'] === 'application/vnd.something'489        }490491        request(app)492          .post('/')493          .set('Content-Type', 'application/vnd.something')494          .send('user=tobi')495          .expect(200, '{"user":"tobi"}', done)496      })497498      it('should work without content-type', function (done) {499        var app = createApp({ type: accept })500501        function accept (req) {502          return true503        }504505        var test = request(app).post('/')506        test.write('user=tobi')507        test.expect(200, '{"user":"tobi"}', done)508      })509510      it('should not invoke without a body', function (done) {511        var app = createApp({ type: accept })512513        function accept (req) {514          throw new Error('oops!')515        }516517        request(app)518          .get('/')519          .expect(404, done)520      })521    })522  })523524  describe('with verify option', function () {525    it('should assert value if function', function () {526      assert.throws(createApp.bind(null, { verify: 'lol' }),527        /TypeError: option verify must be function/)528    })529530    it('should error from verify', function (done) {531      var app = createApp({532        verify: function (req, res, buf) {533          if (buf[0] === 0x20) throw new Error('no leading space')534        }535      })536537      request(app)538        .post('/')539        .set('Content-Type', 'application/x-www-form-urlencoded')540        .send(' user=tobi')541        .expect(403, '[entity.verify.failed] no leading space', done)542    })543544    it('should allow custom codes', function (done) {545      var app = createApp({546        verify: function (req, res, buf) {547          if (buf[0] !== 0x20) return548          var err = new Error('no leading space')549          err.status = 400550          throw err551        }552      })553554      request(app)555        .post('/')556        .set('Content-Type', 'application/x-www-form-urlencoded')557        .send(' user=tobi')558        .expect(400, '[entity.verify.failed] no leading space', done)559    })560561    it('should allow custom type', function (done) {562      var app = createApp({563        verify: function (req, res, buf) {564          if (buf[0] !== 0x20) return565          var err = new Error('no leading space')566          err.type = 'foo.bar'567          throw err568        }569      })570571      request(app)572        .post('/')573        .set('Content-Type', 'application/x-www-form-urlencoded')574        .send(' user=tobi')575        .expect(403, '[foo.bar] no leading space', done)576    })577578    it('should allow pass-through', function (done) {579      var app = createApp({580        verify: function (req, res, buf) {581          if (buf[0] === 0x5b) throw new Error('no arrays')582        }583      })584585      request(app)586        .post('/')587        .set('Content-Type', 'application/x-www-form-urlencoded')588        .send('user=tobi')589        .expect(200, '{"user":"tobi"}', done)590    })591592    it('should 415 on unknown charset prior to verify', function (done) {593      var app = createApp({594        verify: function (req, res, buf) {595          throw new Error('unexpected verify call')596        }597      })598599      var test = request(app).post('/')600      test.set('Content-Type', 'application/x-www-form-urlencoded; charset=x-bogus')601      test.write(Buffer.from('00000000', 'hex'))602      test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done)603    })604  })605606  describe('async local storage', function () {607    before(function () {608      var app = express()609      var store = { foo: 'bar' }610611      app.use(function (req, res, next) {612        req.asyncLocalStorage = new AsyncLocalStorage()613        req.asyncLocalStorage.run(store, next)614      })615616      app.use(express.urlencoded())617618      app.use(function (req, res, next) {619        var local = req.asyncLocalStorage.getStore()620621        if (local) {622          res.setHeader('x-store-foo', String(local.foo))623        }624625        next()626      })627628      app.use(function (err, req, res, next) {629        var local = req.asyncLocalStorage.getStore()630631        if (local) {632          res.setHeader('x-store-foo', String(local.foo))633        }634635        res.status(err.status || 500)636        res.send('[' + err.type + '] ' + err.message)637      })638639      app.post('/', function (req, res) {640        res.json(req.body)641      })642643      this.app = app644    })645646    it('should persist store', function (done) {647      request(this.app)648        .post('/')649        .set('Content-Type', 'application/x-www-form-urlencoded')650        .send('user=tobi')651        .expect(200)652        .expect('x-store-foo', 'bar')653        .expect('{"user":"tobi"}')654        .end(done)655    })656657    it('should persist store when unmatched content-type', function (done) {658      request(this.app)659        .post('/')660        .set('Content-Type', 'application/fizzbuzz')661        .send('buzz')662        .expect(200)663        .expect('x-store-foo', 'bar')664        .end(done)665    })666667    it('should persist store when inflated', function (done) {668      var test = request(this.app).post('/')669      test.set('Content-Encoding', 'gzip')670      test.set('Content-Type', 'application/x-www-form-urlencoded')671      test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))672      test.expect(200)673      test.expect('x-store-foo', 'bar')674      test.expect('{"name":"论"}')675      test.end(done)676    })677678    it('should persist store when inflate error', function (done) {679      var test = request(this.app).post('/')680      test.set('Content-Encoding', 'gzip')681      test.set('Content-Type', 'application/x-www-form-urlencoded')682      test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad6080000', 'hex'))683      test.expect(400)684      test.expect('x-store-foo', 'bar')685      test.end(done)686    })687688    it('should persist store when limit exceeded', function (done) {689      request(this.app)690        .post('/')691        .set('Content-Type', 'application/x-www-form-urlencoded')692        .send('user=' + Buffer.alloc(1024 * 100, '.').toString())693        .expect(413)694        .expect('x-store-foo', 'bar')695        .end(done)696    })697  })698699  describe('charset', function () {700    before(function () {701      this.app = createApp()702    })703704    it('should parse utf-8', function (done) {705      var test = request(this.app).post('/')706      test.set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8')707      test.write(Buffer.from('6e616d653de8aeba', 'hex'))708      test.expect(200, '{"name":"论"}', done)709    })710711    it('should parse when content-length != char length', function (done) {712      var test = request(this.app).post('/')713      test.set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8')714      test.set('Content-Length', '7')715      test.write(Buffer.from('746573743dc3a5', 'hex'))716      test.expect(200, '{"test":"å"}', done)717    })718719    it('should default to utf-8', function (done) {720      var test = request(this.app).post('/')721      test.set('Content-Type', 'application/x-www-form-urlencoded')722      test.write(Buffer.from('6e616d653de8aeba', 'hex'))723      test.expect(200, '{"name":"论"}', done)724    })725726    it('should fail on unknown charset', function (done) {727      var test = request(this.app).post('/')728      test.set('Content-Type', 'application/x-www-form-urlencoded; charset=koi8-r')729      test.write(Buffer.from('6e616d653dcec5d4', 'hex'))730      test.expect(415, '[charset.unsupported] unsupported charset "KOI8-R"', done)731    })732  })733734  describe('encoding', function () {735    before(function () {736      this.app = createApp({ limit: '10kb' })737    })738739    it('should parse without encoding', function (done) {740      var test = request(this.app).post('/')741      test.set('Content-Type', 'application/x-www-form-urlencoded')742      test.write(Buffer.from('6e616d653de8aeba', 'hex'))743      test.expect(200, '{"name":"论"}', done)744    })745746    it('should support identity encoding', function (done) {747      var test = request(this.app).post('/')748      test.set('Content-Encoding', 'identity')749      test.set('Content-Type', 'application/x-www-form-urlencoded')750      test.write(Buffer.from('6e616d653de8aeba', 'hex'))751      test.expect(200, '{"name":"论"}', done)752    })753754    it('should support gzip encoding', function (done) {755      var test = request(this.app).post('/')756      test.set('Content-Encoding', 'gzip')757      test.set('Content-Type', 'application/x-www-form-urlencoded')758      test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))759      test.expect(200, '{"name":"论"}', done)760    })761762    it('should support deflate encoding', function (done) {763      var test = request(this.app).post('/')764      test.set('Content-Encoding', 'deflate')765      test.set('Content-Type', 'application/x-www-form-urlencoded')766      test.write(Buffer.from('789ccb4bcc4db57db16e17001068042f', 'hex'))767      test.expect(200, '{"name":"论"}', done)768    })769770    it('should be case-insensitive', function (done) {771      var test = request(this.app).post('/')772      test.set('Content-Encoding', 'GZIP')773      test.set('Content-Type', 'application/x-www-form-urlencoded')774      test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))775      test.expect(200, '{"name":"论"}', done)776    })777778    it('should 415 on unknown encoding', function (done) {779      var test = request(this.app).post('/')780      test.set('Content-Encoding', 'nulls')781      test.set('Content-Type', 'application/x-www-form-urlencoded')782      test.write(Buffer.from('000000000000', 'hex'))783      test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done)784    })785  })786})787788function createManyParams (count) {789  var str = ''790791  if (count === 0) {792    return str793  }794795  str += '0=0'796797  for (var i = 1; i < count; i++) {798    var n = i.toString(36)799    str += '&' + n + '=' + n800  }801802  return str803}804805function createApp (options) {806  var app = express()807808  app.use(express.urlencoded(options))809810  app.use(function (err, req, res, next) {811    res.status(err.status || 500)812    res.send(String(req.headers['x-error-property']813      ? err[req.headers['x-error-property']]814      : ('[' + err.type + '] ' + err.message)))815  })816817  app.post('/', function (req, res) {818    res.json(req.body)819  })820821  return app822}823824function expectKeyCount (count) {825  return function (res) {826    assert.strictEqual(Object.keys(JSON.parse(res.text)).length, count)827  }828}

Code quality findings 74

Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var assert = require('node:assert')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage
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 request = require('supertest')
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 str = 'f[0]=0'
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
for (var i = 1; i < 500; i++) {
Use let instead of var in loops to avoid scope issues
info correctness var-in-loop
for (var i = 1; i < 500; i++) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var obj = JSON.parse(res.text)
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var str = 'foo'
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
for (var i = 0; i < 32; i++) {
Use let instead of var in loops to avoid scope issues
info correctness var-in-loop
for (var i = 0; i < 32; i++) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var obj = JSON.parse(res.text)
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
assert.strictEqual(typeof obj.foo, 'object')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var depth = 0
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var ref = obj.foo
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var buf = Buffer.alloc(1024, '.')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({ limit: '1kb' })
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var buf = Buffer.alloc(1024, '.')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({ limit: '1kb' })
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var buf = Buffer.alloc(1024, '.')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var buf = Buffer.alloc(1024, '.')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var options = { limit: '1kb' }
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp(options)
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({ limit: '8kb' })
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var buf = Buffer.alloc(10240, '.')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({ limit: '1kb' })
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({ type: accept })
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
return req.headers['content-type'] === 'application/vnd.something'
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({ type: accept })
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({ type: accept })
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (buf[0] === 0x20) throw new Error('no leading space')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (buf[0] !== 0x20) return
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var err = new Error('no leading space')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (buf[0] !== 0x20) return
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var err = new Error('no leading space')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (buf[0] === 0x5b) throw new Error('no arrays')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = createApp({
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(app).post('/')
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 store = { foo: 'bar' }
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var local = req.asyncLocalStorage.getStore()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var local = req.asyncLocalStorage.getStore()
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use strict inequality (!==) to prevent type coercion bugs
info correctness loose-inequality
it('should parse when content-length != char length', function (done) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(this.app).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var str = ''
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (count === 0) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
for (var i = 1; i < count; i++) {
Use let instead of var in loops to avoid scope issues
info correctness var-in-loop
for (var i = 1; i < count; i++) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var n = i.toString(36)
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = express()

Get this view in your editor

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