From ba7bd3a1e70c3f7303edb7f057efabdd6c589063 Mon Sep 17 00:00:00 2001 From: Walt Della Date: Thu, 4 Sep 2025 14:30:11 -0700 Subject: [PATCH 1/2] Reuse ssl context in the sync client This brings ssl context handling in line with the async client. Importantly, openssl has a pretty signifigant performance regression in creating ssl contexts v3.0+ that is mitigated by paying the context creation tax once, instead of for every request. Based on my testing, this reduces the openssl v3 performance penalty from ~200ms per connection to 9ms per connection. --- .../python/template/src/sync/rest.py.mustache | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/config/clients/python/template/src/sync/rest.py.mustache b/config/clients/python/template/src/sync/rest.py.mustache index 9317fe33b..3489e812d 100644 --- a/config/clients/python/template/src/sync/rest.py.mustache +++ b/config/clients/python/template/src/sync/rest.py.mustache @@ -143,10 +143,19 @@ class RESTClientObject: :param pools_size: The number of connection pools to use. :param maxsize: The maximum number of connections per pool. """ - if hasattr(configuration, "verify_ssl") and configuration.verify_ssl: - cert_reqs = ssl.CERT_REQUIRED - else: - cert_reqs = ssl.CERT_NONE + + # Reuse SSL context to mitigate OpenSSL 3.0+ performance issues + # See: https://github.com/openssl/openssl/issues/17064 + ssl_context = ssl.create_default_context(cafile=configuration.ssl_ca_cert) + + if configuration.cert_file: + ssl_context.load_cert_chain( + configuration.cert_file, keyfile=configuration.key_file + ) + + if not configuration.verify_ssl: + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE addition_pool_args = {} @@ -181,10 +190,10 @@ class RESTClientObject: urllib3.ProxyManager( num_pools=pools_size, maxsize=maxsize, - cert_reqs=cert_reqs, ca_certs=configuration.ssl_ca_cert, cert_file=configuration.cert_file, key_file=configuration.key_file, + ssl_context=ssl_context, proxy_url=configuration.proxy, proxy_headers=configuration.proxy_headers, **addition_pool_args, @@ -196,10 +205,10 @@ class RESTClientObject: self.pool_manager = urllib3.PoolManager( num_pools=pools_size, maxsize=maxsize, - cert_reqs=cert_reqs, ca_certs=configuration.ssl_ca_cert, cert_file=configuration.cert_file, key_file=configuration.key_file, + ssl_context=ssl_context, **addition_pool_args, ) From 4598242a931d10ffb2dd9abccad784bb71dba4ee Mon Sep 17 00:00:00 2001 From: Walt Della Date: Mon, 8 Sep 2025 14:37:11 -0700 Subject: [PATCH 2/2] Remove ca_certs, cert_file, and key_file params When ssl_context is provided, urllib3 uses it and ignores per-arg TLS settings. Passing both is redundant. --- config/clients/python/template/src/sync/rest.py.mustache | 6 ------ 1 file changed, 6 deletions(-) diff --git a/config/clients/python/template/src/sync/rest.py.mustache b/config/clients/python/template/src/sync/rest.py.mustache index 3489e812d..0220b251d 100644 --- a/config/clients/python/template/src/sync/rest.py.mustache +++ b/config/clients/python/template/src/sync/rest.py.mustache @@ -190,9 +190,6 @@ class RESTClientObject: urllib3.ProxyManager( num_pools=pools_size, maxsize=maxsize, - ca_certs=configuration.ssl_ca_cert, - cert_file=configuration.cert_file, - key_file=configuration.key_file, ssl_context=ssl_context, proxy_url=configuration.proxy, proxy_headers=configuration.proxy_headers, @@ -205,9 +202,6 @@ class RESTClientObject: self.pool_manager = urllib3.PoolManager( num_pools=pools_size, maxsize=maxsize, - ca_certs=configuration.ssl_ca_cert, - cert_file=configuration.cert_file, - key_file=configuration.key_file, ssl_context=ssl_context, **addition_pool_args, )