perf: cache default HTTP opener at module level
Avoid rebuilding _ProxyHandler + build_opener() on every request. Default-context callers (16 of 18 plugins) reuse one cached opener; custom-context callers still get a fresh one. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,18 @@ _RETRY_ERRORS = (ssl.SSLError, ConnectionError, TimeoutError, OSError)
|
||||
|
||||
_log = logging.getLogger(__name__)
|
||||
|
||||
_default_opener: urllib.request.OpenerDirector | None = None
|
||||
|
||||
|
||||
def _get_opener(context=None):
|
||||
"""Return cached opener for default context, fresh for custom."""
|
||||
global _default_opener
|
||||
if context is not None:
|
||||
return urllib.request.build_opener(_ProxyHandler(context=context))
|
||||
if _default_opener is None:
|
||||
_default_opener = urllib.request.build_opener(_ProxyHandler())
|
||||
return _default_opener
|
||||
|
||||
|
||||
class _ProxyHandler(SocksiPyHandler, urllib.request.HTTPSHandler):
|
||||
"""SOCKS5 handler that forwards SSL context to HTTPS connections."""
|
||||
@@ -45,8 +57,7 @@ def urlopen(req, *, timeout=None, context=None):
|
||||
|
||||
Retries on transient SSL/connection errors with exponential backoff.
|
||||
"""
|
||||
handler = _ProxyHandler(context=context)
|
||||
opener = urllib.request.build_opener(handler)
|
||||
opener = _get_opener(context)
|
||||
kwargs = {}
|
||||
if timeout is not None:
|
||||
kwargs["timeout"] = timeout
|
||||
@@ -64,6 +75,8 @@ def urlopen(req, *, timeout=None, context=None):
|
||||
|
||||
def build_opener(*handlers, context=None):
|
||||
"""Proxy-aware drop-in for urllib.request.build_opener."""
|
||||
if not handlers and context is None:
|
||||
return _get_opener()
|
||||
proxy = _ProxyHandler(context=context)
|
||||
return urllib.request.build_opener(proxy, *handlers)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user