From 5deec9dbd20ee19f2bc866674650f4955f8fb774 Mon Sep 17 00:00:00 2001 From: Nikhil Benesch Date: Tue, 4 Aug 2026 08:03:35 -0400 Subject: [PATCH] fix(client): thread all transport kwargs into the sync transport Supplying a custom transport makes httpx ignore every transport construction kwarg, not just limits, so options like verify and http2 were silently dropped by the default sync client. Reproduce httpx's own transport construction so they take effect again. --- src/turbopuffer/_base_client.py | 14 +++++++++++++- tests/test_client.py | 13 +++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/turbopuffer/_base_client.py b/src/turbopuffer/_base_client.py index 65e13a2a..c4efe382 100644 --- a/src/turbopuffer/_base_client.py +++ b/src/turbopuffer/_base_client.py @@ -830,7 +830,19 @@ def __init__(self, **kwargs: Any) -> None: kwargs.setdefault("timeout", DEFAULT_TIMEOUT) kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS) kwargs.setdefault("follow_redirects", True) - kwargs.setdefault("transport", HttpxTransport(limits=kwargs["limits"])) + # Mirrors httpx.Client._init_transport: + # https://github.com/encode/httpx/blob/0.28.1/httpx/_client.py#L718 + kwargs.setdefault( + "transport", + HttpxTransport( + verify=kwargs.get("verify", True), + cert=kwargs.get("cert"), + trust_env=kwargs.get("trust_env", True), + http1=kwargs.get("http1", True), + http2=kwargs.get("http2", False), + limits=kwargs["limits"], + ), + ) super().__init__(**kwargs) diff --git a/tests/test_client.py b/tests/test_client.py index 73e3c109..f6474b7c 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -4,6 +4,7 @@ import gc import os +import ssl import sys import json import asyncio @@ -1046,6 +1047,18 @@ def test_default_client_honors_custom_connection_limits(self) -> None: pool = DefaultHttpxClient(limits=limits)._transport._pool # type: ignore[attr-defined] assert (pool._max_connections, pool._max_keepalive_connections, pool._keepalive_expiry) == (7, 3, 1.0) # pyright: ignore[reportUnknownMemberType] + def test_default_client_honors_transport_kwargs(self) -> None: + # A custom transport causes httpx to ignore transport-construction + # kwargs (verify, cert, http1/http2, limits), so the default client + # must thread them into the transport itself. verify=False must reach + # the connection pool, otherwise TLS verification stays on despite the + # caller opting out. + pool = DefaultHttpxClient(verify=False)._transport._pool # type: ignore[attr-defined] + assert pool._ssl_context.verify_mode == ssl.CERT_NONE # pyright: ignore[reportUnknownMemberType] + + pool = DefaultHttpxClient()._transport._pool # type: ignore[attr-defined] + assert pool._ssl_context.verify_mode == ssl.CERT_REQUIRED # pyright: ignore[reportUnknownMemberType] + @pytest.mark.respx(base_url=base_url) def test_follow_redirects(self, respx_mock: MockRouter, client: Turbopuffer) -> None: # Test that the default follow_redirects=True allows following redirects