test/express.text.js JAVASCRIPT 567 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');6var express = require('..')7var request = require('supertest')89describe('express.text()', function () {10  before(function () {11    this.app = createApp()12  })1314  it('should parse text/plain', function (done) {15    request(this.app)16      .post('/')17      .set('Content-Type', 'text/plain')18      .send('user is tobi')19      .expect(200, '"user is tobi"', done)20  })2122  it('should 400 when invalid content-length', function (done) {23    var app = express()2425    app.use(function (req, res, next) {26      req.headers['content-length'] = '20' // bad length27      next()28    })2930    app.use(express.text())3132    app.post('/', function (req, res) {33      res.json(req.body)34    })3536    request(app)37      .post('/')38      .set('Content-Type', 'text/plain')39      .send('user')40      .expect(400, /content length/, done)41  })4243  it('should handle Content-Length: 0', function (done) {44    request(createApp({ limit: '1kb' }))45      .post('/')46      .set('Content-Type', 'text/plain')47      .set('Content-Length', '0')48      .expect(200, '""', done)49  })5051  it('should handle empty message-body', function (done) {52    request(createApp({ limit: '1kb' }))53      .post('/')54      .set('Content-Type', 'text/plain')55      .set('Transfer-Encoding', 'chunked')56      .send('')57      .expect(200, '""', done)58  })5960  it('should handle duplicated middleware', function (done) {61    var app = express()6263    app.use(express.text())64    app.use(express.text())6566    app.post('/', function (req, res) {67      res.json(req.body)68    })6970    request(app)71      .post('/')72      .set('Content-Type', 'text/plain')73      .send('user is tobi')74      .expect(200, '"user is tobi"', done)75  })7677  describe('with defaultCharset option', function () {78    it('should change default charset', function (done) {79      var server = createApp({ defaultCharset: 'koi8-r' })80      var test = request(server).post('/')81      test.set('Content-Type', 'text/plain')82      test.write(Buffer.from('6e616d6520697320cec5d4', 'hex'))83      test.expect(200, '"name is нет"', done)84    })8586    it('should honor content-type charset', function (done) {87      var server = createApp({ defaultCharset: 'koi8-r' })88      var test = request(server).post('/')89      test.set('Content-Type', 'text/plain; charset=utf-8')90      test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))91      test.expect(200, '"name is 论"', done)92    })93  })9495  describe('with limit option', function () {96    it('should 413 when over limit with Content-Length', function (done) {97      var buf = Buffer.alloc(1028, '.')98      request(createApp({ limit: '1kb' }))99        .post('/')100        .set('Content-Type', 'text/plain')101        .set('Content-Length', '1028')102        .send(buf.toString())103        .expect(413, done)104    })105106    it('should 413 when over limit with chunked encoding', function (done) {107      var app = createApp({ limit: '1kb' })108      var buf = Buffer.alloc(1028, '.')109      var test = request(app).post('/')110      test.set('Content-Type', 'text/plain')111      test.set('Transfer-Encoding', 'chunked')112      test.write(buf.toString())113      test.expect(413, done)114    })115116    it('should 413 when inflated body over limit', function (done) {117      var app = createApp({ limit: '1kb' })118      var test = request(app).post('/')119      test.set('Content-Encoding', 'gzip')120      test.set('Content-Type', 'text/plain')121      test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a14704040000', 'hex'))122      test.expect(413, done)123    })124125    it('should accept number of bytes', function (done) {126      var buf = Buffer.alloc(1028, '.')127      request(createApp({ limit: 1024 }))128        .post('/')129        .set('Content-Type', 'text/plain')130        .send(buf.toString())131        .expect(413, done)132    })133134    it('should not change when options altered', function (done) {135      var buf = Buffer.alloc(1028, '.')136      var options = { limit: '1kb' }137      var app = createApp(options)138139      options.limit = '100kb'140141      request(app)142        .post('/')143        .set('Content-Type', 'text/plain')144        .send(buf.toString())145        .expect(413, done)146    })147148    it('should not hang response', function (done) {149      var app = createApp({ limit: '8kb' })150      var buf = Buffer.alloc(10240, '.')151      var test = request(app).post('/')152      test.set('Content-Type', 'text/plain')153      test.write(buf)154      test.write(buf)155      test.write(buf)156      test.expect(413, done)157    })158159    it('should not error when inflating', function (done) {160      var app = createApp({ limit: '1kb' })161      var test = request(app).post('/')162      test.set('Content-Encoding', 'gzip')163      test.set('Content-Type', 'text/plain')164      test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a1470404', 'hex'))165      setTimeout(function () {166        test.expect(413, done)167      }, 100)168    })169  })170171  describe('with inflate option', function () {172    describe('when false', function () {173      before(function () {174        this.app = createApp({ inflate: false })175      })176177      it('should not accept content-encoding', function (done) {178        var test = request(this.app).post('/')179        test.set('Content-Encoding', 'gzip')180        test.set('Content-Type', 'text/plain')181        test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))182        test.expect(415, '[encoding.unsupported] content encoding unsupported', done)183      })184    })185186    describe('when true', function () {187      before(function () {188        this.app = createApp({ inflate: true })189      })190191      it('should accept content-encoding', function (done) {192        var test = request(this.app).post('/')193        test.set('Content-Encoding', 'gzip')194        test.set('Content-Type', 'text/plain')195        test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))196        test.expect(200, '"name is 论"', done)197      })198    })199  })200201  describe('with type option', function () {202    describe('when "text/html"', function () {203      before(function () {204        this.app = createApp({ type: 'text/html' })205      })206207      it('should parse for custom type', function (done) {208        request(this.app)209          .post('/')210          .set('Content-Type', 'text/html')211          .send('<b>tobi</b>')212          .expect(200, '"<b>tobi</b>"', done)213      })214215      it('should ignore standard type', function (done) {216        request(this.app)217          .post('/')218          .set('Content-Type', 'text/plain')219          .send('user is tobi')220          .expect(200, '', done)221      })222    })223224    describe('when ["text/html", "text/plain"]', function () {225      before(function () {226        this.app = createApp({ type: ['text/html', 'text/plain'] })227      })228229      it('should parse "text/html"', function (done) {230        request(this.app)231          .post('/')232          .set('Content-Type', 'text/html')233          .send('<b>tobi</b>')234          .expect(200, '"<b>tobi</b>"', done)235      })236237      it('should parse "text/plain"', function (done) {238        request(this.app)239          .post('/')240          .set('Content-Type', 'text/plain')241          .send('tobi')242          .expect(200, '"tobi"', done)243      })244245      it('should ignore "text/xml"', function (done) {246        request(this.app)247          .post('/')248          .set('Content-Type', 'text/xml')249          .send('<user>tobi</user>')250          .expect(200, '', done)251      })252    })253254    describe('when a function', function () {255      it('should parse when truthy value returned', function (done) {256        var app = createApp({ type: accept })257258        function accept (req) {259          return req.headers['content-type'] === 'text/vnd.something'260        }261262        request(app)263          .post('/')264          .set('Content-Type', 'text/vnd.something')265          .send('user is tobi')266          .expect(200, '"user is tobi"', done)267      })268269      it('should work without content-type', function (done) {270        var app = createApp({ type: accept })271272        function accept (req) {273          return true274        }275276        var test = request(app).post('/')277        test.write('user is tobi')278        test.expect(200, '"user is tobi"', done)279      })280281      it('should not invoke without a body', function (done) {282        var app = createApp({ type: accept })283284        function accept (req) {285          throw new Error('oops!')286        }287288        request(app)289          .get('/')290          .expect(404, done)291      })292    })293  })294295  describe('with verify option', function () {296    it('should assert value is function', function () {297      assert.throws(createApp.bind(null, { verify: 'lol' }),298        /TypeError: option verify must be function/)299    })300301    it('should error from verify', function (done) {302      var app = createApp({303        verify: function (req, res, buf) {304          if (buf[0] === 0x20) throw new Error('no leading space')305        }306      })307308      request(app)309        .post('/')310        .set('Content-Type', 'text/plain')311        .send(' user is tobi')312        .expect(403, '[entity.verify.failed] no leading space', done)313    })314315    it('should allow custom codes', function (done) {316      var app = createApp({317        verify: function (req, res, buf) {318          if (buf[0] !== 0x20) return319          var err = new Error('no leading space')320          err.status = 400321          throw err322        }323      })324325      request(app)326        .post('/')327        .set('Content-Type', 'text/plain')328        .send(' user is tobi')329        .expect(400, '[entity.verify.failed] no leading space', done)330    })331332    it('should allow pass-through', function (done) {333      var app = createApp({334        verify: function (req, res, buf) {335          if (buf[0] === 0x20) throw new Error('no leading space')336        }337      })338339      request(app)340        .post('/')341        .set('Content-Type', 'text/plain')342        .send('user is tobi')343        .expect(200, '"user is tobi"', done)344    })345346    it('should 415 on unknown charset prior to verify', function (done) {347      var app = createApp({348        verify: function (req, res, buf) {349          throw new Error('unexpected verify call')350        }351      })352353      var test = request(app).post('/')354      test.set('Content-Type', 'text/plain; charset=x-bogus')355      test.write(Buffer.from('00000000', 'hex'))356      test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done)357    })358  })359360  describe('async local storage', function () {361    before(function () {362      var app = express()363      var store = { foo: 'bar' }364365      app.use(function (req, res, next) {366        req.asyncLocalStorage = new AsyncLocalStorage()367        req.asyncLocalStorage.run(store, next)368      })369370      app.use(express.text())371372      app.use(function (req, res, next) {373        var local = req.asyncLocalStorage.getStore()374375        if (local) {376          res.setHeader('x-store-foo', String(local.foo))377        }378379        next()380      })381382      app.use(function (err, req, res, next) {383        var local = req.asyncLocalStorage.getStore()384385        if (local) {386          res.setHeader('x-store-foo', String(local.foo))387        }388389        res.status(err.status || 500)390        res.send('[' + err.type + '] ' + err.message)391      })392393      app.post('/', function (req, res) {394        res.json(req.body)395      })396397      this.app = app398    })399400    it('should persist store', function (done) {401      request(this.app)402        .post('/')403        .set('Content-Type', 'text/plain')404        .send('user is tobi')405        .expect(200)406        .expect('x-store-foo', 'bar')407        .expect('"user is tobi"')408        .end(done)409    })410411    it('should persist store when unmatched content-type', function (done) {412      request(this.app)413        .post('/')414        .set('Content-Type', 'application/fizzbuzz')415        .send('buzz')416        .expect(200)417        .expect('x-store-foo', 'bar')418        .end(done)419    })420421    it('should persist store when inflated', function (done) {422      var test = request(this.app).post('/')423      test.set('Content-Encoding', 'gzip')424      test.set('Content-Type', 'text/plain')425      test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))426      test.expect(200)427      test.expect('x-store-foo', 'bar')428      test.expect('"name is 论"')429      test.end(done)430    })431432    it('should persist store when inflate error', function (done) {433      var test = request(this.app).post('/')434      test.set('Content-Encoding', 'gzip')435      test.set('Content-Type', 'text/plain')436      test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b0000', 'hex'))437      test.expect(400)438      test.expect('x-store-foo', 'bar')439      test.end(done)440    })441442    it('should persist store when limit exceeded', function (done) {443      request(this.app)444        .post('/')445        .set('Content-Type', 'text/plain')446        .send('user is ' + Buffer.alloc(1024 * 100, '.').toString())447        .expect(413)448        .expect('x-store-foo', 'bar')449        .end(done)450    })451  })452453  describe('charset', function () {454    before(function () {455      this.app = createApp()456    })457458    it('should parse utf-8', function (done) {459      var test = request(this.app).post('/')460      test.set('Content-Type', 'text/plain; charset=utf-8')461      test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))462      test.expect(200, '"name is 论"', done)463    })464465    it('should parse codepage charsets', function (done) {466      var test = request(this.app).post('/')467      test.set('Content-Type', 'text/plain; charset=koi8-r')468      test.write(Buffer.from('6e616d6520697320cec5d4', 'hex'))469      test.expect(200, '"name is нет"', done)470    })471472    it('should parse when content-length != char length', function (done) {473      var test = request(this.app).post('/')474      test.set('Content-Type', 'text/plain; charset=utf-8')475      test.set('Content-Length', '11')476      test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))477      test.expect(200, '"name is 论"', done)478    })479480    it('should default to utf-8', function (done) {481      var test = request(this.app).post('/')482      test.set('Content-Type', 'text/plain')483      test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))484      test.expect(200, '"name is 论"', done)485    })486487    it('should 415 on unknown charset', function (done) {488      var test = request(this.app).post('/')489      test.set('Content-Type', 'text/plain; charset=x-bogus')490      test.write(Buffer.from('00000000', 'hex'))491      test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done)492    })493  })494495  describe('encoding', function () {496    before(function () {497      this.app = createApp({ limit: '10kb' })498    })499500    it('should parse without encoding', function (done) {501      var test = request(this.app).post('/')502      test.set('Content-Type', 'text/plain')503      test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))504      test.expect(200, '"name is 论"', done)505    })506507    it('should support identity encoding', function (done) {508      var test = request(this.app).post('/')509      test.set('Content-Encoding', 'identity')510      test.set('Content-Type', 'text/plain')511      test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))512      test.expect(200, '"name is 论"', done)513    })514515    it('should support gzip encoding', function (done) {516      var test = request(this.app).post('/')517      test.set('Content-Encoding', 'gzip')518      test.set('Content-Type', 'text/plain')519      test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))520      test.expect(200, '"name is 论"', done)521    })522523    it('should support deflate encoding', function (done) {524      var test = request(this.app).post('/')525      test.set('Content-Encoding', 'deflate')526      test.set('Content-Type', 'text/plain')527      test.write(Buffer.from('789ccb4bcc4d55c82c5678b16e17001a6f050e', 'hex'))528      test.expect(200, '"name is 论"', done)529    })530531    it('should be case-insensitive', function (done) {532      var test = request(this.app).post('/')533      test.set('Content-Encoding', 'GZIP')534      test.set('Content-Type', 'text/plain')535      test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))536      test.expect(200, '"name is 论"', done)537    })538539    it('should 415 on unknown encoding', function (done) {540      var test = request(this.app).post('/')541      test.set('Content-Encoding', 'nulls')542      test.set('Content-Type', 'text/plain')543      test.write(Buffer.from('000000000000', 'hex'))544      test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done)545    })546  })547})548549function createApp (options) {550  var app = express()551552  app.use(express.text(options))553554  app.use(function (err, req, res, next) {555    res.status(err.status || 500)556    res.send(String(req.headers['x-error-property']557      ? err[req.headers['x-error-property']]558      : ('[' + err.type + '] ' + err.message)))559  })560561  app.post('/', function (req, res) {562    res.json(req.body)563  })564565  return app566}

Code quality findings 61

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 server = createApp({ defaultCharset: 'koi8-r' })
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(server).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var server = createApp({ defaultCharset: 'koi8-r' })
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var test = request(server).post('/')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var buf = Buffer.alloc(1028, '.')
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(1028, '.')
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(1028, '.')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var buf = Buffer.alloc(1028, '.')
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('/')
Can lead to race conditions; consider Promises or async/await for better control
info correctness set-timeout
setTimeout(function () {
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 app = createApp({ type: accept })
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
return req.headers['content-type'] === 'text/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) throw new Error('no leading space')
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 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 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.