Skip to content

Commit 74fcd83

Browse files
committed
[Fix] proper comma parsing of URL-encoded commas (#361)
Fixes #311. Followup to #336.
1 parent 3756d40 commit 74fcd83

File tree

2 files changed

+24
-18
lines changed

2 files changed

+24
-18
lines changed

lib/parse.js

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ var parseArrayValue = function (val, options) {
3737
return val;
3838
};
3939

40+
var maybeMap = function maybeMap(val, fn) {
41+
if (isArray(val)) {
42+
var mapped = [];
43+
for (var i = 0; i < val.length; i += 1) {
44+
mapped.push(fn(val[i]));
45+
}
46+
return mapped;
47+
}
48+
return fn(val);
49+
};
50+
4051
// This is what browsers will submit when the ✓ character occurs in an
4152
// application/x-www-form-urlencoded body and the encoding of the page containing
4253
// the form is iso-8859-1, or when the submitted form has an accept-charset
@@ -85,23 +96,18 @@ var parseValues = function parseQueryStringValues(str, options) {
8596
val = options.strictNullHandling ? null : '';
8697
} else {
8798
key = options.decoder(part.slice(0, pos), defaults.decoder, charset);
88-
var encodedVal = part.slice(pos + 1);
89-
if (options.comma && encodedVal.indexOf(',') !== -1) {
90-
val = encodedVal.split(',')
91-
.map(function (encodedFragment) {
92-
return options.decoder(encodedFragment, defaults.decoder, charset);
93-
});
94-
} else {
95-
val = options.decoder(encodedVal, defaults.decoder, charset);
96-
}
99+
val = maybeMap(
100+
parseArrayValue(part.slice(pos + 1), options),
101+
function (encodedVal) {
102+
return options.decoder(encodedVal, defaults.decoder, charset);
103+
}
104+
);
97105
}
98106

99107
if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
100108
val = interpretNumericEntities(val);
101109
}
102110

103-
val = parseArrayValue(val, options);
104-
105111
if (part.indexOf('[]=') > -1) {
106112
val = isArray(val) ? [val] : val;
107113
}
@@ -116,8 +122,8 @@ var parseValues = function parseQueryStringValues(str, options) {
116122
return obj;
117123
};
118124

119-
var parseObject = function (chain, val, options) {
120-
var leaf = parseArrayValue(val, options);
125+
var parseObject = function (chain, val, options, valuesParsed) {
126+
var leaf = valuesParsed ? val : parseArrayValue(val, options);
121127

122128
for (var i = chain.length - 1; i >= 0; --i) {
123129
var obj;
@@ -145,13 +151,13 @@ var parseObject = function (chain, val, options) {
145151
}
146152
}
147153

148-
leaf = obj;
154+
leaf = obj; // eslint-disable-line no-param-reassign
149155
}
150156

151157
return leaf;
152158
};
153159

154-
var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
160+
var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) {
155161
if (!givenKey) {
156162
return;
157163
}
@@ -202,7 +208,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
202208
keys.push('[' + key.slice(segment.index) + ']');
203209
}
204210

205-
return parseObject(keys, val, options);
211+
return parseObject(keys, val, options, valuesParsed);
206212
};
207213

208214
var normalizeParseOptions = function normalizeParseOptions(opts) {
@@ -253,7 +259,7 @@ module.exports = function (str, opts) {
253259
var keys = Object.keys(tempObj);
254260
for (var i = 0; i < keys.length; ++i) {
255261
var key = keys[i];
256-
var newObj = parseKeys(key, tempObj[key], options);
262+
var newObj = parseKeys(key, tempObj[key], options, typeof str === 'string');
257263
obj = utils.merge(obj, newObj, options);
258264
}
259265

test/parse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ test('parse()', function (t) {
442442
});
443443

444444
t.test('parses comma delimited array while having percent-encoded comma treated as normal text', function (st) {
445-
st.deepEqual(qs.parse('foo=a%2Cb', { comma: true }), { foo: ['a', 'b'] });
445+
st.deepEqual(qs.parse('foo=a%2Cb', { comma: true }), { foo: 'a,b' });
446446
st.deepEqual(qs.parse('foo=a%2C%20b,d', { comma: true }), { foo: ['a, b', 'd'] });
447447
st.deepEqual(qs.parse('foo=a%2C%20b,c%2C%20d', { comma: true }), { foo: ['a, b', 'c, d'] });
448448

0 commit comments

Comments
 (0)