Merge pull request #307 from alibaba/brotli-content-encoding

fix 302, enhance content encoding
This commit is contained in:
Otto Mao 2017-12-29 10:14:18 +08:00 committed by GitHub
commit 8c3727e9c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 15 deletions

View File

@ -12,6 +12,7 @@ const http = require('http'),
logUtil = require('./log'), logUtil = require('./log'),
co = require('co'), co = require('co'),
HttpsServerMgr = require('./httpsServerMgr'), HttpsServerMgr = require('./httpsServerMgr'),
brotliTorb = require('iltorb'),
Readable = require('stream').Readable; Readable = require('stream').Readable;
const requestErrorHandler = require('./requestErrorHandler'); const requestErrorHandler = require('./requestErrorHandler');
@ -94,11 +95,30 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
} else { } else {
const serverResData = Buffer.concat(resDataChunks); const serverResData = Buffer.concat(resDataChunks);
const originContentLen = util.getByteSize(serverResData); const originContentLen = util.getByteSize(serverResData);
// remove gzip related header, and ungzip the content
// note there are other compression types like deflate
const contentEncoding = resHeader['content-encoding'] || resHeader['Content-Encoding'];
const ifServerGzipped = /gzip/i.test(contentEncoding);
const isServerDeflated = /deflate/i.test(contentEncoding);
const isBrotlied = /br/i.test(contentEncoding);
/**
* when the content is unzipped, update the header content
*/
const refactContentEncoding = () => {
if (contentEncoding) {
resHeader['x-anyproxy-origin-content-encoding'] = contentEncoding;
delete resHeader['content-encoding'];
delete resHeader['Content-Encoding'];
}
}
// set origin content length into header // set origin content length into header
resHeader['x-anyproxy-origin-content-length'] = originContentLen; resHeader['x-anyproxy-origin-content-length'] = originContentLen;
// only do unzip when there is res data // only do unzip when there is res data
if (ifServerGzipped && originContentLen) { if (ifServerGzipped && originContentLen) {
refactContentEncoding();
zlib.gunzip(serverResData, (err, buff) => { // TODO test case to cover zlib.gunzip(serverResData, (err, buff) => { // TODO test case to cover
if (err) { if (err) {
rejectParsing(err); rejectParsing(err);
@ -107,6 +127,7 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
} }
}); });
} else if (isServerDeflated && originContentLen) { } else if (isServerDeflated && originContentLen) {
refactContentEncoding();
zlib.inflateRaw(serverResData, (err, buff) => { // TODO test case to cover zlib.inflateRaw(serverResData, (err, buff) => { // TODO test case to cover
if (err) { if (err) {
rejectParsing(err); rejectParsing(err);
@ -114,6 +135,16 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
fulfill(buff); fulfill(buff);
} }
}); });
} else if (isBrotlied && originContentLen) {
refactContentEncoding();
brotliTorb.decompress(serverResData, (err, buff) => {
if (err) {
rejectParsing(err);
} else {
fulfill(buff);
}
});
} else { } else {
fulfill(serverResData); fulfill(serverResData);
} }
@ -131,12 +162,6 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
}); });
}; };
// remove gzip related header, and ungzip the content
// note there are other compression types like deflate
const contentEncoding = resHeader['content-encoding'] || resHeader['Content-Encoding'];
const ifServerGzipped = /gzip/i.test(contentEncoding);
const isServerDeflated = /deflate/i.test(contentEncoding);
//deal response data //deal response data
res.on('data', (chunk) => { res.on('data', (chunk) => {
rawResChunks.push(chunk); rawResChunks.push(chunk);
@ -265,7 +290,6 @@ function getUserReqHandler(userRule, recorder) {
const responseBody = responseInfo.body || ''; const responseBody = responseInfo.body || '';
const transferEncoding = resHeader['transfer-encoding'] || resHeader['Transfer-Encoding'] || ''; const transferEncoding = resHeader['transfer-encoding'] || resHeader['Transfer-Encoding'] || '';
const contentEncoding = resHeader['content-encoding'] || resHeader['Content-Encoding'];
const contentLength = resHeader['content-length'] || resHeader['Content-Length']; const contentLength = resHeader['content-length'] || resHeader['Content-Length'];
const connection = resHeader.Connection || resHeader.connection; const connection = resHeader.Connection || resHeader.connection;
if (contentLength) { if (contentLength) {
@ -273,12 +297,6 @@ function getUserReqHandler(userRule, recorder) {
delete resHeader['Content-Length']; delete resHeader['Content-Length'];
} }
if (contentEncoding) {
resHeader['x-anyproxy-origin-content-encoding'] = contentEncoding;
delete resHeader['content-encoding'];
delete resHeader['Content-Encoding'];
}
// set proxy-connection // set proxy-connection
if (connection) { if (connection) {
resHeader['x-anyproxy-origin-connection'] = connection; resHeader['x-anyproxy-origin-connection'] = connection;

View File

@ -21,6 +21,7 @@
"es6-promise": "^3.3.1", "es6-promise": "^3.3.1",
"express": "^4.8.5", "express": "^4.8.5",
"iconv-lite": "^0.4.6", "iconv-lite": "^0.4.6",
"iltorb": "^2.0.3",
"inquirer": "^3.0.1", "inquirer": "^3.0.1",
"ip": "^0.3.2", "ip": "^0.3.2",
"juicer": "^0.6.6-stable", "juicer": "^0.6.6-stable",
@ -92,7 +93,7 @@
"worker-loader": "^0.7.1" "worker-loader": "^0.7.1"
}, },
"scripts": { "scripts": {
"prepublish":"npm run buildweb", "prepublish": "npm run buildweb",
"test": "node test.js", "test": "node test.js",
"lint": "eslint .", "lint": "eslint .",
"testserver": "node test/server/startServer.js", "testserver": "node test/server/startServer.js",