Repository: mitmproxy/mitmproxy

Issue:
Unpacking request body (gzip) doesn't automatically update the Content-Length header
##### Steps to reproduce the problem:

1. Send a request with the body packed as gzip.
2. Enter into the request in mitmproxy and notice Content-Length shows the packed length.
3. Unpack the body (the z key) - notice the Content-Length header doesn't change, although the unpacked content length must be known at this point. Replying the request fails in my case as the server complains about the stream having more data than expected (the un-gzipped data has more bytes than gzipped).

When the users goes into raw body edit mode ('e', than 'r') and just quits the editor, the Content-Length header is updated correctly.

##### System information

Mitmproxy version: 2.0.2 (release version)
Python version: 3.6.1
Platform: Darwin-14.5.0-x86_64-i386-64bit
SSL version: OpenSSL 1.1.0e  16 Feb 2017
Mac version: 10.10.5 ('', '', '') x86_64

The same behavior observed on an up-to-date Arch linux.


Discussion:

Resolving patch:
diff --git a/mitmproxy/net/http/message.py b/mitmproxy/net/http/message.py
--- a/mitmproxy/net/http/message.py
+++ b/mitmproxy/net/http/message.py
@@ -226,8 +226,9 @@ def decode(self, strict=True):
         Raises:
             ValueError, when the content-encoding is invalid and strict is True.
         """
-        self.raw_content = self.get_content(strict)
+        decoded = self.get_content(strict)
         self.headers.pop("content-encoding", None)
+        self.content = decoded
 
     def encode(self, e):
         """


Test patch:
diff --git a/test/mitmproxy/addons/test_export.py b/test/mitmproxy/addons/test_export.py
--- a/test/mitmproxy/addons/test_export.py
+++ b/test/mitmproxy/addons/test_export.py
@@ -45,11 +45,11 @@ def tcp_flow():
 
 class TestExportCurlCommand:
     def test_get(self, get_request):
-        result = """curl -H 'header:qvalue' -H 'content-length:7' 'http://address:22/path?a=foo&a=bar&b=baz'"""
+        result = """curl -H 'header:qvalue' -H 'content-length:0' 'http://address:22/path?a=foo&a=bar&b=baz'"""
         assert export.curl_command(get_request) == result
 
     def test_post(self, post_request):
-        result = "curl -X POST 'http://address:22/path' --data-binary '{}'".format(
+        result = "curl -H 'content-length:256' -X POST 'http://address:22/path' --data-binary '{}'".format(
             str(bytes(range(256)))[2:-1]
         )
         assert export.curl_command(post_request) == result
diff --git a/test/mitmproxy/net/http/test_message.py b/test/mitmproxy/net/http/test_message.py
--- a/test/mitmproxy/net/http/test_message.py
+++ b/test/mitmproxy/net/http/test_message.py
@@ -117,6 +117,14 @@ def test_simple(self):
         assert r.content == b"message"
         assert r.raw_content != b"message"
 
+    def test_update_content_length_header(self):
+        r = tutils.tresp()
+        assert int(r.headers["content-length"]) == 7
+        r.encode("gzip")
+        assert int(r.headers["content-length"]) == 27
+        r.decode()
+        assert int(r.headers["content-length"]) == 7
+
     def test_modify(self):
         r = tutils.tresp()
         assert "content-encoding" not in r.headers