• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

expressjs / body-parser / 17579372920

09 Sep 2025 10:14AM UTC coverage: 98.624% (-0.3%) from 98.909%
17579372920

push

github

web-flow
refactor: optimize raw and text parsers with shared passthrough function (#634)

5 of 5 new or added lines in 3 files covered. (100.0%)

3 existing lines in 2 files now uncovered.

215 of 218 relevant lines covered (98.62%)

407.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.73
/lib/types/json.js
1
/*!
2
 * body-parser
3
 * Copyright(c) 2014 Jonathan Ong
4
 * Copyright(c) 2014-2015 Douglas Christopher Wilson
5
 * MIT Licensed
6
 */
7

8
'use strict'
9

10
/**
11
 * Module dependencies.
12
 * @private
13
 */
14

15
var debug = require('debug')('body-parser:json')
7✔
16
var read = require('../read')
7✔
17
var { normalizeOptions } = require('../utils')
7✔
18

19
/**
20
 * Module exports.
21
 */
22

23
module.exports = json
7✔
24

25
/**
26
 * RegExp to match the first non-space in a string.
27
 *
28
 * Allowed whitespace is defined in RFC 7159:
29
 *
30
 *    ws = *(
31
 *            %x20 /              ; Space
32
 *            %x09 /              ; Horizontal tab
33
 *            %x0A /              ; Line feed or New line
34
 *            %x0D )              ; Carriage return
35
 */
36

37
var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/ // eslint-disable-line no-control-regex
7✔
38

39
var JSON_SYNTAX_CHAR = '#'
7✔
40
var JSON_SYNTAX_REGEXP = /#+/g
7✔
41

42
/**
43
 * Create a middleware to parse JSON bodies.
44
 *
45
 * @param {object} [options]
46
 * @return {function}
47
 * @public
48
 */
49

50
function json (options) {
51
  var normalizedOptions = normalizeOptions(options, 'application/json')
259✔
52

53
  var reviver = options?.reviver
252✔
54
  var strict = options?.strict !== false
252✔
55

56
  function parse (body) {
57
    if (body.length === 0) {
252✔
58
      // special-case empty json body, as it's a common client-side mistake
59
      // TODO: maybe make this configurable or part of "strict" option
60
      return {}
14✔
61
    }
62

63
    if (strict) {
238✔
64
      var first = firstchar(body)
231✔
65

66
      if (first !== '{' && first !== '[') {
231✔
67
        debug('strict violation')
35✔
68
        throw createStrictSyntaxError(body, first)
35✔
69
      }
70
    }
71

72
    try {
203✔
73
      debug('parse json')
203✔
74
      return JSON.parse(body, reviver)
203✔
75
    } catch (e) {
76
      throw normalizeJsonSyntaxError(e, {
28✔
77
        message: e.message,
78
        stack: e.stack
79
      })
80
    }
81
  }
82

83
  return function jsonParser (req, res, next) {
252✔
84
    read(req, res, next, parse, debug, {
441✔
85
      ...normalizedOptions,
86

87
      // assert charset per RFC 7159 sec 8.1
88
      isValidCharset: (charset) => charset.slice(0, 4) === 'utf-'
392✔
89
    })
90
  }
91
}
92

93
/**
94
 * Create strict violation syntax error matching native error.
95
 *
96
 * @param {string} str
97
 * @param {string} char
98
 * @return {Error}
99
 * @private
100
 */
101

102
function createStrictSyntaxError (str, char) {
103
  var index = str.indexOf(char)
35✔
104
  var partial = ''
35✔
105

106
  if (index !== -1) {
35✔
107
    partial = str.substring(0, index) + JSON_SYNTAX_CHAR
28✔
108

109
    for (var i = index + 1; i < str.length; i++) {
28✔
110
      partial += JSON_SYNTAX_CHAR
84✔
111
    }
112
  }
113

114
  try {
35✔
115
    JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation')
35✔
116
  } catch (e) {
117
    return normalizeJsonSyntaxError(e, {
35✔
118
      message: e.message.replace(JSON_SYNTAX_REGEXP, function (placeholder) {
119
        return str.substring(index, index + placeholder.length)
52✔
120
      }),
121
      stack: e.stack
122
    })
123
  }
124
}
125

126
/**
127
 * Get the first non-whitespace character in a string.
128
 *
129
 * @param {string} str
130
 * @return {function}
131
 * @private
132
 */
133

134
function firstchar (str) {
135
  var match = FIRST_CHAR_REGEXP.exec(str)
231✔
136

137
  return match
231✔
138
    ? match[1]
139
    : undefined
140
}
141

142
/**
143
 * Normalize a SyntaxError for JSON.parse.
144
 *
145
 * @param {SyntaxError} error
146
 * @param {object} obj
147
 * @return {SyntaxError}
148
 */
149

150
function normalizeJsonSyntaxError (error, obj) {
151
  var keys = Object.getOwnPropertyNames(error)
63✔
152

153
  for (var i = 0; i < keys.length; i++) {
63✔
154
    var key = keys[i]
126✔
155
    if (key !== 'stack' && key !== 'message') {
126✔
UNCOV
156
      delete error[key]
×
157
    }
158
  }
159

160
  // replace stack before message for Node.js 0.10 and below
161
  error.stack = obj.stack.replace(error.message, obj.message)
63✔
162
  error.message = obj.message
63✔
163

164
  return error
63✔
165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc