json.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*!
  2. * body-parser
  3. * MIT Licensed
  4. */
  5. /**
  6. * Module dependencies.
  7. */
  8. var bytes = require('bytes')
  9. var read = require('../read')
  10. var typer = require('media-typer')
  11. var typeis = require('type-is')
  12. /**
  13. * Module exports.
  14. */
  15. module.exports = json
  16. /**
  17. * RegExp to match the first non-space in a string.
  18. */
  19. var firstcharRegExp = /^\s*(.)/
  20. /**
  21. * Create a middleware to parse JSON bodies.
  22. *
  23. * @param {object} [options]
  24. * @return {function}
  25. * @api public
  26. */
  27. function json(options) {
  28. options = options || {}
  29. var limit = typeof options.limit !== 'number'
  30. ? bytes(options.limit || '100kb')
  31. : options.limit
  32. var inflate = options.inflate !== false
  33. var reviver = options.reviver
  34. var strict = options.strict !== false
  35. var type = options.type || 'json'
  36. var verify = options.verify || false
  37. if (verify !== false && typeof verify !== 'function') {
  38. throw new TypeError('option verify must be function')
  39. }
  40. function parse(body) {
  41. if (0 === body.length) {
  42. throw new Error('invalid json, empty body')
  43. }
  44. if (strict) {
  45. var first = firstchar(body)
  46. if (first !== '{' && first !== '[') {
  47. throw new Error('invalid json')
  48. }
  49. }
  50. return JSON.parse(body, reviver)
  51. }
  52. return function jsonParser(req, res, next) {
  53. if (req._body) return next()
  54. req.body = req.body || {}
  55. if (!typeis(req, type)) return next()
  56. // RFC 7159 sec 8.1
  57. var charset = typer.parse(req).parameters.charset || 'utf-8'
  58. if (charset.substr(0, 4).toLowerCase() !== 'utf-') {
  59. var err = new Error('unsupported charset')
  60. err.status = 415
  61. next(err)
  62. return
  63. }
  64. // read
  65. read(req, res, next, parse, {
  66. encoding: charset,
  67. inflate: inflate,
  68. limit: limit,
  69. verify: verify
  70. })
  71. }
  72. }
  73. /**
  74. * Get the first non-whitespace character in a string.
  75. *
  76. * @param {string} str
  77. * @return {function}
  78. * @api public
  79. */
  80. function firstchar(str) {
  81. if (!str) return ''
  82. var match = firstcharRegExp.exec(str)
  83. return match ? match[1] : ''
  84. }