From b6c7088965ecb5a82d1f4155b754cca3fc4aeee9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=A0=9A=E7=84=B6?= <yanran.wwj@alipay.com>
Date: Thu, 14 Dec 2017 23:58:52 +0800
Subject: [PATCH] do not unzip the response body when it's empty, such as 304

also remove the delete operatoin for 'accept-encoding' in the test utils, since AnyProxy will not remove the header now
---
 lib/requestHandler.js          | 11 ++++++-----
 test/jasmine.json              |  2 +-
 test/server/server.js          |  5 +++++
 test/spec_rule/no_rule_spec.js | 25 +++++++++++++++++++++++++
 test/util/CommonUtil.js        |  7 -------
 5 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/lib/requestHandler.js b/lib/requestHandler.js
index a7e86ea..ecde92b 100644
--- a/lib/requestHandler.js
+++ b/lib/requestHandler.js
@@ -93,11 +93,12 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
             fulfill(resDataStream);
           } else {
             const serverResData = Buffer.concat(resDataChunks);
+            const originContentLen = util.getByteSize(serverResData);
+            // set origin content length into header
+            resHeader['x-anyproxy-origin-content-length'] = originContentLen;
 
-            // put origin content length into header
-            resHeader['x-anyproxy-origin-content-length'] = util.getByteSize(serverResData);
-
-            if (ifServerGzipped) {
+            // only do unzip when there is res data
+            if (ifServerGzipped && originContentLen) {
               zlib.gunzip(serverResData, (err, buff) => { // TODO test case to cover
                 if (err) {
                   rejectParsing(err);
@@ -105,7 +106,7 @@ function fetchRemoteResponse(protocol, options, reqData, config) {
                   fulfill(buff);
                 }
               });
-            } else if (isServerDeflated) {
+            } else if (isServerDeflated && originContentLen) {
               zlib.inflateRaw(serverResData, (err, buff) => { // TODO test case to cover
                 if (err) {
                   rejectParsing(err);
diff --git a/test/jasmine.json b/test/jasmine.json
index 689230e..057167a 100644
--- a/test/jasmine.json
+++ b/test/jasmine.json
@@ -8,6 +8,6 @@
      "../node_modules/babel-register/lib/node.js",
      "../node_modules/babel-polyfill/dist/polyfill.js"
   ],
-  "stopSpecOnExpectationFailure": true,
+  "stopSpecOnExpectationFailure": false,
   "random": false
 }
diff --git a/test/server/server.js b/test/server/server.js
index f37c43f..d674633 100644
--- a/test/server/server.js
+++ b/test/server/server.js
@@ -103,6 +103,11 @@ KoaServer.prototype.constructRouter = function () {
     });
   });
 
+  router.get('/test/response/304', this.logRequest, function *(next) {
+    this.response.set('Content-Encoding', 'gzip');
+    this.status = 304;
+  });
+
   router.get('/test/response/303', function *(next) {
     printLog('now to redirect 303');
     this.redirect('/test');
diff --git a/test/spec_rule/no_rule_spec.js b/test/spec_rule/no_rule_spec.js
index 6e9e123..8157076 100644
--- a/test/spec_rule/no_rule_spec.js
+++ b/test/spec_rule/no_rule_spec.js
@@ -212,6 +212,31 @@ function testRequest(protocol = 'http') {
         });
     });
 
+    it('304 should work as direct without proxy rules', (done) => {
+      const url = constructUrl('/test/response/304');
+
+      proxyGet(url, CommonRequestHeader)
+        .then(proxyRes => {
+          directGet(url, CommonRequestHeader)
+            .then(directRes => {
+              expect(directRes.statusCode).toEqual(304);
+              expect(directRes.body).toEqual('');
+
+              expect(directRes.statusCode).toEqual(proxyRes.statusCode);
+              expect(isCommonResHeaderEqual(directRes.headers, proxyRes.headers, url)).toBe(true);
+              expect(directRes.body).toEqual(proxyRes.body);
+              expect(isCommonReqEqual(url, serverInstance)).toBe(true);
+              done();
+            }, error => {
+              console.error('error happened in direct 304 request:', error);
+              done.fail('error happened in direct 304 request');
+            });
+        }, error => {
+          console.error('error happened in proxy 304 request:', error);
+          done.fail('error happened in proxy 304 request');
+        });
+    })
+
     describe('Response code should be honored as direct without proxy rules', () => {
       [301, 302, 303].forEach(code => {
         testRedirect(code);
diff --git a/test/util/CommonUtil.js b/test/util/CommonUtil.js
index 75a3751..1d20e7e 100644
--- a/test/util/CommonUtil.js
+++ b/test/util/CommonUtil.js
@@ -130,13 +130,6 @@ function isCommonReqEqual(url, serverInstance) {
     isEqual = isEqual && proxyReqObj.headers['via-proxy'] === 'true';
     delete proxyReqObj.headers['via-proxy'];
 
-    // exclued accept-encoding from comparing, since the proxy will remove it before sending it out
-    delete directReqObj.headers['accept-encoding'];
-
-    // TODO: 我这里proxy出去的options里没有accept-encoding, 但node自己加上了。Why ?
-    // By 加里 2017.1.31
-    delete proxyReqObj.headers['accept-encoding'];
-
     directReqObj.headers['content-type'] = trimFormContentType(directReqObj.headers['content-type']);
     proxyReqObj.headers['content-type'] = trimFormContentType(proxyReqObj.headers['content-type']);