Handle redirect with malformed Location headers missing host. (#774)
This commit is contained in:
parent
5a63540e8a
commit
1f8fb28d93
@ -330,6 +330,11 @@ class BaseClient:
|
||||
|
||||
url = URL(location, allow_relative=True)
|
||||
|
||||
# Handle malformed 'Location' headers that are "absolute" form, have no host.
|
||||
# See: https://github.com/encode/httpx/issues/771
|
||||
if url.scheme and not url.host:
|
||||
url = url.copy_with(host=request.url.host)
|
||||
|
||||
# Facilitate relative 'Location' headers, as allowed by RFC 7231.
|
||||
# (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')
|
||||
if url.is_relative_url:
|
||||
|
||||
@ -201,7 +201,7 @@ class URL:
|
||||
or "port" in kwargs
|
||||
):
|
||||
host = kwargs.pop("host", self.host)
|
||||
port = kwargs.pop("port", self.port)
|
||||
port = kwargs.pop("port", None if self.is_relative_url else self.port)
|
||||
username = kwargs.pop("username", self.username)
|
||||
password = kwargs.pop("password", self.password)
|
||||
|
||||
@ -216,7 +216,10 @@ class URL:
|
||||
|
||||
kwargs["authority"] = authority
|
||||
|
||||
return URL(self._uri_reference.copy_with(**kwargs).unsplit())
|
||||
return URL(
|
||||
self._uri_reference.copy_with(**kwargs).unsplit(),
|
||||
allow_relative=self.is_relative_url,
|
||||
)
|
||||
|
||||
def join(self, relative_url: URLTypes) -> "URL":
|
||||
"""
|
||||
|
||||
@ -56,6 +56,10 @@ class MockDispatch(AsyncDispatcher):
|
||||
headers = {"location": "/"}
|
||||
return Response(codes.SEE_OTHER, headers=headers, request=request)
|
||||
|
||||
elif request.url.path == "/malformed_redirect":
|
||||
headers = {"location": "https://:443/"}
|
||||
return Response(codes.SEE_OTHER, headers=headers, request=request)
|
||||
|
||||
elif request.url.path == "/no_scheme_redirect":
|
||||
headers = {"location": "//example.org/"}
|
||||
return Response(codes.SEE_OTHER, headers=headers, request=request)
|
||||
@ -176,6 +180,16 @@ async def test_relative_redirect():
|
||||
assert len(response.history) == 1
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_malformed_redirect():
|
||||
# https://github.com/encode/httpx/issues/771
|
||||
client = AsyncClient(dispatch=MockDispatch())
|
||||
response = await client.get("http://example.org/malformed_redirect")
|
||||
assert response.status_code == codes.OK
|
||||
assert response.url == URL("https://example.org/")
|
||||
assert len(response.history) == 1
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_no_scheme_redirect():
|
||||
client = AsyncClient(dispatch=MockDispatch())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user