UNPKG

2.06 kBJavaScriptView Raw
1'use strict'
2
3const querystring = require('querystring')
4
5const common = require('./common')
6
7module.exports = function matchBody(options, spec, body) {
8 if (spec instanceof RegExp) {
9 return spec.test(body)
10 }
11
12 if (Buffer.isBuffer(spec)) {
13 const encoding = common.isUtf8Representable(spec) ? 'utf8' : 'hex'
14 spec = spec.toString(encoding)
15 }
16
17 const contentType = (
18 (options.headers &&
19 (options.headers['Content-Type'] || options.headers['content-type'])) ||
20 ''
21 ).toString()
22
23 const isMultipart = contentType.includes('multipart')
24 const isUrlencoded = contentType.includes('application/x-www-form-urlencoded')
25
26 // try to transform body to json
27 let json
28 if (typeof spec === 'object' || typeof spec === 'function') {
29 try {
30 json = JSON.parse(body)
31 } catch (err) {
32 // not a valid JSON string
33 }
34 if (json !== undefined) {
35 body = json
36 } else if (isUrlencoded) {
37 body = querystring.parse(body)
38 }
39 }
40
41 if (typeof spec === 'function') {
42 return spec.call(options, body)
43 }
44
45 // strip line endings from both so that we get a match no matter what OS we are running on
46 // if Content-Type does not contains 'multipart'
47 if (!isMultipart && typeof body === 'string') {
48 body = body.replace(/\r?\n|\r/g, '')
49 }
50
51 if (!isMultipart && typeof spec === 'string') {
52 spec = spec.replace(/\r?\n|\r/g, '')
53 }
54
55 // Because the nature of URL encoding, all the values in the body have been cast to strings.
56 // dataEqual does strict checking so we we have to cast the non-regexp values in the spec too.
57 if (isUrlencoded) {
58 spec = mapValuesDeep(spec, val => (val instanceof RegExp ? val : `${val}`))
59 }
60
61 return common.dataEqual(spec, body)
62}
63
64/**
65 * Based on lodash issue discussion
66 * https://github.com/lodash/lodash/issues/1244
67 */
68function mapValuesDeep(obj, cb) {
69 if (Array.isArray(obj)) {
70 return obj.map(v => mapValuesDeep(v, cb))
71 }
72 if (common.isPlainObject(obj)) {
73 return common.mapValue(obj, v => mapValuesDeep(v, cb))
74 }
75 return cb(obj)
76}