// Copyright 2012 Mark Cavage, Inc. All rights reserved. 'use strict'; var assert = require('assert-plus'); var errors = require('restify-errors'); var bodyReader = require('./bodyReader'); var regex = require('./utils/regex'); ///--- API /** * Parses json body from the request. * * @public * @function jsonBodyParser * @param {Object} options - an options object * @throws {InvalidContentError} on bad input * @returns {Function} Handler */ function jsonBodyParser(options) { assert.optionalObject(options, 'options'); var opts = options || {}; var override = opts.overrideParams; function parseJson(req, res, next) { // save original body on req.rawBody and req._body req.rawBody = req._body = req.body; var contentType = req.getContentType(); // check for empty body first, don't pay regex tax unless necessary. // for content type, check for exact match and any of the *+json types if ( !req.body || (contentType !== 'application/json' && !regex.jsonContentType.test(contentType)) ) { return next(); } var params; try { params = JSON.parse(req.body, opts.reviver); } catch (e) { return next( new errors.InvalidContentError( '%s', 'Invalid JSON: ' + e.message ) ); } if (opts.mapParams === true) { if (Array.isArray(params)) { // if req.params exists, we have url params. we can't map an // array safely onto req.params, throw an error. if ( req.params && Object.keys(req.params).length > 0 && !(req.params instanceof Array) ) { return next( new errors.InternalServerError( 'Cannot map POST body of [Array array] onto ' + 'req.params' ) ); } req.params = params; } else if (typeof params === 'object' && params !== null) { // else, try to merge the objects Object.keys(params).forEach(function forEach(k) { var p = req.params[k]; if (p && !override) { return; } req.params[k] = params[k]; }); } else { // otherwise, do a wholesale stomp, no need to merge one by one. req.params = params || req.params; } } req.body = params; return next(); } var chain = []; if (!opts.bodyReader) { chain.push(bodyReader(opts)); } chain.push(parseJson); return chain; } module.exports = jsonBodyParser;