diff --git a/CLAUDE.md b/CLAUDE.md index cfc825b..a3a2278 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,7 @@ High-performance Python HTTP client, API-compatible with httpx, powered by Rust' ## Features - **httpx API compatibility** — Drop-in replacement: `import requestx as httpx` works -- **AI SDK compatible** — Works with OpenAI, Anthropic SDKs via `http_client=requestx.Client()` +- **AI SDK compatible** — Works with OpenAI, Anthropic SDKs via `http_client=requestx.Client()` or `AsyncClient` - **High performance** — Rust-powered with GIL-free I/O, SIMD JSON (sonic-rs), zero-copy bytes - **Full async support** — Tokio runtime for true concurrent multiplexing - **Standards compliant** — WHATWG URL, RFC 2388 (multipart), RFC 7616 (digest auth), HTTP/2 @@ -189,9 +189,9 @@ let mut headers = Vec::with_capacity(response.headers().len()); ``` ### 7. SDK Compatibility -- requestx patches `type.__instancecheck__` at import to pass httpx.Client isinstance checks +- requestx patches `builtins.isinstance` at import to pass httpx.Client isinstance checks - This enables AI SDK compatibility (OpenAI, Anthropic accept requestx.Client) -- Patch is global but detection is narrow (class + module name matching) +- Patch is global but detection is narrow (checks `__name__` == "Client"/"AsyncClient" and `__module__` starts with "requestx") ## Don't diff --git a/python/requestx/_client.py b/python/requestx/_client.py index 3c39038..526ddbd 100644 --- a/python/requestx/_client.py +++ b/python/requestx/_client.py @@ -352,7 +352,15 @@ def build_request(self, method, url, **kwargs): else: kwargs["params"] = self._params - rust_request = self._client.build_request(method, merged_url, **kwargs) + # Filter to only parameters supported by Rust build_request + # Rust signature: (method, url, *, content=None, data=None, files=None, json=None, params=None, headers=None, cookies=None) + # Note: timeout and extensions are httpx API parameters but not supported by Rust + supported_kwargs = {} + for key in ["content", "data", "files", "json", "params", "headers", "cookies"]: + if key in kwargs and kwargs[key] is not None: + supported_kwargs[key] = kwargs[key] + + rust_request = self._client.build_request(method, merged_url, **supported_kwargs) # Create a wrapper that delegates to the Rust request but has our headers proxy wrapped = _WrappedRequest(rust_request, sync_stream=sync_stream) # Link the stream back to the owner for consumption tracking