From 02d2b6d310d8497b9da1e630ac704a695e5b3b28 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Wed, 6 Apr 2022 12:51:58 +0200 Subject: [PATCH] warn users if sse flows are received without streaming, refs #4469 (#5249) --- CHANGELOG.md | 2 ++ docs/src/content/overview-features.md | 3 ++- mitmproxy/addons/server_side_events.py | 19 +++++++++++++++++++ .../addons/test_server_side_events.py | 12 ++++++++++++ test/mitmproxy/tools/console/test_common.py | 1 + 5 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 mitmproxy/addons/server_side_events.py create mode 100644 test/mitmproxy/addons/test_server_side_events.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a5add7bb..6307983a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ([#5227](https://github.com/mitmproxy/mitmproxy/issues/5227), @mhils) * Console Performance Improvements ([#3427](https://github.com/mitmproxy/mitmproxy/issues/3427), @BkPHcgQL3V) +* Warn users if server side event responses are received without streaming. + ([#4469](https://github.com/mitmproxy/mitmproxy/issues/4469), @mhils) * Add flatpak support to the browser addon ([#5200](https://github.com/mitmproxy/mitmproxy/issues/5200), @pauloromeira) * Add example addon to dump contents to files based on a filter expression diff --git a/docs/src/content/overview-features.md b/docs/src/content/overview-features.md index 725234f95..f635436a2 100644 --- a/docs/src/content/overview-features.md +++ b/docs/src/content/overview-features.md @@ -358,7 +358,8 @@ By default, mitmproxy will read an entire request/response, perform any indicated manipulations on it, and then send the message on to the other party. This can be problematic when downloading or uploading large files. When streaming is enabled, message bodies are not buffered on the proxy but instead -sent directly to the server/client. HTTP headers are still fully buffered before +sent directly to the server/client. This currently means that the message body +will not be accessible within mitmproxy. HTTP headers are still fully buffered before being sent. Request/response streaming is enabled by specifying a size cutoff in the diff --git a/mitmproxy/addons/server_side_events.py b/mitmproxy/addons/server_side_events.py new file mode 100644 index 000000000..43084f1bf --- /dev/null +++ b/mitmproxy/addons/server_side_events.py @@ -0,0 +1,19 @@ +from mitmproxy import ctx, http + + +class ServerSideEvents: + """ + Server-Side Events are currently swallowed if there's no streaming, + see https://github.com/mitmproxy/mitmproxy/issues/4469. + + Until this bug is fixed, this addon warns the user about this. + """ + + def response(self, flow: http.HTTPFlow): + assert flow.response + is_sse = flow.response.headers.get("content-type", "").startswith("text/event-stream") + if is_sse and not flow.response.stream: + ctx.log.warn( + "mitmproxy currently does not support server side events. As a workaround, you can enable response " + "streaming for such flows: https://github.com/mitmproxy/mitmproxy/issues/4469" + ) diff --git a/test/mitmproxy/addons/test_server_side_events.py b/test/mitmproxy/addons/test_server_side_events.py new file mode 100644 index 000000000..f152dc62b --- /dev/null +++ b/test/mitmproxy/addons/test_server_side_events.py @@ -0,0 +1,12 @@ +from mitmproxy.addons.server_side_events import ServerSideEvents +from mitmproxy.test import taddons +from mitmproxy.test.tflow import tflow + + +async def test_simple(): + s = ServerSideEvents() + with taddons.context() as tctx: + f = tflow(resp=True) + f.response.headers["content-type"] = "text/event-stream" + s.response(f) + await tctx.master.await_log("mitmproxy currently does not support server side events.") diff --git a/test/mitmproxy/tools/console/test_common.py b/test/mitmproxy/tools/console/test_common.py index 181a368ac..e684c43f0 100644 --- a/test/mitmproxy/tools/console/test_common.py +++ b/test/mitmproxy/tools/console/test_common.py @@ -39,6 +39,7 @@ def test_format_keyvals(): def test_truncated_text(): + urwid.set_encoding("utf8") half_width_text = common.TruncatedText("Half-width", []) full_width_text = common.TruncatedText("FULL-WIDTH", []) assert half_width_text.render((10,))