diff --git a/lib/plugins/bodyReader.js b/lib/plugins/bodyReader.js index eb6c10682..e61f6aa5e 100644 --- a/lib/plugins/bodyReader.js +++ b/lib/plugins/bodyReader.js @@ -58,7 +58,7 @@ function createBodyWriter(req) { * * @public * @function bodyReader - * @throws {BadDigestError | PayloadTooLargeError} + * @throws {BadDigestError | PayloadTooLargeError | InvalidContentError} * @param {Object} options - an options object * @returns {Function} Handler */ @@ -155,6 +155,14 @@ function bodyReader(options) { gz = zlib.createGunzip(); gz.on('data', bodyWriter.write); gz.once('end', done); + gz.once('error', function onGunzipError(err) { + next( + new errors.InvalidContentError( + '%s', + 'Invalid gzip: ' + err.message + ) + ); + }); req.once('end', gz.end.bind(gz)); } else { unsupportedContentEncoding = req.headers['content-encoding']; diff --git a/test/plugins/bodyReader.test.js b/test/plugins/bodyReader.test.js index cd20fb949..0c8992d7a 100644 --- a/test/plugins/bodyReader.test.js +++ b/test/plugins/bodyReader.test.js @@ -96,6 +96,97 @@ describe('body reader', function() { ); }); + it('should not crash on an empty gzip body', function(done) { + SERVER.use(restify.plugins.bodyParser()); + + CLIENT = restifyClients.createJsonClient({ + url: 'http://127.0.0.1:' + PORT, + retry: false + }); + + SERVER.get('/hello', function(req, res, next) { + res.send(200, { hello: 'world' }); + next(); + }); + + var req = http.request( + { + hostname: '127.0.0.1', + port: PORT, + path: '/hello', + method: 'GET', + headers: { + 'Content-Encoding': 'gzip', + 'Content-Type': 'application/json' + } + }, + function(res) { + var body = ''; + res.on('data', function(chunk) { + body += chunk; + }); + res.on('end', function() { + assert.equal(res.statusCode, 400); + var rsp = JSON.parse(body); + assert.equal(rsp.code, 'InvalidContent'); + CLIENT.get('/hello', function(err, _, okRes) { + assert.ifError(err); + assert.equal(okRes.statusCode, 200); + done(); + }); + }); + } + ); + + req.on('error', done); + req.end(); + }); + + it('should not crash on invalid gzip content', function(done) { + SERVER.use(restify.plugins.bodyParser()); + + CLIENT = restifyClients.createJsonClient({ + url: 'http://127.0.0.1:' + PORT, + retry: false + }); + + SERVER.post('/hello', function(req, res, next) { + res.send(200, { hello: 'world' }); + next(); + }); + + var payload = Buffer.from('not-gzip'); + var req = http.request( + { + hostname: '127.0.0.1', + port: PORT, + path: '/hello', + method: 'POST', + headers: { + 'Content-Encoding': 'gzip', + 'Content-Type': 'application/json', + 'Content-Length': payload.length + } + }, + function(res) { + var body = ''; + res.on('data', function(chunk) { + body += chunk; + }); + res.on('end', function() { + assert.equal(res.statusCode, 400); + var rsp = JSON.parse(body); + assert.equal(rsp.code, 'InvalidContent'); + done(); + }); + } + ); + + req.on('error', done); + req.write(payload); + req.end(); + }); + it('should parse unencoded content', function(done) { SERVER.use(restify.plugins.bodyParser());