| 'use strict'; | 
|   | 
| /** | 
|  * Module dependencies. | 
|  */ | 
|   | 
| const raw = require('raw-body'); | 
| const inflate = require('inflation'); | 
| const utils = require('./utils'); | 
|   | 
| // Allowed whitespace is defined in RFC 7159 | 
| // http://www.rfc-editor.org/rfc/rfc7159.txt | 
| const strictJSONReg = /^[\x20\x09\x0a\x0d]*(\[|\{)/; | 
|   | 
| /** | 
|  * Return a Promise which parses json requests. | 
|  * | 
|  * Pass a node request or an object with `.req`, | 
|  * such as a koa Context. | 
|  * | 
|  * @param {Request} req | 
|  * @param {Options} [opts] | 
|  * @return {Function} | 
|  * @api public | 
|  */ | 
|   | 
| module.exports = async function(req, opts) { | 
|   req = req.req || req; | 
|   opts = utils.clone(opts); | 
|   | 
|   // defaults | 
|   let len = req.headers['content-length']; | 
|   const encoding = req.headers['content-encoding'] || 'identity'; | 
|   if (len && encoding === 'identity') opts.length = len = ~~len; | 
|   opts.encoding = opts.encoding || 'utf8'; | 
|   opts.limit = opts.limit || '1mb'; | 
|   const strict = opts.strict !== false; | 
|   | 
|   const str = await raw(inflate(req), opts); | 
|   try { | 
|     const parsed = parse(str); | 
|     return opts.returnRawBody ? { parsed, raw: str } : parsed; | 
|   } catch (err) { | 
|     err.status = 400; | 
|     err.body = str; | 
|     throw err; | 
|   } | 
|   | 
|   function parse(str) { | 
|     if (!strict) return str ? JSON.parse(str) : str; | 
|     // strict mode always return object | 
|     if (!str) return {}; | 
|     // strict JSON test | 
|     if (!strictJSONReg.test(str)) { | 
|       throw new Error('invalid JSON, only supports object and array'); | 
|     } | 
|     return JSON.parse(str); | 
|   } | 
| }; |