UNPKG

2.56 kBJavaScriptView Raw
1'use strict';
2
3var has = Object.prototype.hasOwnProperty
4 , undef;
5
6/**
7 * Decode a URI encoded string.
8 *
9 * @param {String} input The URI encoded string.
10 * @returns {String|Null} The decoded string.
11 * @api private
12 */
13function decode(input) {
14 try {
15 return decodeURIComponent(input.replace(/\+/g, ' '));
16 } catch (e) {
17 return null;
18 }
19}
20
21/**
22 * Attempts to encode a given input.
23 *
24 * @param {String} input The string that needs to be encoded.
25 * @returns {String|Null} The encoded string.
26 * @api private
27 */
28function encode(input) {
29 try {
30 return encodeURIComponent(input);
31 } catch (e) {
32 return null;
33 }
34}
35
36/**
37 * Simple query string parser.
38 *
39 * @param {String} query The query string that needs to be parsed.
40 * @returns {Object}
41 * @api public
42 */
43function querystring(query) {
44 var parser = /([^=?#&]+)=?([^&]*)/g
45 , result = {}
46 , part;
47
48 while (part = parser.exec(query)) {
49 var key = decode(part[1])
50 , value = decode(part[2]);
51
52 //
53 // Prevent overriding of existing properties. This ensures that build-in
54 // methods like `toString` or __proto__ are not overriden by malicious
55 // querystrings.
56 //
57 // In the case if failed decoding, we want to omit the key/value pairs
58 // from the result.
59 //
60 if (key === null || value === null || key in result) continue;
61 result[key] = value;
62 }
63
64 return result;
65}
66
67/**
68 * Transform a query string to an object.
69 *
70 * @param {Object} obj Object that should be transformed.
71 * @param {String} prefix Optional prefix.
72 * @returns {String}
73 * @api public
74 */
75function querystringify(obj, prefix) {
76 prefix = prefix || '';
77
78 var pairs = []
79 , value
80 , key;
81
82 //
83 // Optionally prefix with a '?' if needed
84 //
85 if ('string' !== typeof prefix) prefix = '?';
86
87 for (key in obj) {
88 if (has.call(obj, key)) {
89 value = obj[key];
90
91 //
92 // Edge cases where we actually want to encode the value to an empty
93 // string instead of the stringified value.
94 //
95 if (!value && (value === null || value === undef || isNaN(value))) {
96 value = '';
97 }
98
99 key = encode(key);
100 value = encode(value);
101
102 //
103 // If we failed to encode the strings, we should bail out as we don't
104 // want to add invalid strings to the query.
105 //
106 if (key === null || value === null) continue;
107 pairs.push(key +'='+ value);
108 }
109 }
110
111 return pairs.length ? prefix + pairs.join('&') : '';
112}
113
114//
115// Expose the module.
116//
117exports.stringify = querystringify;
118exports.parse = querystring;