Merge branch 'master' into ws-proxy

This commit is contained in:
砚然
2018-01-21 19:43:02 +08:00
24 changed files with 312 additions and 149 deletions

View File

@@ -13,6 +13,7 @@ const http = require('http'),
co = require('co'),
WebSocket = require('ws'),
HttpsServerMgr = require('./httpsServerMgr'),
brotliTorb = require('brotli'),
Readable = require('stream').Readable;
const requestErrorHandler = require('./requestErrorHandler');
@@ -94,11 +95,31 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
fulfill(resDataStream);
} else {
const serverResData = Buffer.concat(resDataChunks);
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);
// put origin content length into header
resHeader['x-anyproxy-origin-content-length'] = util.getByteSize(serverResData);
/**
* 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'];
}
}
if (ifServerGzipped) {
// set origin content length into header
resHeader['x-anyproxy-origin-content-length'] = originContentLen;
// only do unzip when there is res data
if (ifServerGzipped && originContentLen) {
refactContentEncoding();
zlib.gunzip(serverResData, (err, buff) => { // TODO test case to cover
if (err) {
rejectParsing(err);
@@ -106,7 +127,8 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
fulfill(buff);
}
});
} else if (isServerDeflated) {
} else if (isServerDeflated && originContentLen) {
refactContentEncoding();
zlib.inflateRaw(serverResData, (err, buff) => { // TODO test case to cover
if (err) {
rejectParsing(err);
@@ -114,6 +136,16 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
fulfill(buff);
}
});
} else if (isBrotlied && originContentLen) {
refactContentEncoding();
try {
// an Unit8Array returned by decompression
const result = brotliTorb.decompress(serverResData);
fulfill(Buffer.from(result));
} catch (e) {
rejectParsing(e);
}
} else {
fulfill(serverResData);
}
@@ -131,12 +163,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
res.on('data', (chunk) => {
rawResChunks.push(chunk);
@@ -160,7 +186,7 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
res.on('end', () => {
if (resDataStream) {
resDataStream.emit('end'); // EOF
resDataStream.push(null); // indicate the stream is end
} else {
finishCollecting();
}
@@ -293,7 +319,6 @@ function getUserReqHandler(userRule, recorder) {
const responseBody = responseInfo.body || '';
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 connection = resHeader.Connection || resHeader.connection;
if (contentLength) {
@@ -301,12 +326,6 @@ function getUserReqHandler(userRule, recorder) {
delete resHeader['Content-Length'];
}
if (contentEncoding) {
resHeader['x-anyproxy-origin-content-encoding'] = contentEncoding;
delete resHeader['content-encoding'];
delete resHeader['Content-Encoding'];
}
// set proxy-connection
if (connection) {
resHeader['x-anyproxy-origin-connection'] = connection;