123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- 'use strict'
- var createError = require('http-errors')
- var getBody = require('raw-body')
- var iconv = require('iconv-lite')
- var onFinished = require('on-finished')
- var zlib = require('zlib')
- module.exports = read
- function read (req, res, next, parse, debug, options) {
- var length
- var opts = options
- var stream
-
- req._body = true
-
- var encoding = opts.encoding !== null
- ? opts.encoding
- : null
- var verify = opts.verify
- try {
-
- stream = contentstream(req, debug, opts.inflate)
- length = stream.length
- stream.length = undefined
- } catch (err) {
- return next(err)
- }
-
- opts.length = length
- opts.encoding = verify
- ? null
- : encoding
-
- if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) {
- return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
- charset: encoding.toLowerCase(),
- type: 'charset.unsupported'
- }))
- }
-
- debug('read body')
- getBody(stream, opts, function (error, body) {
- if (error) {
- var _error
- if (error.type === 'encoding.unsupported') {
-
- _error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
- charset: encoding.toLowerCase(),
- type: 'charset.unsupported'
- })
- } else {
-
- _error = createError(400, error)
- }
-
- stream.resume()
- onFinished(req, function onfinished () {
- next(createError(400, _error))
- })
- return
- }
-
- if (verify) {
- try {
- debug('verify body')
- verify(req, res, body, encoding)
- } catch (err) {
- next(createError(403, err, {
- body: body,
- type: err.type || 'entity.verify.failed'
- }))
- return
- }
- }
-
- var str = body
- try {
- debug('parse body')
- str = typeof body !== 'string' && encoding !== null
- ? iconv.decode(body, encoding)
- : body
- req.body = parse(str)
- } catch (err) {
- next(createError(400, err, {
- body: str,
- type: err.type || 'entity.parse.failed'
- }))
- return
- }
- next()
- })
- }
- function contentstream (req, debug, inflate) {
- var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()
- var length = req.headers['content-length']
- var stream
- debug('content-encoding "%s"', encoding)
- if (inflate === false && encoding !== 'identity') {
- throw createError(415, 'content encoding unsupported', {
- encoding: encoding,
- type: 'encoding.unsupported'
- })
- }
- switch (encoding) {
- case 'deflate':
- stream = zlib.createInflate()
- debug('inflate body')
- req.pipe(stream)
- break
- case 'gzip':
- stream = zlib.createGunzip()
- debug('gunzip body')
- req.pipe(stream)
- break
- case 'identity':
- stream = req
- stream.length = length
- break
- default:
- throw createError(415, 'unsupported content encoding "' + encoding + '"', {
- encoding: encoding,
- type: 'encoding.unsupported'
- })
- }
- return stream
- }
|