@@ -859,12 +859,45 @@ def _build_keepalive_socket_options() -> list[tuple[int, int, int | bool]]:
859859 return opts
860860
861861
862+ # ``socket_options`` was added to httpx's transports in httpx 0.25.0. This SDK
863+ # still supports ``httpx>=0.23.0``, so detect support at runtime rather than
864+ # raising the dependency floor (which would be a breaking change for users).
865+ _HTTPX_TRANSPORT_SUPPORTS_SOCKET_OPTIONS = (
866+ "socket_options" in inspect .signature (httpx .HTTPTransport .__init__ ).parameters
867+ )
868+
869+ # ``httpx.Client``/``httpx.AsyncClient`` normally apply these options when they
870+ # build their own default transport. Supplying a pre-built transport bypasses
871+ # that step, so the effective values must be forwarded to avoid silently
872+ # dropping ``DEFAULT_CONNECTION_LIMITS`` and customizations like ``http2=True``.
873+ _TRANSPORT_PASSTHROUGH_KEYS = ("verify" , "cert" , "trust_env" , "http1" , "http2" , "limits" )
874+
875+
876+ def _build_keepalive_transport (
877+ transport_cls : type [httpx .HTTPTransport ] | type [httpx .AsyncHTTPTransport ],
878+ kwargs : dict [str , Any ],
879+ ) -> httpx .HTTPTransport | httpx .AsyncHTTPTransport :
880+ """Build a default transport with TCP keepalive enabled.
881+
882+ The relevant httpx client options are forwarded so that constructing the
883+ transport explicitly does not discard them, and ``socket_options`` is only
884+ passed when the installed httpx version supports it.
885+ """
886+ transport_kwargs : dict [str , Any ] = {
887+ key : kwargs [key ] for key in _TRANSPORT_PASSTHROUGH_KEYS if key in kwargs
888+ }
889+ if _HTTPX_TRANSPORT_SUPPORTS_SOCKET_OPTIONS :
890+ transport_kwargs ["socket_options" ] = _build_keepalive_socket_options ()
891+ return transport_cls (** transport_kwargs )
892+
893+
862894class _DefaultHttpxClient (httpx .Client ):
863895 def __init__ (self , ** kwargs : Any ) -> None :
864896 kwargs .setdefault ("timeout" , DEFAULT_TIMEOUT )
865897 kwargs .setdefault ("limits" , DEFAULT_CONNECTION_LIMITS )
866898 kwargs .setdefault ("follow_redirects" , True )
867- kwargs .setdefault ("transport" , httpx .HTTPTransport (socket_options = _build_keepalive_socket_options ()))
899+ if "transport" not in kwargs :
900+ kwargs ["transport" ] = _build_keepalive_transport (httpx .HTTPTransport , kwargs )
868901 super ().__init__ (** kwargs )
869902
870903
@@ -1452,7 +1485,8 @@ def __init__(self, **kwargs: Any) -> None:
14521485 kwargs .setdefault ("timeout" , DEFAULT_TIMEOUT )
14531486 kwargs .setdefault ("limits" , DEFAULT_CONNECTION_LIMITS )
14541487 kwargs .setdefault ("follow_redirects" , True )
1455- kwargs .setdefault ("transport" , httpx .AsyncHTTPTransport (socket_options = _build_keepalive_socket_options ()))
1488+ if "transport" not in kwargs :
1489+ kwargs ["transport" ] = _build_keepalive_transport (httpx .AsyncHTTPTransport , kwargs )
14561490 super ().__init__ (** kwargs )
14571491
14581492
0 commit comments