diff --git a/CHANGES/10156.feature.rst b/CHANGES/10156.feature.rst new file mode 100644 index 00000000000..0ff6b6b8bd8 --- /dev/null +++ b/CHANGES/10156.feature.rst @@ -0,0 +1,3 @@ +Enabled ALPN on default SSL contexts. This improves compatibility with some +proxies which don't work without this extension. +-- by :user:`Cycloctane`. diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 94d003a1719..035436c0426 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -366,6 +366,7 @@ William S. Wilson Ong wouter bolsterlee Xavier Halloran +Xi Rui Xiang Li Yang Zhou Yannick Koechlin diff --git a/aiohttp/connector.py b/aiohttp/connector.py index a9123f82bc0..7e0986df657 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -780,14 +780,16 @@ def _make_ssl_context(verified: bool) -> SSLContext: # No ssl support return None if verified: - return ssl.create_default_context() - sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - sslcontext.options |= ssl.OP_NO_SSLv2 - sslcontext.options |= ssl.OP_NO_SSLv3 - sslcontext.check_hostname = False - sslcontext.verify_mode = ssl.CERT_NONE - sslcontext.options |= ssl.OP_NO_COMPRESSION - sslcontext.set_default_verify_paths() + sslcontext = ssl.create_default_context() + else: + sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + sslcontext.options |= ssl.OP_NO_SSLv2 + sslcontext.options |= ssl.OP_NO_SSLv3 + sslcontext.check_hostname = False + sslcontext.verify_mode = ssl.CERT_NONE + sslcontext.options |= ssl.OP_NO_COMPRESSION + sslcontext.set_default_verify_paths() + sslcontext.set_alpn_protocols(("http/1.1",)) return sslcontext diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index b34ccdb600d..05af9ae25ad 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -603,6 +603,30 @@ async def handler(request): assert txt == "Test message" +async def test_ssl_client_alpn( + aiohttp_server: AiohttpServer, + aiohttp_client: AiohttpClient, + ssl_ctx: ssl.SSLContext, +) -> None: + + async def handler(request: web.Request) -> web.Response: + assert request.transport is not None + sslobj = request.transport.get_extra_info("ssl_object") + return web.Response(text=sslobj.selected_alpn_protocol()) + + app = web.Application() + app.router.add_route("GET", "/", handler) + ssl_ctx.set_alpn_protocols(("http/1.1",)) + server = await aiohttp_server(app, ssl=ssl_ctx) + + connector = aiohttp.TCPConnector(ssl=False) + client = await aiohttp_client(server, connector=connector) + resp = await client.get("/") + assert resp.status == 200 + txt = await resp.text() + assert txt == "http/1.1" + + async def test_tcp_connector_fingerprint_ok( aiohttp_server, aiohttp_client,