Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
converted json parser to use generic parser
  • Loading branch information
Shawn Dellysse authored and sdellysse committed Apr 17, 2020
commit f28e87ff2ac59dae9ec179a63470a4a5499b552e
145 changes: 27 additions & 118 deletions lib/types/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,9 @@
* @private
*/

var bytes = require('bytes')
var contentType = require('content-type')
var createError = require('http-errors')
var assign = require('object-assign')
var genericParser = require('../generic-parser')
var debug = require('debug')('body-parser:json')
var read = require('../read')
var typeis = require('type-is')

/**
* Module exports.
Expand Down Expand Up @@ -47,99 +44,39 @@ var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*(.)/ // eslint-disable-line no-cont
* @public
*/

function json (options) {
function json(options) {
var opts = options || {}

var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var inflate = opts.inflate !== false
var reviver = opts.reviver
var strict = opts.strict !== false
var type = opts.type || 'application/json'
var verify = opts.verify || false
var parser = opts.parser || JSON.parse
var type = opts.type || 'application/json'

if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}

// create the appropriate type checking function
var shouldParse = typeof type !== 'function'
? typeChecker(type)
: type

function parse (body) {
if (body.length === 0) {
// special-case empty json body, as it's a common client-side mistake
// TODO: maybe make this configurable or part of "strict" option
return {}
}
return genericParser(assign({}, opts, {
type: type,

if (strict) {
var first = firstchar(body)
charset: function validateCharset(charset) {
return charset.substr(0, 4) === 'utf-'
},

if (first !== '{' && first !== '[') {
debug('strict violation')
throw createStrictSyntaxError(parser, reviver, body, first)
parse: function parse(buf) {
if (buf.length === 0) {
// special-case empty json body, as it's a common client-side mistake
// TODO: maybe make this configurable or part of "strict" option
return {}
}
}

try {
debug('parse json')
return parser(body, reviver)
} catch (e) {
throw normalizeJsonSyntaxError(e, {
message: e.message,
stack: e.stack
})
}
}

return function jsonParser (req, res, next) {
if (req._body) {
debug('body already parsed')
next()
return
}

req.body = req.body || {}

// skip requests without bodies
if (!typeis.hasBody(req)) {
debug('skip empty body')
next()
return
}

debug('content-type %j', req.headers['content-type'])

// determine if request should be parsed
if (!shouldParse(req)) {
debug('skip parsing')
next()
return
}

// assert charset per RFC 7159 sec 8.1
var charset = getCharset(req) || 'utf-8'
if (charset.substr(0, 4) !== 'utf-') {
debug('invalid charset')
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
charset: charset,
type: 'charset.unsupported'
}))
return
try {
debug('parse json')
return parser(body, reviver)
} catch (e) {
throw normalizeJsonSyntaxError(e, {
message: e.message,
stack: e.stack
})
}
}

// read
read(req, res, next, parse, debug, {
encoding: charset,
inflate: inflate,
limit: limit,
verify: verify
})
}
}))
}

/**
Expand All @@ -151,7 +88,7 @@ function json (options) {
* @private
*/

function createStrictSyntaxError (parser, reviver, str, char) {
function createStrictSyntaxError(parser, reviver, str, char) {
var index = str.indexOf(char)
var partial = str.substring(0, index) + '#'

Expand All @@ -173,25 +110,10 @@ function createStrictSyntaxError (parser, reviver, str, char) {
* @private
*/

function firstchar (str) {
function firstchar(str) {
return FIRST_CHAR_REGEXP.exec(str)[1]
}

/**
* Get the charset of a request.
*
* @param {object} req
* @api private
*/

function getCharset (req) {
try {
return (contentType.parse(req).parameters.charset || '').toLowerCase()
} catch (e) {
return undefined
}
}

/**
* Normalize a SyntaxError for JSON.parse.
*
Expand All @@ -200,7 +122,7 @@ function getCharset (req) {
* @return {SyntaxError}
*/

function normalizeJsonSyntaxError (error, obj) {
function normalizeJsonSyntaxError(error, obj) {
var keys = Object.getOwnPropertyNames(error)

for (var i = 0; i < keys.length; i++) {
Expand All @@ -216,16 +138,3 @@ function normalizeJsonSyntaxError (error, obj) {

return error
}

/**
* Get the simple type checker.
*
* @param {string} type
* @return {function}
*/

function typeChecker (type) {
return function checkType (req) {
return Boolean(typeis(req, type))
}
}