Skip to content

Commit

Permalink
Forwarding HTTP proxies should use a fresh connection for every remot…
Browse files Browse the repository at this point in the history
…e host (#637)
  • Loading branch information
tomchristie authored Dec 12, 2022
1 parent 54f4485 commit b4fd42b
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 6 deletions.
5 changes: 4 additions & 1 deletion httpcore/_async/http_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def create_connection(self, origin: Origin) -> AsyncConnectionInterface:
return AsyncForwardHTTPConnection(
proxy_origin=self._proxy_url.origin,
proxy_headers=self._proxy_headers,
remote_origin=origin,
keepalive_expiry=self._keepalive_expiry,
network_backend=self._network_backend,
)
Expand All @@ -151,6 +152,7 @@ class AsyncForwardHTTPConnection(AsyncConnectionInterface):
def __init__(
self,
proxy_origin: Origin,
remote_origin: Origin,
proxy_headers: Union[HeadersAsMapping, HeadersAsSequence, None] = None,
keepalive_expiry: Optional[float] = None,
network_backend: Optional[AsyncNetworkBackend] = None,
Expand All @@ -162,6 +164,7 @@ def __init__(
)
self._proxy_origin = proxy_origin
self._proxy_headers = enforce_headers(proxy_headers, name="proxy_headers")
self._remote_origin = remote_origin

async def handle_async_request(self, request: Request) -> Response:
headers = merge_headers(self._proxy_headers, request.headers)
Expand All @@ -181,7 +184,7 @@ async def handle_async_request(self, request: Request) -> Response:
return await self._connection.handle_async_request(proxy_request)

def can_handle_request(self, origin: Origin) -> bool:
return origin.scheme == b"http"
return origin == self._remote_origin

async def aclose(self) -> None:
await self._connection.aclose()
Expand Down
5 changes: 4 additions & 1 deletion httpcore/_sync/http_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def create_connection(self, origin: Origin) -> ConnectionInterface:
return ForwardHTTPConnection(
proxy_origin=self._proxy_url.origin,
proxy_headers=self._proxy_headers,
remote_origin=origin,
keepalive_expiry=self._keepalive_expiry,
network_backend=self._network_backend,
)
Expand All @@ -151,6 +152,7 @@ class ForwardHTTPConnection(ConnectionInterface):
def __init__(
self,
proxy_origin: Origin,
remote_origin: Origin,
proxy_headers: Union[HeadersAsMapping, HeadersAsSequence, None] = None,
keepalive_expiry: Optional[float] = None,
network_backend: Optional[NetworkBackend] = None,
Expand All @@ -162,6 +164,7 @@ def __init__(
)
self._proxy_origin = proxy_origin
self._proxy_headers = enforce_headers(proxy_headers, name="proxy_headers")
self._remote_origin = remote_origin

def handle_request(self, request: Request) -> Response:
headers = merge_headers(self._proxy_headers, request.headers)
Expand All @@ -181,7 +184,7 @@ def handle_request(self, request: Request) -> Response:
return self._connection.handle_request(proxy_request)

def can_handle_request(self, origin: Origin) -> bool:
return origin.scheme == b"http"
return origin == self._remote_origin

def close(self) -> None:
self._connection.close()
Expand Down
4 changes: 2 additions & 2 deletions tests/_async/test_http_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ async def test_proxy_forwarding():
assert proxy.connections[0].is_available()
assert not proxy.connections[0].is_closed()

# A connection on a forwarding proxy can handle HTTP requests to any host.
# A connection on a forwarding proxy can only handle HTTP requests to the same origin.
assert proxy.connections[0].can_handle_request(
Origin(b"http", b"example.com", 80)
)
assert proxy.connections[0].can_handle_request(
assert not proxy.connections[0].can_handle_request(
Origin(b"http", b"other.com", 80)
)
assert not proxy.connections[0].can_handle_request(
Expand Down
4 changes: 2 additions & 2 deletions tests/_sync/test_http_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ def test_proxy_forwarding():
assert proxy.connections[0].is_available()
assert not proxy.connections[0].is_closed()

# A connection on a forwarding proxy can handle HTTP requests to any host.
# A connection on a forwarding proxy can only handle HTTP requests to the same origin.
assert proxy.connections[0].can_handle_request(
Origin(b"http", b"example.com", 80)
)
assert proxy.connections[0].can_handle_request(
assert not proxy.connections[0].can_handle_request(
Origin(b"http", b"other.com", 80)
)
assert not proxy.connections[0].can_handle_request(
Expand Down

0 comments on commit b4fd42b

Please sign in to comment.