fix Host and :authority header not being updated on changes to host or port (#5908)

* fix map remote addon not setting `Host` header correctly

* fix failing tests

* fix coverage

* fix host and authority headers

* raise error when port is not of type int

* fix nits

* [autofix.ci] apply automated fixes

* coverage++

---------

Co-authored-by: Maximilian Hils <git@maximilianhils.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Sujal Singh 2023-02-06 22:05:16 +05:30 committed by GitHub
parent 54185c2c8d
commit b9f3574728
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 13 deletions

View File

@ -11,6 +11,9 @@
([#5851](https://github.com/mitmproxy/mitmproxy/pull/5851), @italankin)
* Removed string escaping in raw view.
([#5470](https://github.com/mitmproxy/mitmproxy/issues/5470), @stephenspol)
* Updating `Request.port` now also updates the Host header if present.
This aligns with `Request.host`, which already does this.
([#5908](https://github.com/mitmproxy/mitmproxy/pull/5908), @sujaldev)
### Breaking Changes

View File

@ -749,13 +749,7 @@ class Request(Message):
@host.setter
def host(self, val: Union[str, bytes]) -> None:
self.data.host = always_str(val, "idna", "strict")
# Update host header
if "Host" in self.data.headers:
self.data.headers["Host"] = val
# Update authority
if self.data.authority:
self.authority = url.hostport(self.scheme, self.host, self.port)
self._update_host_and_authority()
@property
def host_header(self) -> Optional[str]:
@ -794,7 +788,21 @@ class Request(Message):
@port.setter
def port(self, port: int) -> None:
if not isinstance(port, int):
raise ValueError(f"Port must be an integer, not {port!r}.")
self.data.port = port
self._update_host_and_authority()
def _update_host_and_authority(self) -> None:
val = url.hostport(self.scheme, self.host, self.port)
# Update host header
if "Host" in self.data.headers:
self.data.headers["Host"] = val
# Update authority
if self.data.authority:
self.authority = val
@property
def path(self) -> str:

View File

@ -27,6 +27,16 @@ class TestMapRemote:
mr.request(f)
assert f.request.url == "https://mitmproxy.org/img/test.jpg"
def test_host_header(self):
mr = mapremote.MapRemote()
with taddons.context(mr) as tctx:
tctx.configure(mr, map_remote=["|http://[^/]+|http://example.com:4444"])
f = tflow.tflow()
f.request.url = b"http://example.org/example"
f.request.headers["Host"] = "example.org"
mr.request(f)
assert f.request.headers.get("Host", "") == "example.com:4444"
def test_is_killed(self):
mr = mapremote.MapRemote()
with taddons.context(mr) as tctx:

View File

@ -2,6 +2,7 @@ import asyncio
import email
import json
import time
from typing import Any
from unittest import mock
import pytest
@ -10,6 +11,7 @@ from mitmproxy import flow
from mitmproxy import flowfilter
from mitmproxy.http import Headers
from mitmproxy.http import HTTPFlow
from mitmproxy.http import Message
from mitmproxy.http import Request
from mitmproxy.http import Response
from mitmproxy.net.http.cookies import CookieAttrs
@ -158,7 +160,9 @@ class TestRequestCore:
_test_decoded_attr(treq(), "scheme")
def test_port(self):
_test_passthrough_attr(treq(), "port")
_test_passthrough_attr(treq(), "port", 1234)
with pytest.raises(ValueError):
treq().port = "foo"
def test_path(self):
_test_decoded_attr(treq(), "path")
@ -199,8 +203,7 @@ class TestRequestCore:
request.headers["Host"] = "foo"
request.authority = "foo"
request.host = "example.org"
assert request.headers["Host"] == "example.org"
assert request.authority == "example.org:22"
assert request.headers["Host"] == request.authority == "example.org:22"
def test_get_host_header(self):
no_hdr = treq()
@ -864,10 +867,10 @@ class TestHeaders:
]
def _test_passthrough_attr(message, attr):
def _test_passthrough_attr(message: Message, attr: str, value: Any = b"foo") -> None:
assert getattr(message, attr) == getattr(message.data, attr)
setattr(message, attr, b"foo")
assert getattr(message.data, attr) == b"foo"
setattr(message, attr, value)
assert getattr(message.data, attr) == value
def _test_decoded_attr(message, attr):