diff --git a/mitmproxy/addons/dumper.py b/mitmproxy/addons/dumper.py index 3832e5ef5..b04506597 100644 --- a/mitmproxy/addons/dumper.py +++ b/mitmproxy/addons/dumper.py @@ -12,6 +12,7 @@ from mitmproxy import exceptions from mitmproxy import flowfilter from mitmproxy.utils import human from mitmproxy.utils import strutils +from mitmproxy.net import http def indent(n: int, text: str) -> str: @@ -225,6 +226,8 @@ class Dumper: self._echo_response_line(f) if ctx.options.flow_detail >= 2: self._echo_headers(f.response.headers) + if f.response.trailers is not None and isinstance(f.response.trailers, http.Headers): + self._echo_headers(f.response.trailers) if ctx.options.flow_detail >= 3: self._echo_message(f.response, f) diff --git a/mitmproxy/contentviews/__init__.py b/mitmproxy/contentviews/__init__.py index 49c41f2ff..7778c8165 100644 --- a/mitmproxy/contentviews/__init__.py +++ b/mitmproxy/contentviews/__init__.py @@ -9,9 +9,10 @@ protobuf messages sent as WebSocket frames. Thus, the View API is very minimalistic. The only arguments are `data` and `**metadata`, where `data` is the actual content (as bytes). The contents on -metadata depend on the protocol in use. For HTTP, the message headers are -passed as the ``headers`` keyword argument. For HTTP requests, the query -parameters are passed as the ``query`` keyword argument. +metadata depend on the protocol in use. For HTTP, the message headers and +message trailers are passed as the ``headers`` and ``trailers`` keyword +argument. For HTTP requests, the query parameters are passed as the ``query`` +keyword argument. """ import traceback from typing import Dict, Optional # noqa @@ -103,6 +104,7 @@ def get_message_content_view(viewname, message, flow): metadata["query"] = message.query if isinstance(message, http.Message): metadata["headers"] = message.headers + metadata["trailers"] = message.trailers metadata["message"] = message metadata["flow"] = flow diff --git a/mitmproxy/test/tutils.py b/mitmproxy/test/tutils.py index 79751060e..5b2bfe353 100644 --- a/mitmproxy/test/tutils.py +++ b/mitmproxy/test/tutils.py @@ -46,7 +46,7 @@ def tresp(**kwargs) -> http.Response: reason=b"OK", headers=http.Headers(((b"header-response", b"svalue"), (b"content-length", b"7"))), content=b"message", - trailers=None, + trailers=http.Headers(((b"trailer-response", b"svalue"), (b"trailer", b"this trailer-1"))), timestamp_start=946681202, timestamp_end=946681203, ) diff --git a/test/mitmproxy/addons/test_dumper.py b/test/mitmproxy/addons/test_dumper.py index 7359229b3..d0d9d4e9b 100644 --- a/test/mitmproxy/addons/test_dumper.py +++ b/test/mitmproxy/addons/test_dumper.py @@ -124,6 +124,19 @@ def test_echo_body(): d._echo_message(f.response, f) t = sio.getvalue() assert "cut off" in t + sio.truncate(0) + + f = tflow.tflow(client_conn=True, server_conn=True, resp=True) + f.response.headers["content-type"] = "text/html" + f.response.content = b"foo bar voing\n" * 100 + f.response.trailers["trailer-2"] = "this is trailer 2" + d._echo_headers(f.response.headers) + d._echo_message(f.response, f) + d._echo_headers(f.response.trailers) + t = sio.getvalue() + assert "content-type" in t + assert "cut off" in t + assert "trailer-2" in t def test_echo_request_line():