From 87264d219a696093c7cecec0211db365940222fa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 18 Mar 2023 23:13:48 -1000 Subject: [PATCH] Fix ssl context being recreated frequently in httpx (#89932) * Fix ssl context being created every time in httpx * its expensive, only do it once --- homeassistant/helpers/aiohttp_client.py | 2 +- homeassistant/helpers/httpx_client.py | 3 ++- homeassistant/util/ssl.py | 9 +++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/homeassistant/helpers/aiohttp_client.py b/homeassistant/helpers/aiohttp_client.py index af8fa4d6f4d..53c3cc1cf22 100644 --- a/homeassistant/helpers/aiohttp_client.py +++ b/homeassistant/helpers/aiohttp_client.py @@ -271,7 +271,7 @@ def _async_get_connector( return cast(aiohttp.BaseConnector, hass.data[key]) if verify_ssl: - ssl_context: bool | SSLContext = ssl_util.client_context() + ssl_context: bool | SSLContext = ssl_util.get_default_context() else: ssl_context = False diff --git a/homeassistant/helpers/httpx_client.py b/homeassistant/helpers/httpx_client.py index 2475469a7d1..1e9d2e776c6 100644 --- a/homeassistant/helpers/httpx_client.py +++ b/homeassistant/helpers/httpx_client.py @@ -11,6 +11,7 @@ from typing_extensions import Self from homeassistant.const import APPLICATION_NAME, EVENT_HOMEASSISTANT_CLOSE, __version__ from homeassistant.core import Event, HomeAssistant, callback from homeassistant.loader import bind_hass +from homeassistant.util import ssl as ssl_util from .frame import warn_use @@ -65,7 +66,7 @@ def create_async_httpx_client( This method must be run in the event loop. """ client = HassHttpXAsyncClient( - verify=verify_ssl, + verify=ssl_util.get_default_context() if verify_ssl else False, headers={USER_AGENT: SERVER_SOFTWARE}, **kwargs, ) diff --git a/homeassistant/util/ssl.py b/homeassistant/util/ssl.py index 71c88ad8446..9c945ef2759 100644 --- a/homeassistant/util/ssl.py +++ b/homeassistant/util/ssl.py @@ -16,6 +16,15 @@ def client_context() -> ssl.SSLContext: return ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=cafile) +# Create this only once and reuse it +_DEFAULT_SSL_CONTEXT = client_context() + + +def get_default_context() -> ssl.SSLContext: + """Return the default SSL context.""" + return _DEFAULT_SSL_CONTEXT + + def server_context_modern() -> ssl.SSLContext: """Return an SSL context following the Mozilla recommendations.