docs: update homepage link http to https (#5920)
[express.git] / test / express.raw.js
blobf6513a7d48da54adc4c4685d0591d74c64c43820
1 'use strict'
3 var assert = require('assert')
4 var asyncHooks = tryRequire('async_hooks')
5 var Buffer = require('safe-buffer').Buffer
6 var express = require('..')
7 var request = require('supertest')
9 var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function'
10 ? describe
11 : describe.skip
13 describe('express.raw()', function () {
14 before(function () {
15 this.app = createApp()
18 it('should parse application/octet-stream', function (done) {
19 request(this.app)
20 .post('/')
21 .set('Content-Type', 'application/octet-stream')
22 .send('the user is tobi')
23 .expect(200, { buf: '746865207573657220697320746f6269' }, done)
26 it('should 400 when invalid content-length', function (done) {
27 var app = express()
29 app.use(function (req, res, next) {
30 req.headers['content-length'] = '20' // bad length
31 next()
34 app.use(express.raw())
36 app.post('/', function (req, res) {
37 if (Buffer.isBuffer(req.body)) {
38 res.json({ buf: req.body.toString('hex') })
39 } else {
40 res.json(req.body)
44 request(app)
45 .post('/')
46 .set('Content-Type', 'application/octet-stream')
47 .send('stuff')
48 .expect(400, /content length/, done)
51 it('should handle Content-Length: 0', function (done) {
52 request(this.app)
53 .post('/')
54 .set('Content-Type', 'application/octet-stream')
55 .set('Content-Length', '0')
56 .expect(200, { buf: '' }, done)
59 it('should handle empty message-body', function (done) {
60 request(this.app)
61 .post('/')
62 .set('Content-Type', 'application/octet-stream')
63 .set('Transfer-Encoding', 'chunked')
64 .send('')
65 .expect(200, { buf: '' }, done)
68 it('should handle duplicated middleware', function (done) {
69 var app = express()
71 app.use(express.raw())
72 app.use(express.raw())
74 app.post('/', function (req, res) {
75 if (Buffer.isBuffer(req.body)) {
76 res.json({ buf: req.body.toString('hex') })
77 } else {
78 res.json(req.body)
82 request(app)
83 .post('/')
84 .set('Content-Type', 'application/octet-stream')
85 .send('the user is tobi')
86 .expect(200, { buf: '746865207573657220697320746f6269' }, done)
89 describe('with limit option', function () {
90 it('should 413 when over limit with Content-Length', function (done) {
91 var buf = Buffer.alloc(1028, '.')
92 var app = createApp({ limit: '1kb' })
93 var test = request(app).post('/')
94 test.set('Content-Type', 'application/octet-stream')
95 test.set('Content-Length', '1028')
96 test.write(buf)
97 test.expect(413, done)
100 it('should 413 when over limit with chunked encoding', function (done) {
101 var buf = Buffer.alloc(1028, '.')
102 var app = createApp({ limit: '1kb' })
103 var test = request(app).post('/')
104 test.set('Content-Type', 'application/octet-stream')
105 test.set('Transfer-Encoding', 'chunked')
106 test.write(buf)
107 test.expect(413, done)
110 it('should 413 when inflated body over limit', function (done) {
111 var app = createApp({ limit: '1kb' })
112 var test = request(app).post('/')
113 test.set('Content-Encoding', 'gzip')
114 test.set('Content-Type', 'application/octet-stream')
115 test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a14704040000', 'hex'))
116 test.expect(413, done)
119 it('should accept number of bytes', function (done) {
120 var buf = Buffer.alloc(1028, '.')
121 var app = createApp({ limit: 1024 })
122 var test = request(app).post('/')
123 test.set('Content-Type', 'application/octet-stream')
124 test.write(buf)
125 test.expect(413, done)
128 it('should not change when options altered', function (done) {
129 var buf = Buffer.alloc(1028, '.')
130 var options = { limit: '1kb' }
131 var app = createApp(options)
133 options.limit = '100kb'
135 var test = request(app).post('/')
136 test.set('Content-Type', 'application/octet-stream')
137 test.write(buf)
138 test.expect(413, done)
141 it('should not hang response', function (done) {
142 var buf = Buffer.alloc(10240, '.')
143 var app = createApp({ limit: '8kb' })
144 var test = request(app).post('/')
145 test.set('Content-Type', 'application/octet-stream')
146 test.write(buf)
147 test.write(buf)
148 test.write(buf)
149 test.expect(413, done)
152 it('should not error when inflating', function (done) {
153 var app = createApp({ limit: '1kb' })
154 var test = request(app).post('/')
155 test.set('Content-Encoding', 'gzip')
156 test.set('Content-Type', 'application/octet-stream')
157 test.write(Buffer.from('1f8b080000000000000ad3d31b05a360148c64000087e5a147040400', 'hex'))
158 test.expect(413, done)
162 describe('with inflate option', function () {
163 describe('when false', function () {
164 before(function () {
165 this.app = createApp({ inflate: false })
168 it('should not accept content-encoding', function (done) {
169 var test = request(this.app).post('/')
170 test.set('Content-Encoding', 'gzip')
171 test.set('Content-Type', 'application/octet-stream')
172 test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
173 test.expect(415, '[encoding.unsupported] content encoding unsupported', done)
177 describe('when true', function () {
178 before(function () {
179 this.app = createApp({ inflate: true })
182 it('should accept content-encoding', function (done) {
183 var test = request(this.app).post('/')
184 test.set('Content-Encoding', 'gzip')
185 test.set('Content-Type', 'application/octet-stream')
186 test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
187 test.expect(200, { buf: '6e616d653de8aeba' }, done)
192 describe('with type option', function () {
193 describe('when "application/vnd+octets"', function () {
194 before(function () {
195 this.app = createApp({ type: 'application/vnd+octets' })
198 it('should parse for custom type', function (done) {
199 var test = request(this.app).post('/')
200 test.set('Content-Type', 'application/vnd+octets')
201 test.write(Buffer.from('000102', 'hex'))
202 test.expect(200, { buf: '000102' }, done)
205 it('should ignore standard type', function (done) {
206 var test = request(this.app).post('/')
207 test.set('Content-Type', 'application/octet-stream')
208 test.write(Buffer.from('000102', 'hex'))
209 test.expect(200, '', done)
213 describe('when ["application/octet-stream", "application/vnd+octets"]', function () {
214 before(function () {
215 this.app = createApp({
216 type: ['application/octet-stream', 'application/vnd+octets']
220 it('should parse "application/octet-stream"', function (done) {
221 var test = request(this.app).post('/')
222 test.set('Content-Type', 'application/octet-stream')
223 test.write(Buffer.from('000102', 'hex'))
224 test.expect(200, { buf: '000102' }, done)
227 it('should parse "application/vnd+octets"', function (done) {
228 var test = request(this.app).post('/')
229 test.set('Content-Type', 'application/vnd+octets')
230 test.write(Buffer.from('000102', 'hex'))
231 test.expect(200, { buf: '000102' }, done)
234 it('should ignore "application/x-foo"', function (done) {
235 var test = request(this.app).post('/')
236 test.set('Content-Type', 'application/x-foo')
237 test.write(Buffer.from('000102', 'hex'))
238 test.expect(200, '', done)
242 describe('when a function', function () {
243 it('should parse when truthy value returned', function (done) {
244 var app = createApp({ type: accept })
246 function accept (req) {
247 return req.headers['content-type'] === 'application/vnd.octet'
250 var test = request(app).post('/')
251 test.set('Content-Type', 'application/vnd.octet')
252 test.write(Buffer.from('000102', 'hex'))
253 test.expect(200, { buf: '000102' }, done)
256 it('should work without content-type', function (done) {
257 var app = createApp({ type: accept })
259 function accept (req) {
260 return true
263 var test = request(app).post('/')
264 test.write(Buffer.from('000102', 'hex'))
265 test.expect(200, { buf: '000102' }, done)
268 it('should not invoke without a body', function (done) {
269 var app = createApp({ type: accept })
271 function accept (req) {
272 throw new Error('oops!')
275 request(app)
276 .get('/')
277 .expect(404, done)
282 describe('with verify option', function () {
283 it('should assert value is function', function () {
284 assert.throws(createApp.bind(null, { verify: 'lol' }),
285 /TypeError: option verify must be function/)
288 it('should error from verify', function (done) {
289 var app = createApp({
290 verify: function (req, res, buf) {
291 if (buf[0] === 0x00) throw new Error('no leading null')
295 var test = request(app).post('/')
296 test.set('Content-Type', 'application/octet-stream')
297 test.write(Buffer.from('000102', 'hex'))
298 test.expect(403, '[entity.verify.failed] no leading null', done)
301 it('should allow custom codes', function (done) {
302 var app = createApp({
303 verify: function (req, res, buf) {
304 if (buf[0] !== 0x00) return
305 var err = new Error('no leading null')
306 err.status = 400
307 throw err
311 var test = request(app).post('/')
312 test.set('Content-Type', 'application/octet-stream')
313 test.write(Buffer.from('000102', 'hex'))
314 test.expect(400, '[entity.verify.failed] no leading null', done)
317 it('should allow pass-through', function (done) {
318 var app = createApp({
319 verify: function (req, res, buf) {
320 if (buf[0] === 0x00) throw new Error('no leading null')
324 var test = request(app).post('/')
325 test.set('Content-Type', 'application/octet-stream')
326 test.write(Buffer.from('0102', 'hex'))
327 test.expect(200, { buf: '0102' }, done)
331 describeAsyncHooks('async local storage', function () {
332 before(function () {
333 var app = express()
334 var store = { foo: 'bar' }
336 app.use(function (req, res, next) {
337 req.asyncLocalStorage = new asyncHooks.AsyncLocalStorage()
338 req.asyncLocalStorage.run(store, next)
341 app.use(express.raw())
343 app.use(function (req, res, next) {
344 var local = req.asyncLocalStorage.getStore()
346 if (local) {
347 res.setHeader('x-store-foo', String(local.foo))
350 next()
353 app.use(function (err, req, res, next) {
354 var local = req.asyncLocalStorage.getStore()
356 if (local) {
357 res.setHeader('x-store-foo', String(local.foo))
360 res.status(err.status || 500)
361 res.send('[' + err.type + '] ' + err.message)
364 app.post('/', function (req, res) {
365 if (Buffer.isBuffer(req.body)) {
366 res.json({ buf: req.body.toString('hex') })
367 } else {
368 res.json(req.body)
372 this.app = app
375 it('should presist store', function (done) {
376 request(this.app)
377 .post('/')
378 .set('Content-Type', 'application/octet-stream')
379 .send('the user is tobi')
380 .expect(200)
381 .expect('x-store-foo', 'bar')
382 .expect({ buf: '746865207573657220697320746f6269' })
383 .end(done)
386 it('should presist store when unmatched content-type', function (done) {
387 request(this.app)
388 .post('/')
389 .set('Content-Type', 'application/fizzbuzz')
390 .send('buzz')
391 .expect(200)
392 .expect('x-store-foo', 'bar')
393 .end(done)
396 it('should presist store when inflated', function (done) {
397 var test = request(this.app).post('/')
398 test.set('Content-Encoding', 'gzip')
399 test.set('Content-Type', 'application/octet-stream')
400 test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
401 test.expect(200)
402 test.expect('x-store-foo', 'bar')
403 test.expect({ buf: '6e616d653de8aeba' })
404 test.end(done)
407 it('should presist store when inflate error', function (done) {
408 var test = request(this.app).post('/')
409 test.set('Content-Encoding', 'gzip')
410 test.set('Content-Type', 'application/octet-stream')
411 test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad6080000', 'hex'))
412 test.expect(400)
413 test.expect('x-store-foo', 'bar')
414 test.end(done)
417 it('should presist store when limit exceeded', function (done) {
418 request(this.app)
419 .post('/')
420 .set('Content-Type', 'application/octet-stream')
421 .send('the user is ' + Buffer.alloc(1024 * 100, '.').toString())
422 .expect(413)
423 .expect('x-store-foo', 'bar')
424 .end(done)
428 describe('charset', function () {
429 before(function () {
430 this.app = createApp()
433 it('should ignore charset', function (done) {
434 var test = request(this.app).post('/')
435 test.set('Content-Type', 'application/octet-stream; charset=utf-8')
436 test.write(Buffer.from('6e616d6520697320e8aeba', 'hex'))
437 test.expect(200, { buf: '6e616d6520697320e8aeba' }, done)
441 describe('encoding', function () {
442 before(function () {
443 this.app = createApp({ limit: '10kb' })
446 it('should parse without encoding', function (done) {
447 var test = request(this.app).post('/')
448 test.set('Content-Type', 'application/octet-stream')
449 test.write(Buffer.from('6e616d653de8aeba', 'hex'))
450 test.expect(200, { buf: '6e616d653de8aeba' }, done)
453 it('should support identity encoding', function (done) {
454 var test = request(this.app).post('/')
455 test.set('Content-Encoding', 'identity')
456 test.set('Content-Type', 'application/octet-stream')
457 test.write(Buffer.from('6e616d653de8aeba', 'hex'))
458 test.expect(200, { buf: '6e616d653de8aeba' }, done)
461 it('should support gzip encoding', function (done) {
462 var test = request(this.app).post('/')
463 test.set('Content-Encoding', 'gzip')
464 test.set('Content-Type', 'application/octet-stream')
465 test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
466 test.expect(200, { buf: '6e616d653de8aeba' }, done)
469 it('should support deflate encoding', function (done) {
470 var test = request(this.app).post('/')
471 test.set('Content-Encoding', 'deflate')
472 test.set('Content-Type', 'application/octet-stream')
473 test.write(Buffer.from('789ccb4bcc4db57db16e17001068042f', 'hex'))
474 test.expect(200, { buf: '6e616d653de8aeba' }, done)
477 it('should be case-insensitive', function (done) {
478 var test = request(this.app).post('/')
479 test.set('Content-Encoding', 'GZIP')
480 test.set('Content-Type', 'application/octet-stream')
481 test.write(Buffer.from('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
482 test.expect(200, { buf: '6e616d653de8aeba' }, done)
485 it('should 415 on unknown encoding', function (done) {
486 var test = request(this.app).post('/')
487 test.set('Content-Encoding', 'nulls')
488 test.set('Content-Type', 'application/octet-stream')
489 test.write(Buffer.from('000000000000', 'hex'))
490 test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done)
495 function createApp (options) {
496 var app = express()
498 app.use(express.raw(options))
500 app.use(function (err, req, res, next) {
501 res.status(err.status || 500)
502 res.send(String(req.headers['x-error-property']
503 ? err[req.headers['x-error-property']]
504 : ('[' + err.type + '] ' + err.message)))
507 app.post('/', function (req, res) {
508 if (Buffer.isBuffer(req.body)) {
509 res.json({ buf: req.body.toString('hex') })
510 } else {
511 res.json(req.body)
515 return app
518 function tryRequire (name) {
519 try {
520 return require(name)
521 } catch (e) {
522 return {}