Fix interaction of modifyheaders addon with stream_large_bodies option (#7286)

* Fix interaction of modifyheaders addon with stream_large_bodies option

`modifyheaders` addon uses `request` and `response` hooks which, when
`stream_large_bodies` is enabled, are called after headers have already
been sent and can no longer be modified.

This commit changes `modifyheaders` addon to use
`requestheaders` and `responseheaders` hooks.

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
lukant 2024-10-31 23:08:17 +01:00 committed by GitHub
parent 69f455b962
commit c10ff719f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 15 deletions

View File

@ -18,6 +18,10 @@
([#7241](https://github.com/mitmproxy/mitmproxy/pull/7241), @mhils)
- `browser.start` command now supports Firefox.
([#7239](https://github.com/mitmproxy/mitmproxy/pull/7239), @sujaldev)
- Fix interaction of the `modify_headers` and `stream_large_bodies` options.
This may break users of `modify_headers` that rely on filters referencing the message body.
We expect this to be uncommon, but please make yourself heard if that's not the case.
([#7286](https://github.com/mitmproxy/mitmproxy/pull/7286), @lukant)
## 02 October 2024: mitmproxy 11.0.0

View File

@ -81,12 +81,12 @@ class ModifyHeaders:
) from e
self.replacements.append(spec)
def request(self, flow):
def requestheaders(self, flow):
if flow.response or flow.error or not flow.live:
return
self.run(flow, flow.request.headers)
def response(self, flow):
def responseheaders(self, flow):
if flow.error or not flow.live:
return
self.run(flow, flow.response.headers)

View File

@ -41,48 +41,48 @@ class TestModifyHeaders:
tctx.configure(mh, modify_headers=["/~q/one/two", "/~s/one/three"])
f = tflow.tflow()
f.request.headers["one"] = "xxx"
mh.request(f)
mh.requestheaders(f)
assert f.request.headers["one"] == "two"
f = tflow.tflow(resp=True)
f.response.headers["one"] = "xxx"
mh.response(f)
mh.responseheaders(f)
assert f.response.headers["one"] == "three"
tctx.configure(mh, modify_headers=["/~s/one/two", "/~s/one/three"])
f = tflow.tflow(resp=True)
f.request.headers["one"] = "xxx"
f.response.headers["one"] = "xxx"
mh.response(f)
mh.responseheaders(f)
assert f.response.headers.get_all("one") == ["two", "three"]
tctx.configure(mh, modify_headers=["/~q/one/two", "/~q/one/three"])
f = tflow.tflow()
f.request.headers["one"] = "xxx"
mh.request(f)
mh.requestheaders(f)
assert f.request.headers.get_all("one") == ["two", "three"]
# test removal of existing headers
tctx.configure(mh, modify_headers=["/~q/one/", "/~s/one/"])
f = tflow.tflow()
f.request.headers["one"] = "xxx"
mh.request(f)
mh.requestheaders(f)
assert "one" not in f.request.headers
f = tflow.tflow(resp=True)
f.response.headers["one"] = "xxx"
mh.response(f)
mh.responseheaders(f)
assert "one" not in f.response.headers
tctx.configure(mh, modify_headers=["/one/"])
f = tflow.tflow()
f.request.headers["one"] = "xxx"
mh.request(f)
mh.requestheaders(f)
assert "one" not in f.request.headers
f = tflow.tflow(resp=True)
f.response.headers["one"] = "xxx"
mh.response(f)
mh.responseheaders(f)
assert "one" not in f.response.headers
# test modifying a header that is also part of the filter expression
@ -95,7 +95,7 @@ class TestModifyHeaders:
)
f = tflow.tflow()
f.request.headers["user-agent"] = "Hello, it's me, Mozilla"
mh.request(f)
mh.requestheaders(f)
assert "Definitely not Mozilla ;)" == f.request.headers["user-agent"]
@pytest.mark.parametrize("take", [True, False])
@ -106,13 +106,13 @@ class TestModifyHeaders:
f = tflow.tflow()
if take:
f.response = tresp()
mh.request(f)
mh.requestheaders(f)
assert (f.request.headers["content-length"] == "42") ^ take
f = tflow.tflow(resp=True)
if take:
f.kill()
mh.response(f)
mh.responseheaders(f)
assert (f.response.headers["content-length"] == "42") ^ take
@ -125,7 +125,7 @@ class TestModifyHeadersFile:
tctx.configure(mh, modify_headers=["/~q/one/@" + str(tmpfile)])
f = tflow.tflow()
f.request.headers["one"] = "xxx"
mh.request(f)
mh.requestheaders(f)
assert f.request.headers["one"] == "two"
async def test_nonexistent(self, tmpdir, caplog):
@ -142,5 +142,5 @@ class TestModifyHeadersFile:
tmpfile.remove()
f = tflow.tflow()
f.request.content = b"foo"
mh.request(f)
mh.requestheaders(f)
assert "Could not read" in caplog.text