From ee0f285e78a5a754069ccb70a179074d58d61fb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=A0=9A=E7=84=B6?= <yanran.wwj@alipay.com>
Date: Thu, 28 Dec 2017 21:31:13 +0800
Subject: [PATCH 1/2] Only update the `content-header` when the content is
 handled by AnyProxy

---
 lib/requestHandler.js | 34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/lib/requestHandler.js b/lib/requestHandler.js
index ecde92b..2480102 100644
--- a/lib/requestHandler.js
+++ b/lib/requestHandler.js
@@ -94,11 +94,29 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
           } 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);
+
+            /**
+             * 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
             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);
@@ -107,6 +125,7 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
                 }
               });
             } else if (isServerDeflated && originContentLen) {
+              refactContentEncoding();
               zlib.inflateRaw(serverResData, (err, buff) => { // TODO test case to cover
                 if (err) {
                   rejectParsing(err);
@@ -131,12 +150,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);
@@ -265,7 +278,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) {
@@ -273,12 +285,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;

From 63170983674a50b3d08ea3ee1f4cc55721add0d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=A0=9A=E7=84=B6?= <yanran.wwj@alipay.com>
Date: Thu, 28 Dec 2017 21:57:10 +0800
Subject: [PATCH 2/2] Support to decompress the brotli content-encoding

---
 lib/requestHandler.js | 12 ++++++++++++
 package.json          |  3 ++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/lib/requestHandler.js b/lib/requestHandler.js
index 2480102..bba6b7f 100644
--- a/lib/requestHandler.js
+++ b/lib/requestHandler.js
@@ -12,6 +12,7 @@ const http = require('http'),
   logUtil = require('./log'),
   co = require('co'),
   HttpsServerMgr = require('./httpsServerMgr'),
+  brotliTorb = require('iltorb'),
   Readable = require('stream').Readable;
 
 const requestErrorHandler = require('./requestErrorHandler');
@@ -99,6 +100,7 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
             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
@@ -133,6 +135,16 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
                   fulfill(buff);
                 }
               });
+            } else if (isBrotlied && originContentLen) {
+              refactContentEncoding();
+
+              brotliTorb.decompress(serverResData, (err, buff) => {
+                if (err) {
+                  rejectParsing(err);
+                } else {
+                  fulfill(buff);
+                }
+              });
             } else {
               fulfill(serverResData);
             }
diff --git a/package.json b/package.json
index e2008d5..37bdea5 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
     "es6-promise": "^3.3.1",
     "express": "^4.8.5",
     "iconv-lite": "^0.4.6",
+    "iltorb": "^2.0.3",
     "inquirer": "^3.0.1",
     "ip": "^0.3.2",
     "juicer": "^0.6.6-stable",
@@ -92,7 +93,7 @@
     "worker-loader": "^0.7.1"
   },
   "scripts": {
-    "prepublish":"npm run buildweb",
+    "prepublish": "npm run buildweb",
     "test": "node test.js",
     "lint": "eslint .",
     "testserver": "node test/server/startServer.js",