json.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. /**
  2. * Module dependencies.
  3. */
  4. var raw = require('raw-body');
  5. var inflate = require('inflation');
  6. // Allowed whitespace is defined in RFC 7159
  7. // http://www.rfc-editor.org/rfc/rfc7159.txt
  8. var strictJSONReg = /^[\x20\x09\x0a\x0d]*(\[|\{)/;
  9. /**
  10. * Return a Promise which parses json requests.
  11. *
  12. * Pass a node request or an object with `.req`,
  13. * such as a koa Context.
  14. *
  15. * @param {Request} req
  16. * @param {Options} [opts]
  17. * @return {Function}
  18. * @api public
  19. */
  20. module.exports = function(req, opts){
  21. req = req.req || req;
  22. opts = opts || {};
  23. // defaults
  24. var len = req.headers['content-length'];
  25. var encoding = req.headers['content-encoding'] || 'identity';
  26. if (len && encoding === 'identity') opts.length = len = ~~len;
  27. opts.encoding = opts.encoding || 'utf8';
  28. opts.limit = opts.limit || '1mb';
  29. var strict = opts.strict !== false;
  30. // raw-body returns a promise when no callback is specified
  31. return raw(inflate(req), opts)
  32. .then(function(str) {
  33. try {
  34. return parse(str);
  35. } catch (err) {
  36. err.status = 400;
  37. err.body = str;
  38. throw err;
  39. }
  40. });
  41. function parse(str){
  42. if (!strict) return str ? JSON.parse(str) : str;
  43. // strict mode always return object
  44. if (!str) return {};
  45. // strict JSON test
  46. if (!strictJSONReg.test(str)) {
  47. throw new Error('invalid JSON, only supports object and array');
  48. }
  49. return JSON.parse(str);
  50. }
  51. };