Skip to content

Commit

Permalink
Fix import of HTTP/1.1 connection causing thread-safety bug on 3.9 (#237
Browse files Browse the repository at this point in the history
)

* Fix import of HTTP/1.1 connection causing thread-safety bug on 3.9

* Typo
  • Loading branch information
florimondmanca authored Nov 20, 2020
1 parent 76f6e91 commit 0fce6d3
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
3 changes: 1 addition & 2 deletions httpcore/_async/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
NewConnectionRequired,
)
from .http import AsyncBaseHTTPConnection
from .http11 import AsyncHTTP11Connection

logger = get_logger(__name__)

Expand Down Expand Up @@ -150,8 +151,6 @@ def _create_connection(self, socket: AsyncSocketStream) -> None:
socket=socket, backend=self.backend, ssl_context=self.ssl_context
)
else:
from .http11 import AsyncHTTP11Connection

self.is_http11 = True
self.connection = AsyncHTTP11Connection(
socket=socket, ssl_context=self.ssl_context
Expand Down
3 changes: 1 addition & 2 deletions httpcore/_sync/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
NewConnectionRequired,
)
from .http import SyncBaseHTTPConnection
from .http11 import SyncHTTP11Connection

logger = get_logger(__name__)

Expand Down Expand Up @@ -150,8 +151,6 @@ def _create_connection(self, socket: SyncSocketStream) -> None:
socket=socket, backend=self.backend, ssl_context=self.ssl_context
)
else:
from .http11 import SyncHTTP11Connection

self.is_http11 = True
self.connection = SyncHTTP11Connection(
socket=socket, ssl_context=self.ssl_context
Expand Down
46 changes: 46 additions & 0 deletions tests/test_threadsafety.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import concurrent.futures

import pytest

import httpcore

from .utils import Server


def read_body(stream: httpcore.SyncByteStream) -> bytes:
try:
return b"".join(chunk for chunk in stream)
finally:
stream.close()


@pytest.mark.parametrize(
"http2", [pytest.param(False, id="h11"), pytest.param(True, id="h2")]
)
def test_threadsafe_basic(server: Server, http2: bool) -> None:
"""
The sync connection pool can be used to perform requests concurrently using
threads.
Also a regression test for: https://github.com/encode/httpx/issues/1393
"""
with httpcore.SyncConnectionPool(http2=http2) as http:

def request(http: httpcore.SyncHTTPTransport) -> int:
method = b"GET"
url = (b"http", *server.netloc, b"/")
headers = [server.host_header]
status_code, headers, stream, ext = http.request(method, url, headers)
read_body(stream)
return status_code

with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(request, http) for _ in range(10)]
num_results = 0

for future in concurrent.futures.as_completed(futures):
status_code = future.result()
assert status_code == 200
num_results += 1

assert num_results == 10

0 comments on commit 0fce6d3

Please sign in to comment.