Skip to content

Commit

Permalink
querystring: add decodeSpaces option to .parse()
Browse files Browse the repository at this point in the history
Prevents auto-decoding of '+' characters to spaces.
  • Loading branch information
bnoordhuis committed Sep 25, 2012
1 parent a1ba29d commit 9a7b6c0
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 9 deletions.
8 changes: 6 additions & 2 deletions doc/api/querystring.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ Deserialize a query string to an object.
Optionally override the default separator (`'&'`) and assignment (`'='`)
characters.

Options object may contain `maxKeys` property (equal to 1000 by default), it'll
be used to limit processed keys. Set it to 0 to remove key count limitation.
The options object may contain the following keys:

* `decodeSpaces` (default: true). Convert `'+'` characters to spaces.

* `maxKeys` (default: 1000). Limits the number of processed keys. Set to 0 to
disable.

Example:

Expand Down
24 changes: 17 additions & 7 deletions lib/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) {
QueryString.escape(stringifyPrimitive(obj));
};


// Parse a key=val string.
QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
sep = sep || '&';
Expand All @@ -170,9 +171,16 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
var regexp = /\+/g;
qs = qs.split(sep);

var decodeSpaces = true;
var maxKeys = 1000;
if (options && typeof options.maxKeys === 'number') {
maxKeys = options.maxKeys;

if (options) {
if (typeof options.decodeSpaces === 'boolean') {
decodeSpaces = options.decodeSpaces;
}
if (typeof options.maxKeys === 'number') {
maxKeys = options.maxKeys;
}
}

var len = qs.length;
Expand All @@ -182,9 +190,11 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
}

for (var i = 0; i < len; ++i) {
var x = qs[i].replace(regexp, '%20'),
idx = x.indexOf(eq),
kstr, vstr, k, v;
var x = qs[i];
if (decodeSpaces) x = x.replace(regexp, '%20');

var idx = x.indexOf(eq);
var kstr, vstr, k, v;

if (idx >= 0) {
kstr = x.substr(0, idx);
Expand All @@ -198,8 +208,8 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
k = decodeURIComponent(kstr);
v = decodeURIComponent(vstr);
} catch (e) {
k = QueryString.unescape(kstr, true);
v = QueryString.unescape(vstr, true);
k = QueryString.unescape(kstr, decodeSpaces);
v = QueryString.unescape(vstr, decodeSpaces);
}

if (!hasOwnProperty(obj, k)) {
Expand Down
7 changes: 7 additions & 0 deletions test/simple/test-querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ function testUnlimitedKeys() {
}
testUnlimitedKeys();

// Test space decoding
assert.deepEqual(qs.parse('foo=bar+baz'),
{'foo': 'bar baz'});
assert.deepEqual(qs.parse('foo=bar+baz', '&', '=', { decodeSpaces: true }),
{'foo': 'bar baz'});
assert.deepEqual(qs.parse('foo=bar+baz', '&', '=', { decodeSpaces: false }),
{'foo': 'bar+baz'});

var b = qs.unescapeBuffer('%d3%f2Ug%1f6v%24%5e%98%cb' +
'%0d%ac%a2%2f%9d%eb%d8%a2%e6');
Expand Down

0 comments on commit 9a7b6c0

Please sign in to comment.