cleanup: remove unnecessary require for global Buffer
[express.git] / test / express.text.js
blob1bcc034b86f9376a4f81e40b0e730470e903f314
1 'use strict'
3 var assert = require('assert')
4 var asyncHooks = tryRequire('async_hooks')
5 var express = require('..')
6 var request = require('supertest')
8 var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function'
9 ? describe
10 : describe.skip
12 describe('express.text()', function () {
13 before(function () {
14 this.app = createApp()
17 it('should parse text/plain', function (done) {
18 request(this.app)
19 .post('/')
20 .set('Content-Type', 'text/plain')
21 .send('user is tobi')
22 .expect(200, '"user is tobi"', done)
25 it('should 400 when invalid content-length', function (done) {
26 var app = express()
28 app.use(function (req, res, next) {
29 req.headers['content-length'] = '20' // bad length
30 next()
33 app.use(express.text())
35 app.post('/', function (req, res) {
36 res.json(req.body)
39 request(app)
40 .post('/')
41 .set('Content-Type', 'text/plain')
42 .send('user')
43 .expect(400, /content length/, done)
46 it('should handle Content-Length: 0', function (done) {
47 request(createApp({ limit: '1kb' }))
48 .post('/')
49 .set('Content-Type', 'text/plain')
50 .set('Content-Length', '0')
51 .expect(200, '""', done)
54 it('should handle empty message-body', function (done) {
55 request(createApp({ limit: '1kb' }))
56 .post('/')
57 .set('Content-Type', 'text/plain')
58 .set('Transfer-Encoding', 'chunked')
59 .send('')
60 .expect(200, '""', done)
63 it('should handle duplicated middleware', function (done) {
64 var app = express()
66 app.use(express.text())
67 app.use(express.text())
69 app.post('/', function (req, res) {
70 res.json(req.body)
73 request(app)
74 .post('/')
75 .set('Content-Type', 'text/plain')
76 .send('user is tobi')
77 .expect(200, '"user is tobi"', done)
80 describe('with defaultCharset option', function () {
81 it('should change default charset', function (done) {
82 var server = createApp({ defaultCharset: 'koi8-r' })
83 var test = request(server).post('/')
84 test.set('Content-Type', 'text/plain')
85 test.write(Buffer.from('6e616d6520697320cec5d4', 'hex'))
86 test.expect(200, '"name is нет"', done)
89 it('should honor content-type charset', function (done) {
90 var server = createApp({ defaultCharset: 'koi8-r' })
91 var test = request(server).post('/')
92 test.set('Content-Type', 'text/plain; charset=utf-8')
93 test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))
94 test.expect(200, '"name is 论"', done)
98 describe('with limit option', function () {
99 it('should 413 when over limit with Content-Length', function (done) {
100 var buf = Buffer.alloc(1028, '.')
101 request(createApp({ limit: '1kb' }))
102 .post('/')
103 .set('Content-Type', 'text/plain')
104 .set('Content-Length', '1028')
105 .send(buf.toString())
106 .expect(413, done)
109 it('should 413 when over limit with chunked encoding', function (done) {
110 var app = createApp({ limit: '1kb' })
111 var buf = Buffer.alloc(1028, '.')
112 var test = request(app).post('/')
113 test.set('Content-Type', 'text/plain')
114 test.set('Transfer-Encoding', 'chunked')
115 test.write(buf.toString())
116 test.expect(413, done)
119 it('should 413 when inflated body over limit', function (done) {
120 var app = createApp({ limit: '1kb' })
121 var test = request(app).post('/')
122 test.set('Content-Encoding', 'gzip')
123 test.set('Content-Type', 'text/plain')
124 test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a14704040000', 'hex'))
125 test.expect(413, done)
128 it('should accept number of bytes', function (done) {
129 var buf = Buffer.alloc(1028, '.')
130 request(createApp({ limit: 1024 }))
131 .post('/')
132 .set('Content-Type', 'text/plain')
133 .send(buf.toString())
134 .expect(413, done)
137 it('should not change when options altered', function (done) {
138 var buf = Buffer.alloc(1028, '.')
139 var options = { limit: '1kb' }
140 var app = createApp(options)
142 options.limit = '100kb'
144 request(app)
145 .post('/')
146 .set('Content-Type', 'text/plain')
147 .send(buf.toString())
148 .expect(413, done)
151 it('should not hang response', function (done) {
152 var app = createApp({ limit: '8kb' })
153 var buf = Buffer.alloc(10240, '.')
154 var test = request(app).post('/')
155 test.set('Content-Type', 'text/plain')
156 test.write(buf)
157 test.write(buf)
158 test.write(buf)
159 test.expect(413, done)
162 it('should not error when inflating', function (done) {
163 var app = createApp({ limit: '1kb' })
164 var test = request(app).post('/')
165 test.set('Content-Encoding', 'gzip')
166 test.set('Content-Type', 'text/plain')
167 test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a1470404', 'hex'))
168 setTimeout(function () {
169 test.expect(413, done)
170 }, 100)
174 describe('with inflate option', function () {
175 describe('when false', function () {
176 before(function () {
177 this.app = createApp({ inflate: false })
180 it('should not accept content-encoding', function (done) {
181 var test = request(this.app).post('/')
182 test.set('Content-Encoding', 'gzip')
183 test.set('Content-Type', 'text/plain')
184 test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))
185 test.expect(415, '[encoding.unsupported] content encoding unsupported', done)
189 describe('when true', function () {
190 before(function () {
191 this.app = createApp({ inflate: true })
194 it('should accept content-encoding', function (done) {
195 var test = request(this.app).post('/')
196 test.set('Content-Encoding', 'gzip')
197 test.set('Content-Type', 'text/plain')
198 test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))
199 test.expect(200, '"name is 论"', done)
204 describe('with type option', function () {
205 describe('when "text/html"', function () {
206 before(function () {
207 this.app = createApp({ type: 'text/html' })
210 it('should parse for custom type', function (done) {
211 request(this.app)
212 .post('/')
213 .set('Content-Type', 'text/html')
214 .send('<b>tobi</b>')
215 .expect(200, '"<b>tobi</b>"', done)
218 it('should ignore standard type', function (done) {
219 request(this.app)
220 .post('/')
221 .set('Content-Type', 'text/plain')
222 .send('user is tobi')
223 .expect(200, '', done)
227 describe('when ["text/html", "text/plain"]', function () {
228 before(function () {
229 this.app = createApp({ type: ['text/html', 'text/plain'] })
232 it('should parse "text/html"', function (done) {
233 request(this.app)
234 .post('/')
235 .set('Content-Type', 'text/html')
236 .send('<b>tobi</b>')
237 .expect(200, '"<b>tobi</b>"', done)
240 it('should parse "text/plain"', function (done) {
241 request(this.app)
242 .post('/')
243 .set('Content-Type', 'text/plain')
244 .send('tobi')
245 .expect(200, '"tobi"', done)
248 it('should ignore "text/xml"', function (done) {
249 request(this.app)
250 .post('/')
251 .set('Content-Type', 'text/xml')
252 .send('<user>tobi</user>')
253 .expect(200, '', done)
257 describe('when a function', function () {
258 it('should parse when truthy value returned', function (done) {
259 var app = createApp({ type: accept })
261 function accept (req) {
262 return req.headers['content-type'] === 'text/vnd.something'
265 request(app)
266 .post('/')
267 .set('Content-Type', 'text/vnd.something')
268 .send('user is tobi')
269 .expect(200, '"user is tobi"', done)
272 it('should work without content-type', function (done) {
273 var app = createApp({ type: accept })
275 function accept (req) {
276 return true
279 var test = request(app).post('/')
280 test.write('user is tobi')
281 test.expect(200, '"user is tobi"', done)
284 it('should not invoke without a body', function (done) {
285 var app = createApp({ type: accept })
287 function accept (req) {
288 throw new Error('oops!')
291 request(app)
292 .get('/')
293 .expect(404, done)
298 describe('with verify option', function () {
299 it('should assert value is function', function () {
300 assert.throws(createApp.bind(null, { verify: 'lol' }),
301 /TypeError: option verify must be function/)
304 it('should error from verify', function (done) {
305 var app = createApp({
306 verify: function (req, res, buf) {
307 if (buf[0] === 0x20) throw new Error('no leading space')
311 request(app)
312 .post('/')
313 .set('Content-Type', 'text/plain')
314 .send(' user is tobi')
315 .expect(403, '[entity.verify.failed] no leading space', done)
318 it('should allow custom codes', function (done) {
319 var app = createApp({
320 verify: function (req, res, buf) {
321 if (buf[0] !== 0x20) return
322 var err = new Error('no leading space')
323 err.status = 400
324 throw err
328 request(app)
329 .post('/')
330 .set('Content-Type', 'text/plain')
331 .send(' user is tobi')
332 .expect(400, '[entity.verify.failed] no leading space', done)
335 it('should allow pass-through', function (done) {
336 var app = createApp({
337 verify: function (req, res, buf) {
338 if (buf[0] === 0x20) throw new Error('no leading space')
342 request(app)
343 .post('/')
344 .set('Content-Type', 'text/plain')
345 .send('user is tobi')
346 .expect(200, '"user is tobi"', done)
349 it('should 415 on unknown charset prior to verify', function (done) {
350 var app = createApp({
351 verify: function (req, res, buf) {
352 throw new Error('unexpected verify call')
356 var test = request(app).post('/')
357 test.set('Content-Type', 'text/plain; charset=x-bogus')
358 test.write(Buffer.from('00000000', 'hex'))
359 test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done)
363 describeAsyncHooks('async local storage', function () {
364 before(function () {
365 var app = express()
366 var store = { foo: 'bar' }
368 app.use(function (req, res, next) {
369 req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage()
370 req.asyncLocalStorage.run(store, next)
373 app.use(express.text())
375 app.use(function (req, res, next) {
376 var local = req.asyncLocalStorage.getStore()
378 if (local) {
379 res.setHeader('x-store-foo', String(local.foo))
382 next()
385 app.use(function (err, req, res, next) {
386 var local = req.asyncLocalStorage.getStore()
388 if (local) {
389 res.setHeader('x-store-foo', String(local.foo))
392 res.status(err.status || 500)
393 res.send('[' + err.type + '] ' + err.message)
396 app.post('/', function (req, res) {
397 res.json(req.body)
400 this.app = app
403 it('should presist store', function (done) {
404 request(this.app)
405 .post('/')
406 .set('Content-Type', 'text/plain')
407 .send('user is tobi')
408 .expect(200)
409 .expect('x-store-foo', 'bar')
410 .expect('"user is tobi"')
411 .end(done)
414 it('should presist store when unmatched content-type', function (done) {
415 request(this.app)
416 .post('/')
417 .set('Content-Type', 'application/fizzbuzz')
418 .send('buzz')
419 .expect(200)
420 .expect('x-store-foo', 'bar')
421 .end(done)
424 it('should presist store when inflated', function (done) {
425 var test = request(this.app).post('/')
426 test.set('Content-Encoding', 'gzip')
427 test.set('Content-Type', 'text/plain')
428 test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))
429 test.expect(200)
430 test.expect('x-store-foo', 'bar')
431 test.expect('"name is 论"')
432 test.end(done)
435 it('should presist store when inflate error', function (done) {
436 var test = request(this.app).post('/')
437 test.set('Content-Encoding', 'gzip')
438 test.set('Content-Type', 'text/plain')
439 test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b0000', 'hex'))
440 test.expect(400)
441 test.expect('x-store-foo', 'bar')
442 test.end(done)
445 it('should presist store when limit exceeded', function (done) {
446 request(this.app)
447 .post('/')
448 .set('Content-Type', 'text/plain')
449 .send('user is ' + Buffer.alloc(1024 * 100, '.').toString())
450 .expect(413)
451 .expect('x-store-foo', 'bar')
452 .end(done)
456 describe('charset', function () {
457 before(function () {
458 this.app = createApp()
461 it('should parse utf-8', function (done) {
462 var test = request(this.app).post('/')
463 test.set('Content-Type', 'text/plain; charset=utf-8')
464 test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))
465 test.expect(200, '"name is 论"', done)
468 it('should parse codepage charsets', function (done) {
469 var test = request(this.app).post('/')
470 test.set('Content-Type', 'text/plain; charset=koi8-r')
471 test.write(Buffer.from('6e616d6520697320cec5d4', 'hex'))
472 test.expect(200, '"name is нет"', done)
475 it('should parse when content-length != char length', function (done) {
476 var test = request(this.app).post('/')
477 test.set('Content-Type', 'text/plain; charset=utf-8')
478 test.set('Content-Length', '11')
479 test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))
480 test.expect(200, '"name is 论"', done)
483 it('should default to utf-8', function (done) {
484 var test = request(this.app).post('/')
485 test.set('Content-Type', 'text/plain')
486 test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))
487 test.expect(200, '"name is 论"', done)
490 it('should 415 on unknown charset', function (done) {
491 var test = request(this.app).post('/')
492 test.set('Content-Type', 'text/plain; charset=x-bogus')
493 test.write(Buffer.from('00000000', 'hex'))
494 test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done)
498 describe('encoding', function () {
499 before(function () {
500 this.app = createApp({ limit: '10kb' })
503 it('should parse without encoding', function (done) {
504 var test = request(this.app).post('/')
505 test.set('Content-Type', 'text/plain')
506 test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))
507 test.expect(200, '"name is 论"', done)
510 it('should support identity encoding', function (done) {
511 var test = request(this.app).post('/')
512 test.set('Content-Encoding', 'identity')
513 test.set('Content-Type', 'text/plain')
514 test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))
515 test.expect(200, '"name is 论"', done)
518 it('should support gzip encoding', function (done) {
519 var test = request(this.app).post('/')
520 test.set('Content-Encoding', 'gzip')
521 test.set('Content-Type', 'text/plain')
522 test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))
523 test.expect(200, '"name is 论"', done)
526 it('should support deflate encoding', function (done) {
527 var test = request(this.app).post('/')
528 test.set('Content-Encoding', 'deflate')
529 test.set('Content-Type', 'text/plain')
530 test.write(Buffer.from('789ccb4bcc4d55c82c5678b16e17001a6f050e', 'hex'))
531 test.expect(200, '"name is 论"', done)
534 it('should be case-insensitive', function (done) {
535 var test = request(this.app).post('/')
536 test.set('Content-Encoding', 'GZIP')
537 test.set('Content-Type', 'text/plain')
538 test.write(Buffer.from('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))
539 test.expect(200, '"name is 论"', done)
542 it('should 415 on unknown encoding', function (done) {
543 var test = request(this.app).post('/')
544 test.set('Content-Encoding', 'nulls')
545 test.set('Content-Type', 'text/plain')
546 test.write(Buffer.from('000000000000', 'hex'))
547 test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done)
552 function createApp (options) {
553 var app = express()
555 app.use(express.text(options))
557 app.use(function (err, req, res, next) {
558 res.status(err.status || 500)
559 res.send(String(req.headers['x-error-property']
560 ? err[req.headers['x-error-property']]
561 : ('[' + err.type + '] ' + err.message)))
564 app.post('/', function (req, res) {
565 res.json(req.body)
568 return app
571 function tryRequire (name) {
572 try {
573 return require(name)
574 } catch (e) {
575 return {}