-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed the problem with socket, which might leak when tunnel proxy connection couldn't be establish #223
Fixed the problem with socket, which might leak when tunnel proxy connection couldn't be establish #223
Changes from 2 commits
546325a
10df7fa
c69e392
dfe46ac
74d87b0
0a6bd9c
43ac004
5413954
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -191,6 +191,36 @@ async def test_http_proxy( | |
assert ext == {"http_version": "HTTP/1.1", "reason": "OK"} | ||
|
||
|
||
@pytest.mark.parametrize("proxy_mode", ["DEFAULT", "FORWARD_ONLY", "TUNNEL_ONLY"]) | ||
@pytest.mark.parametrize("protocol,port", [(b"http", 80), (b"https", 443)]) | ||
@pytest.mark.trio | ||
async def test_proxy_socket_does_not_leak_when_the_connection_hasnt_been_added_to_pool( | ||
proxy_server: URL, | ||
server: Server, | ||
proxy_mode: str, | ||
protocol: bytes, | ||
port: int, | ||
): | ||
method = b"GET" | ||
url = (protocol, b"example.com", port, b"/") | ||
headers = [(b"host", b"example.org")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the host mismatch between url / headers expected? I think this is somewhat related to the block file passed to
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right! I missed that the url and header are different, and it might confuse. Moreover the server name is not so clear. I'm renaming this host to "blockedhost.example.com" (and changing the fixture the same way) |
||
|
||
with pytest.warns(None) as recorded_warnings: | ||
async with httpcore.AsyncHTTPProxy(proxy_server, proxy_mode=proxy_mode) as http: | ||
for _ in range(100): | ||
try: | ||
_ = await http.arequest(method, url, headers) | ||
except httpcore.RemoteProtocolError: | ||
pass | ||
|
||
# have to filter out https://github.com/encode/httpx/issues/825 from other tests | ||
warnings_list = [ | ||
*filter(lambda warn: "asyncio" not in warn.filename, recorded_warnings.list) | ||
] | ||
|
||
assert len(warnings_list) == 0 | ||
cdeler marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
@pytest.mark.anyio | ||
async def test_http_request_local_address(backend: str, server: Server) -> None: | ||
if backend == "auto" and lookup_async_backend() == "trio": | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
import contextlib | ||
import socket | ||
import subprocess | ||
import tempfile | ||
import time | ||
from typing import Tuple | ||
from typing import List, Tuple | ||
|
||
import sniffio | ||
|
||
|
@@ -48,13 +49,34 @@ def host_header(self) -> Tuple[bytes, bytes]: | |
def http_proxy_server(proxy_host: str, proxy_port: int): | ||
|
||
proc = None | ||
try: | ||
command = ["pproxy", "-l", f"http://{proxy_host}:{proxy_port}/"] | ||
proc = subprocess.Popen(command) | ||
|
||
_wait_can_connect(proxy_host, proxy_port) | ||
with create_proxy_block_file(["example.com"]) as block_file_name: | ||
try: | ||
command = [ | ||
"pproxy", | ||
"-b", | ||
block_file_name, | ||
"-l", | ||
f"http://{proxy_host}:{proxy_port}/", | ||
] | ||
proc = subprocess.Popen(command) | ||
|
||
_wait_can_connect(proxy_host, proxy_port) | ||
|
||
yield b"http", proxy_host.encode(), proxy_port, b"/" | ||
finally: | ||
if proc is not None: | ||
proc.kill() | ||
|
||
|
||
@contextlib.contextmanager | ||
def create_proxy_block_file(blocked_domains: List[str]): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest we add a small docstring here with any relevant docs material from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added some docs to |
||
with tempfile.NamedTemporaryFile(delete=True, mode="w+") as file: | ||
|
||
for domain in blocked_domains: | ||
file.write(domain) | ||
file.write("\n") | ||
|
||
file.flush() | ||
|
||
yield b"http", proxy_host.encode(), proxy_port, b"/" | ||
finally: | ||
if proc is not None: | ||
proc.kill() | ||
yield file.name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to explicitly put this operation outside the
try
/except
block? I assume the only operations that we want to fail upon is socket-related stuff, soproxy_connection.arequest()
andproxy_connection.start_tls()
. Anything that's not related to it, such as adding to the pool, should be left outside the block, correct?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right, the
try
-except
block should be as narrow as possible