Use let or const to avoid scope issues and hoisting
var assert = require('node:assert')
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}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.