From: Yeray Diaz Diaz Date: Tue, 13 Aug 2019 11:44:23 +0000 (+0100) Subject: Remove "Host" header on redirects if URL origin has changed (#199) X-Git-Tag: 0.7.0~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=95dad247b531489f4cf18ac6d8daacf9c4906d18;p=thirdparty%2Fhttpx.git Remove "Host" header on redirects if URL origin has changed (#199) Fixes #198 * Reinstate accidentally removed return statement --- diff --git a/httpx/__init__.py b/httpx/__init__.py index fd174412..39b44aae 100644 --- a/httpx/__init__.py +++ b/httpx/__init__.py @@ -32,10 +32,10 @@ from .exceptions import ( ) from .interfaces import ( AsyncDispatcher, - BaseReader, - BaseWriter, BaseBackgroundManager, BasePoolSemaphore, + BaseReader, + BaseWriter, ConcurrencyBackend, Dispatcher, Protocol, diff --git a/httpx/client.py b/httpx/client.py index e22d1a9f..6b49797e 100644 --- a/httpx/client.py +++ b/httpx/client.py @@ -20,11 +20,11 @@ from .dispatch.connection_pool import ConnectionPool from .dispatch.threaded import ThreadedDispatcher from .dispatch.wsgi import WSGIDispatch from .exceptions import ( + HTTPError, InvalidURL, RedirectBodyUnavailable, RedirectLoop, TooManyRedirects, - HTTPError, ) from .interfaces import AsyncDispatcher, ConcurrencyBackend, Dispatcher from .models import ( @@ -312,6 +312,7 @@ class BaseClient: headers = Headers(request.headers) if url.origin != request.url.origin: del headers["Authorization"] + del headers["host"] return headers def redirect_content( diff --git a/httpx/exceptions.py b/httpx/exceptions.py index 21dc7f4d..ddccbf8c 100644 --- a/httpx/exceptions.py +++ b/httpx/exceptions.py @@ -9,7 +9,9 @@ class HTTPError(Exception): Base class for Httpx exception """ - def __init__(self, request: 'BaseRequest' = None, response: 'BaseResponse' = None, *args) -> None: + def __init__( + self, request: "BaseRequest" = None, response: "BaseResponse" = None, *args + ) -> None: self.response = response self.request = request or getattr(self.response, "request", None) super().__init__(*args) diff --git a/httpx/models.py b/httpx/models.py index e7e7a57a..f397e780 100644 --- a/httpx/models.py +++ b/httpx/models.py @@ -33,7 +33,7 @@ from .utils import ( is_known_encoding, normalize_header_key, normalize_header_value, - str_query_param + str_query_param, ) PrimitiveData = typing.Union[str, int, float, bool, type(None)] diff --git a/tests/client/test_headers.py b/tests/client/test_headers.py index bf82a578..2d17c125 100755 --- a/tests/client/test_headers.py +++ b/tests/client/test_headers.py @@ -1,15 +1,16 @@ #!/usr/bin/env python3 import json + from httpx import ( - __version__, - Client, + AsyncDispatcher, AsyncRequest, AsyncResponse, - VerifyTypes, CertTypes, + Client, TimeoutTypes, - AsyncDispatcher, + VerifyTypes, + __version__, ) diff --git a/tests/client/test_redirects.py b/tests/client/test_redirects.py index ff754751..f9c20757 100644 --- a/tests/client/test_redirects.py +++ b/tests/client/test_redirects.py @@ -86,6 +86,17 @@ class MockDispatch(AsyncDispatcher): body = json.dumps({"body": content.decode()}).encode() return AsyncResponse(codes.OK, content=body, request=request) + elif request.url.path == "/cross_subdomain": + if request.headers["host"] != "www.example.org": + headers = {"location": "https://www.example.org/cross_subdomain"} + return AsyncResponse( + codes.PERMANENT_REDIRECT, headers=headers, request=request + ) + else: + return AsyncResponse( + codes.OK, content=b"Hello, world!", request=request + ) + return AsyncResponse(codes.OK, content=b"Hello, world!", request=request) @@ -250,3 +261,11 @@ async def test_cannot_redirect_streaming_body(): with pytest.raises(RedirectBodyUnavailable): await client.post(url, data=streaming_body()) + + +@pytest.mark.asyncio +async def test_cross_dubdomain_redirect(): + client = AsyncClient(dispatch=MockDispatch()) + url = "https://example.com/cross_subdomain" + response = await client.get(url) + assert response.url == URL("https://www.example.org/cross_subdomain")