diff --git a/lib/utils.js b/lib/utils.js index 4f21e7ef1e3..10f78864a2d 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -259,6 +259,11 @@ function createETagGenerator (options) { /** * Parse an extended query string with qs. * + * Sets parameterLimit to Infinity to avoid silently truncating + * query parameters. The default qs limit of 1000 parameters + * would cause data loss without any warning. If users need a + * limit for security, they can provide a custom query parser. + * * @param {String} str * @return {Object} * @private @@ -266,6 +271,7 @@ function createETagGenerator (options) { function parseExtendedQueryString(str) { return qs.parse(str, { - allowPrototypes: true + allowPrototypes: true, + parameterLimit: Infinity }); } diff --git a/test/req.query.js b/test/req.query.js index c0d3c8376e9..0bce4916139 100644 --- a/test/req.query.js +++ b/test/req.query.js @@ -38,6 +38,28 @@ describe('req', function(){ .get('/?user.name=tj') .expect(200, '{"user.name":"tj"}', done); }); + + it('should not truncate parameters over 1000', function (done) { + var app = createApp('extended'); + + // Create a query string with 1500 parameters + var params = []; + for (var i = 0; i < 1500; i++) { + params.push('a' + i + '=' + i); + } + var query = params.join('&'); + + request(app) + .get('/?' + query) + .expect(200) + .expect(function (res) { + var keys = Object.keys(res.body); + if (keys.length !== 1500) { + throw new Error('Expected 1500 parameters, got ' + keys.length); + } + }) + .end(done); + }); }); describe('when "query parser" is simple', function () {