Skip to content

Commit

Permalink
Merge pull request #2492 from addaleax/lenient-gzip
Browse files Browse the repository at this point in the history
More lenient gzip decompression
  • Loading branch information
simov committed Dec 21, 2016
2 parents 76eb485 + 71081b6 commit f009af2
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
13 changes: 11 additions & 2 deletions request.js
Expand Up @@ -946,11 +946,20 @@ Request.prototype.onRequestResponse = function (response) {
var contentEncoding = response.headers['content-encoding'] || 'identity'
contentEncoding = contentEncoding.trim().toLowerCase()

// Be more lenient with decoding compressed responses, since (very rarely)
// servers send slightly invalid gzip responses that are still accepted
// by common browsers.
// Always using Z_SYNC_FLUSH is what cURL does.
var zlibOptions = {
flush: zlib.Z_SYNC_FLUSH
, finishFlush: zlib.Z_SYNC_FLUSH
}

if (contentEncoding === 'gzip') {
responseContent = zlib.createGunzip()
responseContent = zlib.createGunzip(zlibOptions)
response.pipe(responseContent)
} else if (contentEncoding === 'deflate') {
responseContent = zlib.createInflate()
responseContent = zlib.createInflate(zlibOptions)
response.pipe(responseContent)
} else {
// Since previous versions didn't check for Content-Encoding header,
Expand Down
16 changes: 16 additions & 0 deletions tests/test-gzip.js
Expand Up @@ -39,6 +39,12 @@ var server = http.createServer(function(req, res) {
res.writeHead(200)
res.write(testContentBigGzip.slice(0, 4096))
setTimeout(function() { res.end(testContentBigGzip.slice(4096)) }, 10)
} else if (req.url === '/just-slightly-truncated') {
zlib.gzip(testContent, function(err, data) {
assert.equal(err, null)
// truncate the CRC checksum and size check at the end of the stream
res.end(data.slice(0, data.length-8))
})
} else {
zlib.gzip(testContent, function(err, data) {
assert.equal(err, null)
Expand Down Expand Up @@ -96,6 +102,16 @@ tape('transparently supports gzip decoding to callbacks', function(t) {
})
})

tape('supports slightly invalid gzip content', function(t) {
var options = { url: server.url + '/just-slightly-truncated', gzip: true }
request.get(options, function(err, res, body) {
t.equal(err, null)
t.equal(res.headers['content-encoding'], 'gzip')
t.equal(body, testContent)
t.end()
})
})

tape('transparently supports gzip decoding to pipes', function(t) {
var options = { url: server.url + '/foo', gzip: true }
var chunks = []
Expand Down

0 comments on commit f009af2

Please sign in to comment.