step-node-agent 3.29.0 → 3.29.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/body-parser/HISTORY.md +8 -0
- package/node_modules/body-parser/lib/types/urlencoded.js +2 -9
- package/node_modules/body-parser/package.json +9 -10
- package/node_modules/cookie/index.js +2 -1
- package/node_modules/cookie/package.json +1 -1
- package/node_modules/cookie-signature/History.md +5 -1
- package/node_modules/cookie-signature/index.js +6 -6
- package/node_modules/cookie-signature/package.json +2 -2
- package/node_modules/express/History.md +11 -0
- package/node_modules/express/package.json +17 -17
- package/node_modules/finalhandler/HISTORY.md +6 -0
- package/node_modules/finalhandler/package.json +3 -3
- package/node_modules/http-errors/HISTORY.md +6 -0
- package/node_modules/http-errors/index.js +4 -3
- package/node_modules/http-errors/package.json +12 -8
- package/node_modules/qs/.github/SECURITY.md +11 -0
- package/node_modules/qs/.github/THREAT_MODEL.md +78 -0
- package/node_modules/qs/CHANGELOG.md +31 -0
- package/node_modules/qs/README.md +25 -1
- package/node_modules/qs/dist/qs.js +95 -44
- package/node_modules/qs/eslint.config.mjs +56 -0
- package/node_modules/qs/lib/parse.js +107 -43
- package/node_modules/qs/lib/stringify.js +11 -6
- package/node_modules/qs/lib/utils.js +61 -6
- package/node_modules/qs/package.json +15 -12
- package/node_modules/qs/test/parse.js +257 -31
- package/node_modules/qs/test/stringify.js +23 -11
- package/node_modules/qs/test/utils.js +245 -0
- package/node_modules/raw-body/package.json +5 -7
- package/node_modules/send/HISTORY.md +19 -7
- package/node_modules/send/package.json +6 -6
- package/node_modules/serve-static/HISTORY.md +6 -0
- package/node_modules/serve-static/package.json +2 -2
- package/node_modules/statuses/HISTORY.md +5 -0
- package/node_modules/statuses/README.md +3 -0
- package/node_modules/statuses/package.json +7 -7
- package/node_modules/yaml/browser/dist/compose/compose-collection.js +1 -1
- package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +1 -1
- package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +2 -2
- package/node_modules/yaml/browser/dist/errors.js +1 -1
- package/node_modules/yaml/browser/dist/nodes/Alias.js +1 -1
- package/node_modules/yaml/browser/dist/parse/parser.js +2 -2
- package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +1 -1
- package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +1 -1
- package/node_modules/yaml/dist/compose/compose-collection.js +1 -1
- package/node_modules/yaml/dist/compose/resolve-block-seq.js +1 -1
- package/node_modules/yaml/dist/compose/resolve-flow-collection.js +2 -2
- package/node_modules/yaml/dist/errors.js +1 -1
- package/node_modules/yaml/dist/nodes/Alias.js +1 -1
- package/node_modules/yaml/dist/parse/parser.js +2 -2
- package/node_modules/yaml/dist/stringify/stringifyNumber.js +1 -1
- package/node_modules/yaml/dist/stringify/stringifyPair.js +1 -1
- package/node_modules/yaml/package.json +4 -4
- package/package.json +1 -1
- package/node_modules/body-parser/SECURITY.md +0 -25
- package/node_modules/cookie-signature/.npmignore +0 -4
- package/node_modules/qs/.eslintrc +0 -38
- package/node_modules/raw-body/HISTORY.md +0 -308
- package/node_modules/raw-body/SECURITY.md +0 -24
- package/node_modules/send/node_modules/encodeurl/HISTORY.md +0 -14
- package/node_modules/send/node_modules/encodeurl/LICENSE +0 -22
- package/node_modules/send/node_modules/encodeurl/README.md +0 -128
- package/node_modules/send/node_modules/encodeurl/index.js +0 -60
- package/node_modules/send/node_modules/encodeurl/package.json +0 -40
|
@@ -9,6 +9,7 @@ var SaferBuffer = require('safer-buffer').Buffer;
|
|
|
9
9
|
var v = require('es-value-fixtures');
|
|
10
10
|
var inspect = require('object-inspect');
|
|
11
11
|
var emptyTestCases = require('./empty-keys-cases').emptyTestCases;
|
|
12
|
+
var hasProto = require('has-proto')();
|
|
12
13
|
|
|
13
14
|
var qs = require('../');
|
|
14
15
|
var utils = require('../lib/utils');
|
|
@@ -117,7 +118,7 @@ test('parse()', function (t) {
|
|
|
117
118
|
st.end();
|
|
118
119
|
});
|
|
119
120
|
|
|
120
|
-
t.test('
|
|
121
|
+
t.test('decodes dot in key of object, and allow enabling dot notation when decodeDotInKeys is set to true and allowDots is undefined', function (st) {
|
|
121
122
|
st.deepEqual(
|
|
122
123
|
qs.parse(
|
|
123
124
|
'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe',
|
|
@@ -130,7 +131,7 @@ test('parse()', function (t) {
|
|
|
130
131
|
st.end();
|
|
131
132
|
});
|
|
132
133
|
|
|
133
|
-
t.test('
|
|
134
|
+
t.test('throws when decodeDotInKeys is not of type boolean', function (st) {
|
|
134
135
|
st['throws'](
|
|
135
136
|
function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: 'foobar' }); },
|
|
136
137
|
TypeError
|
|
@@ -160,7 +161,7 @@ test('parse()', function (t) {
|
|
|
160
161
|
st.end();
|
|
161
162
|
});
|
|
162
163
|
|
|
163
|
-
t.test('
|
|
164
|
+
t.test('throws when allowEmptyArrays is not of type boolean', function (st) {
|
|
164
165
|
st['throws'](
|
|
165
166
|
function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: 'foobar' }); },
|
|
166
167
|
TypeError
|
|
@@ -234,11 +235,11 @@ test('parse()', function (t) {
|
|
|
234
235
|
st.deepEqual(qs.parse('a=b&a[0]=c'), { a: ['b', 'c'] });
|
|
235
236
|
|
|
236
237
|
st.deepEqual(qs.parse('a[1]=b&a=c', { arrayLimit: 20 }), { a: ['b', 'c'] });
|
|
237
|
-
st.deepEqual(qs.parse('a[]=b&a=c', { arrayLimit: 0 }), { a:
|
|
238
|
+
st.deepEqual(qs.parse('a[]=b&a=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } });
|
|
238
239
|
st.deepEqual(qs.parse('a[]=b&a=c'), { a: ['b', 'c'] });
|
|
239
240
|
|
|
240
241
|
st.deepEqual(qs.parse('a=b&a[1]=c', { arrayLimit: 20 }), { a: ['b', 'c'] });
|
|
241
|
-
st.deepEqual(qs.parse('a=b&a[]=c', { arrayLimit: 0 }), { a:
|
|
242
|
+
st.deepEqual(qs.parse('a=b&a[]=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } });
|
|
242
243
|
st.deepEqual(qs.parse('a=b&a[]=c'), { a: ['b', 'c'] });
|
|
243
244
|
|
|
244
245
|
st.end();
|
|
@@ -363,7 +364,7 @@ test('parse()', function (t) {
|
|
|
363
364
|
);
|
|
364
365
|
st.deepEqual(
|
|
365
366
|
qs.parse('a[]=b&a[]&a[]=c&a[]=', { strictNullHandling: true, arrayLimit: 0 }),
|
|
366
|
-
{ a:
|
|
367
|
+
{ a: { 0: 'b', 1: null, 2: 'c', 3: '' } },
|
|
367
368
|
'with arrayLimit 0 + array brackets: null then empty string works'
|
|
368
369
|
);
|
|
369
370
|
|
|
@@ -374,7 +375,7 @@ test('parse()', function (t) {
|
|
|
374
375
|
);
|
|
375
376
|
st.deepEqual(
|
|
376
377
|
qs.parse('a[]=b&a[]=&a[]=c&a[]', { strictNullHandling: true, arrayLimit: 0 }),
|
|
377
|
-
{ a:
|
|
378
|
+
{ a: { 0: 'b', 1: '', 2: 'c', 3: null } },
|
|
378
379
|
'with arrayLimit 0 + array brackets: empty string then null works'
|
|
379
380
|
);
|
|
380
381
|
|
|
@@ -443,7 +444,7 @@ test('parse()', function (t) {
|
|
|
443
444
|
st.end();
|
|
444
445
|
});
|
|
445
446
|
|
|
446
|
-
t.test('
|
|
447
|
+
t.test('does not throw when a native prototype has an enumerable property', function (st) {
|
|
447
448
|
st.intercept(Object.prototype, 'crash', { value: '' });
|
|
448
449
|
st.intercept(Array.prototype, 'crash', { value: '' });
|
|
449
450
|
|
|
@@ -691,9 +692,8 @@ test('parse()', function (t) {
|
|
|
691
692
|
st.end();
|
|
692
693
|
});
|
|
693
694
|
|
|
694
|
-
t.test('parses null objects correctly', { skip: !
|
|
695
|
-
var a =
|
|
696
|
-
a.b = 'c';
|
|
695
|
+
t.test('parses null objects correctly', { skip: !hasProto }, function (st) {
|
|
696
|
+
var a = { __proto__: null, b: 'c' };
|
|
697
697
|
|
|
698
698
|
st.deepEqual(qs.parse(a), { b: 'c' });
|
|
699
699
|
var result = qs.parse({ a: a });
|
|
@@ -870,17 +870,25 @@ test('parse()', function (t) {
|
|
|
870
870
|
st.end();
|
|
871
871
|
});
|
|
872
872
|
|
|
873
|
-
t.test('can return null objects', { skip: !
|
|
874
|
-
var expected =
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
873
|
+
t.test('can return null objects', { skip: !hasProto }, function (st) {
|
|
874
|
+
var expected = {
|
|
875
|
+
__proto__: null,
|
|
876
|
+
a: {
|
|
877
|
+
__proto__: null,
|
|
878
|
+
b: 'c',
|
|
879
|
+
hasOwnProperty: 'd'
|
|
880
|
+
}
|
|
881
|
+
};
|
|
878
882
|
st.deepEqual(qs.parse('a[b]=c&a[hasOwnProperty]=d', { plainObjects: true }), expected);
|
|
879
|
-
st.deepEqual(qs.parse(null, { plainObjects: true }),
|
|
880
|
-
var expectedArray =
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
883
|
+
st.deepEqual(qs.parse(null, { plainObjects: true }), { __proto__: null });
|
|
884
|
+
var expectedArray = {
|
|
885
|
+
__proto__: null,
|
|
886
|
+
a: {
|
|
887
|
+
__proto__: null,
|
|
888
|
+
0: 'b',
|
|
889
|
+
c: 'd'
|
|
890
|
+
}
|
|
891
|
+
};
|
|
884
892
|
st.deepEqual(qs.parse('a[]=b&a[c]=d', { plainObjects: true }), expectedArray);
|
|
885
893
|
st.end();
|
|
886
894
|
});
|
|
@@ -957,7 +965,7 @@ test('parse()', function (t) {
|
|
|
957
965
|
st.end();
|
|
958
966
|
});
|
|
959
967
|
|
|
960
|
-
t.test('
|
|
968
|
+
t.test('ignores an utf8 sentinel with an unknown value', function (st) {
|
|
961
969
|
st.deepEqual(qs.parse('utf8=foo&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'utf-8' }), { ø: 'ø' });
|
|
962
970
|
st.end();
|
|
963
971
|
});
|
|
@@ -988,6 +996,20 @@ test('parse()', function (t) {
|
|
|
988
996
|
st.end();
|
|
989
997
|
});
|
|
990
998
|
|
|
999
|
+
t.test('handles a custom decoder returning `null`, with a string key of `null`', function (st) {
|
|
1000
|
+
st.deepEqual(
|
|
1001
|
+
qs.parse('null=1&ToNull=2', {
|
|
1002
|
+
decoder: function (str, defaultDecoder, charset) {
|
|
1003
|
+
return str === 'ToNull' ? null : defaultDecoder(str, defaultDecoder, charset);
|
|
1004
|
+
}
|
|
1005
|
+
}),
|
|
1006
|
+
{ 'null': '1' },
|
|
1007
|
+
'"null" key is not overridden by `null` decoder result'
|
|
1008
|
+
);
|
|
1009
|
+
|
|
1010
|
+
st.end();
|
|
1011
|
+
});
|
|
1012
|
+
|
|
991
1013
|
t.test('does not interpret numeric entities in iso-8859-1 when `interpretNumericEntities` is absent', function (st) {
|
|
992
1014
|
st.deepEqual(qs.parse('foo=' + urlEncodedNumSmiley, { charset: 'iso-8859-1' }), { foo: '☺' });
|
|
993
1015
|
st.end();
|
|
@@ -998,6 +1020,15 @@ test('parse()', function (t) {
|
|
|
998
1020
|
st.end();
|
|
999
1021
|
});
|
|
1000
1022
|
|
|
1023
|
+
t.test('interpretNumericEntities with comma:true and iso charset does not crash', function (st) {
|
|
1024
|
+
st.deepEqual(
|
|
1025
|
+
qs.parse('b&a[]=1,' + urlEncodedNumSmiley, { comma: true, charset: 'iso-8859-1', interpretNumericEntities: true }),
|
|
1026
|
+
{ b: '', a: ['1,☺'] }
|
|
1027
|
+
);
|
|
1028
|
+
|
|
1029
|
+
st.end();
|
|
1030
|
+
});
|
|
1031
|
+
|
|
1001
1032
|
t.test('does not interpret %uXXXX syntax in iso-8859-1 mode', function (st) {
|
|
1002
1033
|
st.deepEqual(qs.parse('%u263A=%u263A', { charset: 'iso-8859-1' }), { '%u263A': '%u263A' });
|
|
1003
1034
|
st.end();
|
|
@@ -1018,6 +1049,95 @@ test('parse()', function (t) {
|
|
|
1018
1049
|
st.end();
|
|
1019
1050
|
});
|
|
1020
1051
|
|
|
1052
|
+
t.test('parameter limit tests', function (st) {
|
|
1053
|
+
st.test('does not throw error when within parameter limit', function (sst) {
|
|
1054
|
+
var result = qs.parse('a=1&b=2&c=3', { parameterLimit: 5, throwOnLimitExceeded: true });
|
|
1055
|
+
sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses without errors');
|
|
1056
|
+
sst.end();
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1059
|
+
st.test('throws error when throwOnLimitExceeded is present but not boolean', function (sst) {
|
|
1060
|
+
sst['throws'](
|
|
1061
|
+
function () {
|
|
1062
|
+
qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: 3, throwOnLimitExceeded: 'true' });
|
|
1063
|
+
},
|
|
1064
|
+
new TypeError('`throwOnLimitExceeded` option must be a boolean'),
|
|
1065
|
+
'throws error when throwOnLimitExceeded is present and not boolean'
|
|
1066
|
+
);
|
|
1067
|
+
sst.end();
|
|
1068
|
+
});
|
|
1069
|
+
|
|
1070
|
+
st.test('throws error when parameter limit exceeded', function (sst) {
|
|
1071
|
+
sst['throws'](
|
|
1072
|
+
function () {
|
|
1073
|
+
qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: 3, throwOnLimitExceeded: true });
|
|
1074
|
+
},
|
|
1075
|
+
new RangeError('Parameter limit exceeded. Only 3 parameters allowed.'),
|
|
1076
|
+
'throws error when parameter limit is exceeded'
|
|
1077
|
+
);
|
|
1078
|
+
sst.end();
|
|
1079
|
+
});
|
|
1080
|
+
|
|
1081
|
+
st.test('silently truncates when throwOnLimitExceeded is not given', function (sst) {
|
|
1082
|
+
var result = qs.parse('a=1&b=2&c=3&d=4&e=5', { parameterLimit: 3 });
|
|
1083
|
+
sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses and truncates silently');
|
|
1084
|
+
sst.end();
|
|
1085
|
+
});
|
|
1086
|
+
|
|
1087
|
+
st.test('silently truncates when parameter limit exceeded without error', function (sst) {
|
|
1088
|
+
var result = qs.parse('a=1&b=2&c=3&d=4&e=5', { parameterLimit: 3, throwOnLimitExceeded: false });
|
|
1089
|
+
sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses and truncates silently');
|
|
1090
|
+
sst.end();
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1093
|
+
st.test('allows unlimited parameters when parameterLimit set to Infinity', function (sst) {
|
|
1094
|
+
var result = qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: Infinity });
|
|
1095
|
+
sst.deepEqual(result, { a: '1', b: '2', c: '3', d: '4', e: '5', f: '6' }, 'parses all parameters without truncation');
|
|
1096
|
+
sst.end();
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
st.end();
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1102
|
+
t.test('array limit tests', function (st) {
|
|
1103
|
+
st.test('does not throw error when array is within limit', function (sst) {
|
|
1104
|
+
var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 5, throwOnLimitExceeded: true });
|
|
1105
|
+
sst.deepEqual(result, { a: ['1', '2', '3'] }, 'parses array without errors');
|
|
1106
|
+
sst.end();
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
st.test('throws error when throwOnLimitExceeded is present but not boolean for array limit', function (sst) {
|
|
1110
|
+
sst['throws'](
|
|
1111
|
+
function () {
|
|
1112
|
+
qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: 'true' });
|
|
1113
|
+
},
|
|
1114
|
+
new TypeError('`throwOnLimitExceeded` option must be a boolean'),
|
|
1115
|
+
'throws error when throwOnLimitExceeded is present and not boolean for array limit'
|
|
1116
|
+
);
|
|
1117
|
+
sst.end();
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
st.test('throws error when array limit exceeded', function (sst) {
|
|
1121
|
+
sst['throws'](
|
|
1122
|
+
function () {
|
|
1123
|
+
qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: true });
|
|
1124
|
+
},
|
|
1125
|
+
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
|
|
1126
|
+
'throws error when array limit is exceeded'
|
|
1127
|
+
);
|
|
1128
|
+
sst.end();
|
|
1129
|
+
});
|
|
1130
|
+
|
|
1131
|
+
st.test('converts array to object if length is greater than limit', function (sst) {
|
|
1132
|
+
var result = qs.parse('a[1]=1&a[2]=2&a[3]=3&a[4]=4&a[5]=5&a[6]=6', { arrayLimit: 5 });
|
|
1133
|
+
|
|
1134
|
+
sst.deepEqual(result, { a: { 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6' } }, 'parses into object if array length is greater than limit');
|
|
1135
|
+
sst.end();
|
|
1136
|
+
});
|
|
1137
|
+
|
|
1138
|
+
st.end();
|
|
1139
|
+
});
|
|
1140
|
+
|
|
1021
1141
|
t.end();
|
|
1022
1142
|
});
|
|
1023
1143
|
|
|
@@ -1076,7 +1196,7 @@ test('qs strictDepth option - throw cases', function (t) {
|
|
|
1076
1196
|
qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1, strictDepth: true });
|
|
1077
1197
|
},
|
|
1078
1198
|
RangeError,
|
|
1079
|
-
'
|
|
1199
|
+
'throws RangeError'
|
|
1080
1200
|
);
|
|
1081
1201
|
st.end();
|
|
1082
1202
|
});
|
|
@@ -1087,7 +1207,7 @@ test('qs strictDepth option - throw cases', function (t) {
|
|
|
1087
1207
|
qs.parse('a[0][1][2][3][4]=b', { depth: 3, strictDepth: true });
|
|
1088
1208
|
},
|
|
1089
1209
|
RangeError,
|
|
1090
|
-
'
|
|
1210
|
+
'throws RangeError'
|
|
1091
1211
|
);
|
|
1092
1212
|
st.end();
|
|
1093
1213
|
});
|
|
@@ -1098,7 +1218,7 @@ test('qs strictDepth option - throw cases', function (t) {
|
|
|
1098
1218
|
qs.parse('a[b][c][0][d][e]=f', { depth: 3, strictDepth: true });
|
|
1099
1219
|
},
|
|
1100
1220
|
RangeError,
|
|
1101
|
-
'
|
|
1221
|
+
'throws RangeError'
|
|
1102
1222
|
);
|
|
1103
1223
|
st.end();
|
|
1104
1224
|
});
|
|
@@ -1109,7 +1229,7 @@ test('qs strictDepth option - throw cases', function (t) {
|
|
|
1109
1229
|
qs.parse('a[b][c][d][e]=true&a[b][c][d][f]=42', { depth: 3, strictDepth: true });
|
|
1110
1230
|
},
|
|
1111
1231
|
RangeError,
|
|
1112
|
-
'
|
|
1232
|
+
'throws RangeError'
|
|
1113
1233
|
);
|
|
1114
1234
|
st.end();
|
|
1115
1235
|
});
|
|
@@ -1123,7 +1243,7 @@ test('qs strictDepth option - non-throw cases', function (t) {
|
|
|
1123
1243
|
qs.parse('a[b][c][d][e]=true&a[b][c][d][f]=42', { depth: 0, strictDepth: true });
|
|
1124
1244
|
},
|
|
1125
1245
|
RangeError,
|
|
1126
|
-
'
|
|
1246
|
+
'does not throw RangeError'
|
|
1127
1247
|
);
|
|
1128
1248
|
st.end();
|
|
1129
1249
|
});
|
|
@@ -1132,7 +1252,7 @@ test('qs strictDepth option - non-throw cases', function (t) {
|
|
|
1132
1252
|
st.doesNotThrow(
|
|
1133
1253
|
function () {
|
|
1134
1254
|
var result = qs.parse('a[b]=c', { depth: 1, strictDepth: true });
|
|
1135
|
-
st.deepEqual(result, { a: { b: 'c' } }, '
|
|
1255
|
+
st.deepEqual(result, { a: { b: 'c' } }, 'parses correctly');
|
|
1136
1256
|
}
|
|
1137
1257
|
);
|
|
1138
1258
|
st.end();
|
|
@@ -1142,7 +1262,7 @@ test('qs strictDepth option - non-throw cases', function (t) {
|
|
|
1142
1262
|
st.doesNotThrow(
|
|
1143
1263
|
function () {
|
|
1144
1264
|
var result = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
|
|
1145
|
-
st.deepEqual(result, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } }, '
|
|
1265
|
+
st.deepEqual(result, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } }, 'parses with depth limit');
|
|
1146
1266
|
}
|
|
1147
1267
|
);
|
|
1148
1268
|
st.end();
|
|
@@ -1152,7 +1272,7 @@ test('qs strictDepth option - non-throw cases', function (t) {
|
|
|
1152
1272
|
st.doesNotThrow(
|
|
1153
1273
|
function () {
|
|
1154
1274
|
var result = qs.parse('a[b]=c', { depth: 1 });
|
|
1155
|
-
st.deepEqual(result, { a: { b: 'c' } }, '
|
|
1275
|
+
st.deepEqual(result, { a: { b: 'c' } }, 'parses correctly');
|
|
1156
1276
|
}
|
|
1157
1277
|
);
|
|
1158
1278
|
st.end();
|
|
@@ -1162,9 +1282,115 @@ test('qs strictDepth option - non-throw cases', function (t) {
|
|
|
1162
1282
|
st.doesNotThrow(
|
|
1163
1283
|
function () {
|
|
1164
1284
|
var result = qs.parse('a[b][c]=d', { depth: 2, strictDepth: true });
|
|
1165
|
-
st.deepEqual(result, { a: { b: { c: 'd' } } }, '
|
|
1285
|
+
st.deepEqual(result, { a: { b: { c: 'd' } } }, 'parses correctly');
|
|
1166
1286
|
}
|
|
1167
1287
|
);
|
|
1168
1288
|
st.end();
|
|
1169
1289
|
});
|
|
1170
1290
|
});
|
|
1291
|
+
|
|
1292
|
+
test('DOS', function (t) {
|
|
1293
|
+
var arr = [];
|
|
1294
|
+
for (var i = 0; i < 105; i++) {
|
|
1295
|
+
arr[arr.length] = 'x';
|
|
1296
|
+
}
|
|
1297
|
+
var attack = 'a[]=' + arr.join('&a[]=');
|
|
1298
|
+
var result = qs.parse(attack, { arrayLimit: 100 });
|
|
1299
|
+
|
|
1300
|
+
t.notOk(Array.isArray(result.a), 'arrayLimit is respected: result is an object, not an array');
|
|
1301
|
+
t.equal(Object.keys(result.a).length, 105, 'all values are preserved');
|
|
1302
|
+
|
|
1303
|
+
t.end();
|
|
1304
|
+
});
|
|
1305
|
+
|
|
1306
|
+
test('arrayLimit boundary conditions', function (t) {
|
|
1307
|
+
t.test('exactly at the limit stays as array', function (st) {
|
|
1308
|
+
var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3 });
|
|
1309
|
+
st.ok(Array.isArray(result.a), 'result is an array when exactly at limit');
|
|
1310
|
+
st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1311
|
+
st.end();
|
|
1312
|
+
});
|
|
1313
|
+
|
|
1314
|
+
t.test('one over the limit converts to object', function (st) {
|
|
1315
|
+
var result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3 });
|
|
1316
|
+
st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
|
|
1317
|
+
st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
|
|
1318
|
+
st.end();
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1321
|
+
t.test('arrayLimit 1 with two values', function (st) {
|
|
1322
|
+
var result = qs.parse('a[]=1&a[]=2', { arrayLimit: 1 });
|
|
1323
|
+
st.notOk(Array.isArray(result.a), 'result is not an array');
|
|
1324
|
+
st.deepEqual(result.a, { 0: '1', 1: '2' }, 'both values preserved');
|
|
1325
|
+
st.end();
|
|
1326
|
+
});
|
|
1327
|
+
|
|
1328
|
+
t.end();
|
|
1329
|
+
});
|
|
1330
|
+
|
|
1331
|
+
test('mixed array and object notation', function (t) {
|
|
1332
|
+
t.test('array brackets with object key - under limit', function (st) {
|
|
1333
|
+
st.deepEqual(
|
|
1334
|
+
qs.parse('a[]=b&a[c]=d'),
|
|
1335
|
+
{ a: { 0: 'b', c: 'd' } },
|
|
1336
|
+
'mixing [] and [key] converts to object'
|
|
1337
|
+
);
|
|
1338
|
+
st.end();
|
|
1339
|
+
});
|
|
1340
|
+
|
|
1341
|
+
t.test('array index with object key - under limit', function (st) {
|
|
1342
|
+
st.deepEqual(
|
|
1343
|
+
qs.parse('a[0]=b&a[c]=d'),
|
|
1344
|
+
{ a: { 0: 'b', c: 'd' } },
|
|
1345
|
+
'mixing [0] and [key] produces object'
|
|
1346
|
+
);
|
|
1347
|
+
st.end();
|
|
1348
|
+
});
|
|
1349
|
+
|
|
1350
|
+
t.test('plain value with array brackets - under limit', function (st) {
|
|
1351
|
+
st.deepEqual(
|
|
1352
|
+
qs.parse('a=b&a[]=c', { arrayLimit: 20 }),
|
|
1353
|
+
{ a: ['b', 'c'] },
|
|
1354
|
+
'plain value combined with [] stays as array under limit'
|
|
1355
|
+
);
|
|
1356
|
+
st.end();
|
|
1357
|
+
});
|
|
1358
|
+
|
|
1359
|
+
t.test('array brackets with plain value - under limit', function (st) {
|
|
1360
|
+
st.deepEqual(
|
|
1361
|
+
qs.parse('a[]=b&a=c', { arrayLimit: 20 }),
|
|
1362
|
+
{ a: ['b', 'c'] },
|
|
1363
|
+
'[] combined with plain value stays as array under limit'
|
|
1364
|
+
);
|
|
1365
|
+
st.end();
|
|
1366
|
+
});
|
|
1367
|
+
|
|
1368
|
+
t.test('plain value with array index - under limit', function (st) {
|
|
1369
|
+
st.deepEqual(
|
|
1370
|
+
qs.parse('a=b&a[0]=c', { arrayLimit: 20 }),
|
|
1371
|
+
{ a: ['b', 'c'] },
|
|
1372
|
+
'plain value combined with [0] stays as array under limit'
|
|
1373
|
+
);
|
|
1374
|
+
st.end();
|
|
1375
|
+
});
|
|
1376
|
+
|
|
1377
|
+
t.test('multiple plain values with duplicates combine', function (st) {
|
|
1378
|
+
st.deepEqual(
|
|
1379
|
+
qs.parse('a=b&a=c&a=d', { arrayLimit: 20 }),
|
|
1380
|
+
{ a: ['b', 'c', 'd'] },
|
|
1381
|
+
'duplicate plain keys combine into array'
|
|
1382
|
+
);
|
|
1383
|
+
st.end();
|
|
1384
|
+
});
|
|
1385
|
+
|
|
1386
|
+
t.test('multiple plain values exceeding limit', function (st) {
|
|
1387
|
+
st.deepEqual(
|
|
1388
|
+
qs.parse('a=b&a=c&a=d', { arrayLimit: 2 }),
|
|
1389
|
+
{ a: { 0: 'b', 1: 'c', 2: 'd' } },
|
|
1390
|
+
'duplicate plain keys convert to object when exceeding limit'
|
|
1391
|
+
);
|
|
1392
|
+
st.end();
|
|
1393
|
+
});
|
|
1394
|
+
|
|
1395
|
+
t.end();
|
|
1396
|
+
});
|
|
@@ -8,7 +8,8 @@ var SaferBuffer = require('safer-buffer').Buffer;
|
|
|
8
8
|
var hasSymbols = require('has-symbols');
|
|
9
9
|
var mockProperty = require('mock-property');
|
|
10
10
|
var emptyTestCases = require('./empty-keys-cases').emptyTestCases;
|
|
11
|
-
var
|
|
11
|
+
var hasProto = require('has-proto')();
|
|
12
|
+
var hasBigInt = require('has-bigints')();
|
|
12
13
|
|
|
13
14
|
test('stringify()', function (t) {
|
|
14
15
|
t.test('stringifies a querystring object', function (st) {
|
|
@@ -650,10 +651,8 @@ test('stringify()', function (t) {
|
|
|
650
651
|
st.end();
|
|
651
652
|
});
|
|
652
653
|
|
|
653
|
-
t.test('stringifies a null object', { skip: !
|
|
654
|
-
|
|
655
|
-
obj.a = 'b';
|
|
656
|
-
st.equal(qs.stringify(obj), 'a=b');
|
|
654
|
+
t.test('stringifies a null object', { skip: !hasProto }, function (st) {
|
|
655
|
+
st.equal(qs.stringify({ __proto__: null, a: 'b' }), 'a=b');
|
|
657
656
|
st.end();
|
|
658
657
|
});
|
|
659
658
|
|
|
@@ -665,11 +664,8 @@ test('stringify()', function (t) {
|
|
|
665
664
|
st.end();
|
|
666
665
|
});
|
|
667
666
|
|
|
668
|
-
t.test('stringifies an object with a null object as a child', { skip: !
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
obj.a.b = 'c';
|
|
672
|
-
st.equal(qs.stringify(obj), 'a%5Bb%5D=c');
|
|
667
|
+
t.test('stringifies an object with a null object as a child', { skip: !hasProto }, function (st) {
|
|
668
|
+
st.equal(qs.stringify({ a: { __proto__: null, b: 'c' } }), 'a%5Bb%5D=c');
|
|
673
669
|
st.end();
|
|
674
670
|
});
|
|
675
671
|
|
|
@@ -1254,7 +1250,7 @@ test('stringify()', function (t) {
|
|
|
1254
1250
|
};
|
|
1255
1251
|
|
|
1256
1252
|
st.equal(
|
|
1257
|
-
qs.stringify(obj, { arrayFormat: '
|
|
1253
|
+
qs.stringify(obj, { arrayFormat: 'brackets', charset: 'utf-8' }),
|
|
1258
1254
|
'foo=' + expected.join('')
|
|
1259
1255
|
);
|
|
1260
1256
|
|
|
@@ -1295,4 +1291,20 @@ test('stringifies empty keys', function (t) {
|
|
|
1295
1291
|
|
|
1296
1292
|
st.end();
|
|
1297
1293
|
});
|
|
1294
|
+
|
|
1295
|
+
t.test('stringifies non-string keys', function (st) {
|
|
1296
|
+
var S = Object('abc');
|
|
1297
|
+
S.toString = function () {
|
|
1298
|
+
return 'd';
|
|
1299
|
+
};
|
|
1300
|
+
var actual = qs.stringify({ a: 'b', 'false': {}, 1e+22: 'c', d: 'e' }, {
|
|
1301
|
+
filter: ['a', false, null, 10000000000000000000000, S],
|
|
1302
|
+
allowDots: true,
|
|
1303
|
+
encodeDotInKeys: true
|
|
1304
|
+
});
|
|
1305
|
+
|
|
1306
|
+
st.equal(actual, 'a=b&1e%2B22=c&d=e', 'stringifies correctly');
|
|
1307
|
+
|
|
1308
|
+
st.end();
|
|
1309
|
+
});
|
|
1298
1310
|
});
|