Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50654 views
1
/*!
2
* body-parser
3
* Copyright(c) 2014 Jonathan Ong
4
* Copyright(c) 2014-2015 Douglas Christopher Wilson
5
* MIT Licensed
6
*/
7
8
'use strict'
9
10
/**
11
* Module dependencies.
12
* @private
13
*/
14
15
var bytes = require('bytes')
16
var contentType = require('content-type')
17
var createError = require('http-errors')
18
var debug = require('debug')('body-parser:json')
19
var read = require('../read')
20
var typeis = require('type-is')
21
22
/**
23
* Module exports.
24
*/
25
26
module.exports = json
27
28
/**
29
* RegExp to match the first non-space in a string.
30
*
31
* Allowed whitespace is defined in RFC 7159:
32
*
33
* ws = *(
34
* %x20 / ; Space
35
* %x09 / ; Horizontal tab
36
* %x0A / ; Line feed or New line
37
* %x0D ) ; Carriage return
38
*/
39
40
var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*(.)/ // eslint-disable-line no-control-regex
41
42
/**
43
* Create a middleware to parse JSON bodies.
44
*
45
* @param {object} [options]
46
* @return {function}
47
* @public
48
*/
49
50
function json (options) {
51
var opts = options || {}
52
53
var limit = typeof opts.limit !== 'number'
54
? bytes.parse(opts.limit || '100kb')
55
: opts.limit
56
var inflate = opts.inflate !== false
57
var reviver = opts.reviver
58
var strict = opts.strict !== false
59
var type = opts.type || 'application/json'
60
var verify = opts.verify || false
61
62
if (verify !== false && typeof verify !== 'function') {
63
throw new TypeError('option verify must be function')
64
}
65
66
// create the appropriate type checking function
67
var shouldParse = typeof type !== 'function'
68
? typeChecker(type)
69
: type
70
71
function parse (body) {
72
if (body.length === 0) {
73
// special-case empty json body, as it's a common client-side mistake
74
// TODO: maybe make this configurable or part of "strict" option
75
return {}
76
}
77
78
if (strict) {
79
var first = firstchar(body)
80
81
if (first !== '{' && first !== '[') {
82
debug('strict violation')
83
throw new SyntaxError('Unexpected token ' + first)
84
}
85
}
86
87
debug('parse json')
88
return JSON.parse(body, reviver)
89
}
90
91
return function jsonParser (req, res, next) {
92
if (req._body) {
93
debug('body already parsed')
94
next()
95
return
96
}
97
98
req.body = req.body || {}
99
100
// skip requests without bodies
101
if (!typeis.hasBody(req)) {
102
debug('skip empty body')
103
next()
104
return
105
}
106
107
debug('content-type %j', req.headers['content-type'])
108
109
// determine if request should be parsed
110
if (!shouldParse(req)) {
111
debug('skip parsing')
112
next()
113
return
114
}
115
116
// assert charset per RFC 7159 sec 8.1
117
var charset = getCharset(req) || 'utf-8'
118
if (charset.substr(0, 4) !== 'utf-') {
119
debug('invalid charset')
120
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
121
charset: charset
122
}))
123
return
124
}
125
126
// read
127
read(req, res, next, parse, debug, {
128
encoding: charset,
129
inflate: inflate,
130
limit: limit,
131
verify: verify
132
})
133
}
134
}
135
136
/**
137
* Get the first non-whitespace character in a string.
138
*
139
* @param {string} str
140
* @return {function}
141
* @private
142
*/
143
144
function firstchar (str) {
145
return FIRST_CHAR_REGEXP.exec(str)[1]
146
}
147
148
/**
149
* Get the charset of a request.
150
*
151
* @param {object} req
152
* @api private
153
*/
154
155
function getCharset (req) {
156
try {
157
return contentType.parse(req).parameters.charset.toLowerCase()
158
} catch (e) {
159
return undefined
160
}
161
}
162
163
/**
164
* Get the simple type checker.
165
*
166
* @param {string} type
167
* @return {function}
168
*/
169
170
function typeChecker (type) {
171
return function checkType (req) {
172
return Boolean(typeis(req, type))
173
}
174
}
175
176