Projekt

Obecné

Profil

Stáhnout (3.8 KB) Statistiky
| Větev: | Revize:
1
/*!
2
 * body-parser
3
 * Copyright(c) 2014-2015 Douglas Christopher Wilson
4
 * MIT Licensed
5
 */
6

    
7
'use strict'
8

    
9
/**
10
 * Module dependencies.
11
 * @private
12
 */
13

    
14
var createError = require('http-errors')
15
var getBody = require('raw-body')
16
var iconv = require('iconv-lite')
17
var onFinished = require('on-finished')
18
var zlib = require('zlib')
19

    
20
/**
21
 * Module exports.
22
 */
23

    
24
module.exports = read
25

    
26
/**
27
 * Read a request into a buffer and parse.
28
 *
29
 * @param {object} req
30
 * @param {object} res
31
 * @param {function} next
32
 * @param {function} parse
33
 * @param {function} debug
34
 * @param {object} options
35
 * @private
36
 */
37

    
38
function read (req, res, next, parse, debug, options) {
39
  var length
40
  var opts = options
41
  var stream
42

    
43
  // flag as parsed
44
  req._body = true
45

    
46
  // read options
47
  var encoding = opts.encoding !== null
48
    ? opts.encoding
49
    : null
50
  var verify = opts.verify
51

    
52
  try {
53
    // get the content stream
54
    stream = contentstream(req, debug, opts.inflate)
55
    length = stream.length
56
    stream.length = undefined
57
  } catch (err) {
58
    return next(err)
59
  }
60

    
61
  // set raw-body options
62
  opts.length = length
63
  opts.encoding = verify
64
    ? null
65
    : encoding
66

    
67
  // assert charset is supported
68
  if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) {
69
    return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
70
      charset: encoding.toLowerCase(),
71
      type: 'charset.unsupported'
72
    }))
73
  }
74

    
75
  // read body
76
  debug('read body')
77
  getBody(stream, opts, function (error, body) {
78
    if (error) {
79
      var _error
80

    
81
      if (error.type === 'encoding.unsupported') {
82
        // echo back charset
83
        _error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
84
          charset: encoding.toLowerCase(),
85
          type: 'charset.unsupported'
86
        })
87
      } else {
88
        // set status code on error
89
        _error = createError(400, error)
90
      }
91

    
92
      // read off entire request
93
      stream.resume()
94
      onFinished(req, function onfinished () {
95
        next(createError(400, _error))
96
      })
97
      return
98
    }
99

    
100
    // verify
101
    if (verify) {
102
      try {
103
        debug('verify body')
104
        verify(req, res, body, encoding)
105
      } catch (err) {
106
        next(createError(403, err, {
107
          body: body,
108
          type: err.type || 'entity.verify.failed'
109
        }))
110
        return
111
      }
112
    }
113

    
114
    // parse
115
    var str = body
116
    try {
117
      debug('parse body')
118
      str = typeof body !== 'string' && encoding !== null
119
        ? iconv.decode(body, encoding)
120
        : body
121
      req.body = parse(str)
122
    } catch (err) {
123
      next(createError(400, err, {
124
        body: str,
125
        type: err.type || 'entity.parse.failed'
126
      }))
127
      return
128
    }
129

    
130
    next()
131
  })
132
}
133

    
134
/**
135
 * Get the content stream of the request.
136
 *
137
 * @param {object} req
138
 * @param {function} debug
139
 * @param {boolean} [inflate=true]
140
 * @return {object}
141
 * @api private
142
 */
143

    
144
function contentstream (req, debug, inflate) {
145
  var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()
146
  var length = req.headers['content-length']
147
  var stream
148

    
149
  debug('content-encoding "%s"', encoding)
150

    
151
  if (inflate === false && encoding !== 'identity') {
152
    throw createError(415, 'content encoding unsupported', {
153
      encoding: encoding,
154
      type: 'encoding.unsupported'
155
    })
156
  }
157

    
158
  switch (encoding) {
159
    case 'deflate':
160
      stream = zlib.createInflate()
161
      debug('inflate body')
162
      req.pipe(stream)
163
      break
164
    case 'gzip':
165
      stream = zlib.createGunzip()
166
      debug('gunzip body')
167
      req.pipe(stream)
168
      break
169
    case 'identity':
170
      stream = req
171
      stream.length = length
172
      break
173
    default:
174
      throw createError(415, 'unsupported content encoding "' + encoding + '"', {
175
        encoding: encoding,
176
        type: 'encoding.unsupported'
177
      })
178
  }
179

    
180
  return stream
181
}
    (1-1/1)