mitmweb: handle {en,de}coding on server-side (#4811)

* mitmweb: handle {en,de}coding on server-side

Handle this server-side rather than passing the message content encoding
details back when fetching flow content. If {en,de}coding fails, return
the raw request contents.

This addresses https://github.com/mitmproxy/mitmproxy/issues/4809

* fix typo

Co-authored-by: Maximilian Hils <github@maximilianhils.com>
This commit is contained in:
Matthew Hughes 2021-09-23 14:55:43 +01:00 committed by GitHub
parent c1003ee332
commit 7b4e219c4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 8 deletions

View File

@ -439,11 +439,6 @@ class FlowContent(RequestHandler):
def get(self, flow_id, message):
message = getattr(self.flow, message)
content_encoding = message.headers.get("Content-Encoding", None)
if content_encoding:
content_encoding = re.sub(r"[^\w]", "", content_encoding)
self.set_header("Content-Encoding", content_encoding)
original_cd = message.headers.get("Content-Disposition", None)
filename = None
if original_cd:
@ -459,7 +454,7 @@ class FlowContent(RequestHandler):
self.set_header("Content-Type", "application/text")
self.set_header("X-Content-Type-Options", "nosniff")
self.set_header("X-Frame-Options", "DENY")
self.write(message.raw_content)
self.write(message.get_content(strict=False))
class FlowContentView(RequestHandler):

View File

@ -1,5 +1,6 @@
import asyncio
import io
import gzip
import json
import logging
import textwrap
@ -290,12 +291,10 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
def test_flow_content(self):
f = self.view.get_by_id("42")
f.backup()
f.response.headers["Content-Encoding"] = "ran\x00dom"
f.response.headers["Content-Disposition"] = 'inline; filename="filename.jpg"'
r = self.fetch("/flows/42/response/content.data")
assert r.body == b"message"
assert r.headers["Content-Encoding"] == "random"
assert r.headers["Content-Disposition"] == 'attachment; filename="filename.jpg"'
del f.response.headers["Content-Disposition"]
@ -311,6 +310,21 @@ class TestApp(tornado.testing.AsyncHTTPTestCase):
f.revert()
def test_flow_content_returns_raw_content_when_decoding_fails(self):
f = self.view.get_by_id("42")
f.backup()
f.response.headers["Content-Encoding"] = "gzip"
# replace gzip magic number with garbage
invalid_encoded_content = gzip.compress(b"Hello world!").replace(b"\x1f\x8b", b"\xff\xff")
f.response.raw_content = invalid_encoded_content
r = self.fetch("/flows/42/response/content.data")
assert r.body == invalid_encoded_content
assert r.code == 200
f.revert()
def test_update_flow_content(self):
assert self.fetch(
"/flows/42/request/content.data",