Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for checking empty JSON body. #374

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 44 additions & 18 deletions lib/types/json.js
Expand Up @@ -47,7 +47,7 @@ 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'
Expand All @@ -68,20 +68,24 @@ function json (options) {
? 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 {}
}

function parse(body) {
if (strict) {
var first = firstchar(body)
// BEGIN - Check empty body
if (body.length === 0) {
debug('strict violation')
throw createEmptyBodyError()
}
// END - Check empty body

var first = firstchar(body)
if (first !== '{' && first !== '[') {
debug('strict violation')
throw createStrictSyntaxError(body, first)
}
} else {
if (body.length === 0) {
return {}
}
}

try {
Expand All @@ -95,7 +99,7 @@ function json (options) {
}
}

return function jsonParser (req, res, next) {
return function jsonParser(req, res, next) {
if (req._body) {
debug('body already parsed')
next()
Expand All @@ -104,12 +108,15 @@ function json (options) {

req.body = req.body || {}

// BEGIN - Check empty body
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this has been left commented out on accident -- this is how all the parsers work, they only parse bodies and this does not parse when there is no body at all (this is different from a zero-length body, i.e. empty string, which AFAIK is that you are adding an error for).

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

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

Expand Down Expand Up @@ -150,15 +157,34 @@ function json (options) {
* @private
*/

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

try {
JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation')
} catch (e) {
return normalizeJsonSyntaxError(e, {
message: e.message.replace('#', char),
message: e.message.replace('#', char) + ' NS ',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this message here. NS?

stack: e.stack
})
}
}

/**
* Create empty violation syntax error matching native error.
*
* @param {string} str
* @param {string} char
* @return {Error}
* @private
*/
function createEmptyBodyError() {
try {
throw Error()
} catch (e) {
return normalizeJsonSyntaxError(e, {
message: 'Empty JSON body received.',
stack: e.stack
})
}
Expand All @@ -172,7 +198,7 @@ function createStrictSyntaxError (str, char) {
* @private
*/

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

Expand All @@ -183,7 +209,7 @@ function firstchar (str) {
* @api private
*/

function getCharset (req) {
function getCharset(req) {
try {
return (contentType.parse(req).parameters.charset || '').toLowerCase()
} catch (e) {
Expand All @@ -199,7 +225,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 @@ -223,8 +249,8 @@ function normalizeJsonSyntaxError (error, obj) {
* @return {function}
*/

function typeChecker (type) {
return function checkType (req) {
function typeChecker(type) {
return function checkType(req) {
return Boolean(typeis(req, type))
}
}
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -29,10 +29,10 @@
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-standard": "4.0.0",
"istanbul": "0.4.5",
"methods": "1.1.2",
"methods": "^1.1.2",
"mocha": "6.1.4",
"safe-buffer": "5.1.2",
"supertest": "4.0.2"
"supertest": "^4.0.2"
},
"files": [
"lib/",
Expand Down