Skip to content

Commit dbdff43

Browse files
committed
Merge pull request #25 from hapijs/qs
Remove qs support. Closes #24
2 parents 131b4f1 + f401a78 commit dbdff43

File tree

3 files changed

+25
-175
lines changed

3 files changed

+25
-175
lines changed

lib/index.js

+5-12
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
const Fs = require('fs');
66
const Os = require('os');
7+
const Querystring = require('querystring');
78
const Stream = require('stream');
89
const Zlib = require('zlib');
910
const Boom = require('boom');
1011
const Content = require('content');
1112
const Hoek = require('hoek');
1213
const Pez = require('pez');
13-
const Qs = require('qs');
1414
const Wreck = require('wreck');
1515

1616

@@ -257,7 +257,7 @@ internals.object = function (payload, mime, options, next) {
257257
// Form-encoded
258258

259259
if (mime === 'application/x-www-form-urlencoded') {
260-
return next(null, payload.length ? Qs.parse(payload.toString('utf8'), options.qs) : {});
260+
return next(null, payload.length ? Querystring.parse(payload.toString('utf8')) : {});
261261
}
262262

263263
return next(Boom.unsupportedMediaType());
@@ -302,8 +302,7 @@ internals.Parser.prototype.multipart = function (source, contentType) {
302302

303303
dispenser.once('error', onError);
304304

305-
let arrayFields = false;
306-
let data = {};
305+
const data = {};
307306
const finalize = () => {
308307

309308
clearTimeout(clientTimeoutId);
@@ -312,10 +311,6 @@ internals.Parser.prototype.multipart = function (source, contentType) {
312311
dispenser.removeListener('field', onField);
313312
dispenser.removeListener('close', onClose);
314313

315-
if (arrayFields) {
316-
data = Qs.parse(data, this.settings.qs);
317-
}
318-
319314
this.result.payload = data;
320315
return next();
321316
};
@@ -331,8 +326,6 @@ internals.Parser.prototype.multipart = function (source, contentType) {
331326

332327
const set = (name, value) => {
333328

334-
arrayFields = arrayFields || (name.indexOf('[') !== -1);
335-
336329
if (!data.hasOwnProperty(name)) {
337330
data[name] = value;
338331
}
@@ -378,9 +371,9 @@ internals.Parser.prototype.multipart = function (source, contentType) {
378371
});
379372
}
380373
else { // Output: 'data'
381-
Wreck.read(part, {}, (err, payload) => {
374+
Wreck.read(part, {}, (ignoreErr, payload) => {
382375

383-
// err handled by dispenser.once('error')
376+
// Error handled by dispenser.once('error')
384377

385378
if (this.settings.output === 'stream') { // Output: 'stream'
386379
const item = Wreck.toReadableStream(payload);

package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "subtext",
33
"description": "HTTP payload parsing",
4-
"version": "3.0.1",
4+
"version": "4.0.0",
55
"repository": "git://github.com/hapijs/subtext",
66
"main": "lib/index.js",
77
"keywords": [
@@ -19,13 +19,12 @@
1919
"content": "3.x.x",
2020
"hoek": "3.x.x",
2121
"pez": "2.x.x",
22-
"qs": "6.x.x",
2322
"wreck": "7.x.x"
2423
},
2524
"devDependencies": {
2625
"code": "2.x.x",
2726
"form-data": "0.1.x",
28-
"lab": "7.x.x"
27+
"lab": "8.x.x"
2928
},
3029
"scripts": {
3130
"test": "lab -a code -t 100 -L",

test/index.js

+18-160
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ describe('parse()', () => {
7979
expect(parsed.mime).to.equal('application/json');
8080
Wreck.read(parsed.payload, null, (err, result) => {
8181

82+
expect(err).to.not.exist();
8283
expect(result.toString()).to.equal(payload);
8384
done();
8485
});
@@ -99,6 +100,7 @@ describe('parse()', () => {
99100
expect(parsed.mime).to.equal('application/json');
100101
Wreck.read(parsed.payload, null, (err, result) => {
101102

103+
expect(err).to.not.exist();
102104
expect(result.toString()).to.equal(payload);
103105
done();
104106
});
@@ -316,6 +318,7 @@ describe('parse()', () => {
316318

317319
Zlib.gzip(sourceContents, (err, compressed) => {
318320

321+
expect(err).to.not.exist();
319322
const request = Wreck.toReadableStream(compressed);
320323
request.headers = {
321324
'content-encoding': 'gzip'
@@ -341,6 +344,7 @@ describe('parse()', () => {
341344

342345
Zlib.gzip(sourceContents, (err, compressed) => {
343346

347+
expect(err).to.not.exist();
344348
const request = Wreck.toReadableStream(compressed);
345349
request.headers = {
346350
'content-encoding': 'gzip',
@@ -587,57 +591,6 @@ describe('parse()', () => {
587591
});
588592
});
589593

590-
it('parses form encoded payload (array keys)', (done) => {
591-
592-
const payload = 'x[y]=1&x[z]=2';
593-
const request = Wreck.toReadableStream(payload);
594-
request.headers = {
595-
'content-type': 'application/x-www-form-urlencoded'
596-
};
597-
598-
Subtext.parse(request, null, { parse: true, output: 'data' }, (err, parsed) => {
599-
600-
expect(err).to.not.exist();
601-
expect(parsed.mime).to.equal('application/x-www-form-urlencoded');
602-
expect(parsed.payload).to.deep.equal({ x: { y: '1', z: '2' } });
603-
done();
604-
});
605-
});
606-
607-
it('parses form encoded payload (with qs arraylimit set to 0)', (done) => {
608-
609-
const payload = 'x[0]=1&x[100]=2';
610-
const request = Wreck.toReadableStream(payload);
611-
request.headers = {
612-
'content-type': 'application/x-www-form-urlencoded'
613-
};
614-
615-
Subtext.parse(request, null, { parse: true, output: 'data', qs: { arrayLimit: 0 } }, (err, parsed) => {
616-
617-
expect(err).to.not.exist();
618-
expect(parsed.mime).to.equal('application/x-www-form-urlencoded');
619-
expect(parsed.payload).to.deep.equal({ x: { 0: '1', 100: '2' } });
620-
done();
621-
});
622-
});
623-
624-
it('parses form encoded payload (with qs arraylimit set to 30) as flat zero indexed array', (done) => {
625-
626-
const payload = 'x[0]=0&x[1]=1&x[2]=2&x[3]=3&x[4]=4&x[5]=5&x[6]=6&x[7]=7&x[8]=8&x[9]=9&x[10]=10&x[11]=11&x[12]=12&x[13]=13&x[14]=14&x[15]=15&x[16]=16&x[17]=17&x[18]=18&x[19]=19&x[20]=20&x[21]=21&x[22]=22&x[23]=23&x[24]=24&x[25]=25&x[26]=26&x[27]=27&x[28]=28&x[29]=29&';
627-
const request = Wreck.toReadableStream(payload);
628-
request.headers = {
629-
'content-type': 'application/x-www-form-urlencoded'
630-
};
631-
632-
Subtext.parse(request, null, { parse: true, output: 'data', qs: { arrayLimit: 30 } }, (err, parsed) => {
633-
634-
expect(err).to.not.exist();
635-
expect(parsed.mime).to.equal('application/x-www-form-urlencoded');
636-
expect(parsed.payload).to.deep.equal({ x: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29'] });
637-
done();
638-
});
639-
});
640-
641594
it('errors on malformed zipped payload', (done) => {
642595

643596
const payload = '7d8d78347h8347d58w347hd58w374d58w37h5d8w37hd4';
@@ -677,6 +630,7 @@ describe('parse()', () => {
677630
const payload = '{"x":"1","y":"2","z":"3"}';
678631
Zlib.gzip(payload, (err, compressed) => {
679632

633+
expect(err).to.not.exist();
680634
const request = Wreck.toReadableStream(compressed);
681635
request.headers = {
682636
'content-encoding': 'gzip',
@@ -697,6 +651,7 @@ describe('parse()', () => {
697651
const payload = '{"x":"1","y":"2","z":"3"}';
698652
Zlib.gzip(payload, (err, compressed) => {
699653

654+
expect(err).to.not.exist();
700655
const request = Wreck.toReadableStream(compressed);
701656
request.headers = {
702657
'content-encoding': 'gzip',
@@ -717,6 +672,7 @@ describe('parse()', () => {
717672
const payload = '{"x":"1","y":"2","z":"3"}';
718673
Zlib.deflate(payload, (err, compressed) => {
719674

675+
expect(err).to.not.exist();
720676
const request = Wreck.toReadableStream(compressed);
721677
request.headers = {
722678
'content-encoding': 'deflate',
@@ -737,6 +693,7 @@ describe('parse()', () => {
737693
const payload = '{"x":"1","y":"2","z":"3"}';
738694
Zlib.deflate(payload, (err, compressed) => {
739695

696+
expect(err).to.not.exist();
740697
const request = Wreck.toReadableStream(compressed);
741698
request.headers = {
742699
'content-encoding': 'deflate',
@@ -800,55 +757,7 @@ describe('parse()', () => {
800757
});
801758
});
802759

803-
it('parses a multipart payload with qs arraylimit set to zero', (done) => {
804-
805-
const payload =
806-
'--AaB03x\r\n' +
807-
'content-disposition: form-data; name="x[0]"\r\n' +
808-
'\r\n' +
809-
'First\r\n' +
810-
'--AaB03x\r\n' +
811-
'content-disposition: form-data; name="x[1]"\r\n' +
812-
'\r\n' +
813-
'Second\r\n' +
814-
'--AaB03x\r\n' +
815-
'content-disposition: form-data; name="x[30]"\r\n' +
816-
'\r\n' +
817-
'Third\r\n' +
818-
'--AaB03x\r\n' +
819-
'content-disposition: form-data; name="field1"\r\n' +
820-
'\r\n' +
821-
'Joe Blow\r\nalmost tricked you!\r\n' +
822-
'--AaB03x\r\n' +
823-
'content-disposition: form-data; name="field1"\r\n' +
824-
'\r\n' +
825-
'Repeated name segment\r\n' +
826-
'--AaB03x\r\n' +
827-
'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' +
828-
'Content-Type: text/plain\r\n' +
829-
'\r\n' +
830-
'... contents of file1.txt ...\r\r\n' +
831-
'--AaB03x--\r\n';
832-
833-
const request = Wreck.toReadableStream(payload);
834-
request.headers = {
835-
'content-type': 'multipart/form-data; boundary=AaB03x'
836-
};
837-
838-
Subtext.parse(request, null, { parse: true, output: 'data', qs: { arrayLimit: 0 } }, (err, parsed) => {
839-
840-
expect(err).to.not.exist();
841-
expect(parsed.payload).to.deep.equal({
842-
x: { '0': 'First', '1': 'Second', '30': 'Third' },
843-
field1: ['Joe Blow\r\nalmost tricked you!', 'Repeated name segment'],
844-
pics: '... contents of file1.txt ...\r'
845-
});
846-
847-
done();
848-
});
849-
});
850-
851-
it('parses a multipart payload', (done) => {
760+
it('parses a multipart payload (ignores unknown mime type)', (done) => {
852761

853762
const payload =
854763
'--AaB03x\r\n' +
@@ -873,7 +782,7 @@ describe('parse()', () => {
873782
'Repeated name segment\r\n' +
874783
'--AaB03x\r\n' +
875784
'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' +
876-
'Content-Type: text/plain\r\n' +
785+
'Content-Type: unknown/X\r\n' +
877786
'\r\n' +
878787
'... contents of file1.txt ...\r\r\n' +
879788
'--AaB03x--\r\n';
@@ -889,7 +798,7 @@ describe('parse()', () => {
889798
expect(parsed.payload).to.deep.equal({
890799
x: ['First', 'Second', 'Third'],
891800
field1: ['Joe Blow\r\nalmost tricked you!', 'Repeated name segment'],
892-
pics: '... contents of file1.txt ...\r'
801+
pics: new Buffer('... contents of file1.txt ...\r')
893802
});
894803

895804
done();
@@ -1061,10 +970,13 @@ describe('parse()', () => {
1061970

1062971
Wreck.read(parsed.payload.files[1], null, (err, payload2) => {
1063972

973+
expect(err).to.not.exist();
1064974
Wreck.read(parsed.payload.files[0], null, (err, payload1) => {
1065975

976+
expect(err).to.not.exist();
1066977
Wreck.read(parsed.payload.files[2], null, (err, payload3) => {
1067978

979+
expect(err).to.not.exist();
1068980
expect(payload1.toString()).to.equal('one');
1069981
expect(payload2.toString()).to.equal('two');
1070982
expect(payload3.toString()).to.equal('three');
@@ -1349,61 +1261,6 @@ describe('parse()', () => {
13491261
});
13501262
});
13511263

1352-
it('parses field names with arrays', (done) => {
1353-
1354-
const payload = '--AaB03x\r\n' +
1355-
'Content-Disposition: form-data; name="a[b]"\r\n' +
1356-
'\r\n' +
1357-
'3\r\n' +
1358-
'--AaB03x\r\n' +
1359-
'Content-Disposition: form-data; name="a[c]"\r\n' +
1360-
'\r\n' +
1361-
'4\r\n' +
1362-
'--AaB03x--\r\n';
1363-
1364-
const request = Wreck.toReadableStream(payload);
1365-
request.headers = {
1366-
'content-type': 'multipart/form-data; boundary=AaB03x'
1367-
};
1368-
1369-
Subtext.parse(request, null, { parse: true, output: 'data' }, (err, parsed) => {
1370-
1371-
expect(err).to.not.exist();
1372-
expect(parsed.payload.a.b + parsed.payload.a.c).to.equal('34');
1373-
done();
1374-
});
1375-
});
1376-
1377-
it('parses field names with arrays and file', (done) => {
1378-
1379-
const payload = '----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n' +
1380-
'Content-Disposition: form-data; name="a[b]"\r\n' +
1381-
'\r\n' +
1382-
'3\r\n' +
1383-
'----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n' +
1384-
'Content-Disposition: form-data; name="a[c]"\r\n' +
1385-
'\r\n' +
1386-
'4\r\n' +
1387-
'----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n' +
1388-
'Content-Disposition: form-data; name="file"; filename="test.txt"\r\n' +
1389-
'Content-Type: plain/text\r\n' +
1390-
'\r\n' +
1391-
'and\r\n' +
1392-
'----WebKitFormBoundaryE19zNvXGzXaLvS5C--\r\n';
1393-
1394-
const request = Wreck.toReadableStream(payload);
1395-
request.headers = {
1396-
'content-type': 'multipart/form-data; boundary="--WebKitFormBoundaryE19zNvXGzXaLvS5C"'
1397-
};
1398-
1399-
Subtext.parse(request, null, { parse: true, output: 'data' }, (err, parsed) => {
1400-
1401-
expect(err).to.not.exist();
1402-
expect(parsed.payload.a.b + parsed.payload.file + parsed.payload.a.c).to.equal('3and4');
1403-
done();
1404-
});
1405-
});
1406-
14071264
it('cleans file when stream is aborted', (done) => {
14081265

14091266
const path = Path.join(__dirname, 'file');
@@ -1414,6 +1271,7 @@ describe('parse()', () => {
14141271

14151272
Subtext.parse(req, null, { parse: false, output: 'file', uploads: path }, (err, parsed) => {
14161273

1274+
expect(err).to.exist();
14171275
expect(Fs.readdirSync(path).length).to.equal(count);
14181276
done();
14191277
});
@@ -1431,7 +1289,7 @@ describe('parse()', () => {
14311289

14321290
const req = Http.request(options, (res) => { });
14331291

1434-
req.on('error', (err) => { });
1292+
req.on('error', () => { });
14351293

14361294
const random = new Buffer(100000);
14371295
req.write(random);
@@ -1480,7 +1338,7 @@ describe('parse()', () => {
14801338
Subtext.parse(form, null, { parse: true, output: 'stream', timeout: 1 }, (err, parsed) => {
14811339

14821340
expect(err).to.exist();
1483-
expect(err.message).to.equal('Request Timeout');
1341+
expect(err.message).to.equal('Request Time-out');
14841342
expect(err.output.statusCode).to.equal(408);
14851343
done();
14861344
});
@@ -1498,7 +1356,7 @@ describe('parse()', () => {
14981356
Subtext.parse(form, null, { parse: true, output: 'file', timeout: 1 }, (err, parsed) => {
14991357

15001358
expect(err).to.exist();
1501-
expect(err.message).to.equal('Request Timeout');
1359+
expect(err.message).to.equal('Request Time-out');
15021360
expect(err.output.statusCode).to.equal(408);
15031361
done();
15041362
});

0 commit comments

Comments
 (0)