The task is not complete. Preserve the full objective in
/home/jerlendds/.codex/attachments/38378646-771a-4417-997d-ab7ae50523d6/goal-objective.md
and all ten accompanying pasted files. All were read on the initial goal turn.
The requirement is to expose all wreq configuration through the existing Python
API and recreate every supplied example, including WebSockets, custom connector
middleware, runtime selection, certificates, emulation, and request overrides.
- Maturin builds
httpxp._native, a PyO3 extension using wreq 0.16.1 and wreq-util 0.2.0. Cargo requires Rust >=1.98, matching these dependencies. - Rust owns pooled clients and streamed response bodies, releases the GIL while doing network work, and translates network errors into httpxp exceptions.
- Default sync and async transports use the extension; async uses AnyIO workers and works under both asyncio and Trio. Custom transports remain Python APIs.
Client,AsyncClient, both HTTP transports, and module-level request helpers acceptprivacy_options. Request overrides useextensions={"private": {...}}.src/options.rsimplements many client and request options, every primitive public TLS/HTTP1/HTTP2 field, TLS key shares/compressors/extensions, HTTP/2 pseudo-header/settings/priority ordering, profile names, and custom emulation. Unknown keys fail explicitly. This is NOT yet full configuration coverage.- Python still handles its usual auth, redirects, cookies, encodings, multipart, request/response hooks, etc. Native redirects/decompression are disabled by default to preserve that behavior.
- Response streams retain a semaphore permit until closed/exhausted; Python pool timeout and max_connections are enforced separately from wreq's pool.
- Client connect timeout is forwarded. Per-request read/pool/write timeouts are
forwarded.
src/upload.rsstreams Python iterators in <=64KiB wire chunks, preserves original Python exceptions, and uses an upload progress watchdog. The write watchdog currently includes time spent waiting on the Python producer; audit its exact compatibility with socket-only write deadlines before completion. src/cancel.rssupplies a native cancellation signal for queued pool acquisition, waiting for response headers, and streamed response reads. Async worker calls can be abandoned; cancellation wakes Rust and releases the held permit.- Async uploads use an AnyIO BlockingPortal with explicit error capture (avoids wrapping user errors in ExceptionGroup) and close async generators. Early responses stop pending upload tasks via an atomic stop signal, turning an interrupted producer into clean EOF rather than a response-breaking body error. Known-empty bodies use a native empty body. Already-cached bytes/JSON/form bodies stay in Rust and finish their declared content length after an early response; they do not use a Python portal or get stopped early. Iterators remain streamed.
- Both transports implement nonnegative connection retries with exponential backoff. A local delayed-listener test proves retries do not consume the body before a connection succeeds.
- CLI header output uses request/response hooks rather than httpcore trace events. CLI verbose output describes sending a request without inventing connection events.
- Current populated test environment:
.venv(Python 3.12.11). The former/tmp/httpxp-rename-venvand old logs disappeared when the environment reset. System Python lacks the Python dependencies..venv/is ignored by git. - Native source: Cargo registry under
/home/jerlendds/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/. - Stable Rust here is 1.97.1. Initial compilation and wheel build succeeded using
--ignore-rust-version; installed nightly is 1.99.0. A normal nightly check was completed successfully withcargo +nightly check --lockedafter removal of the unused scaffold src/main.rs. - For local tests, the built
target/debug/lib_native.sowas copied tohttpxp/_native.abi3.so(ignored in git). Rebuild and replace it after Rust changes. Never overwrite a shared library while a Python process has it loaded. maturin build --interpreter python --profile dev --ignore-rust-versionbuilt an abi3 Python >=3.9 wheel. It predates the latest changes and must be rebuilt.- Initial full suite: 1372 passed, 49 failed, 1 skipped. Log:
/tmp/httpxp-suite.log. Most failures inspected obsolete httpcore internals; others were CLI output, pool limits, and write timeout. - After fixes: 104 focused tests passed, 2 write-timeout tests deselected.
Log:
/tmp/httpxp-targeted.log. - Initial dedicated native suite: 7 passed, including custom emulation at both scopes and local TLS/CA store/peer-certificate checks.
- Added
tests/test_wreq.pyexercises real local sync/async I/O, streamed downloads, form/JSON uploads, option rejection, module-level forwarding, custom emulation, local BoringSSL TLS and certificate stores. - Ruff, mypy, and git diff whitespace checks passed before the final added tests.
- Local sockets need sandbox escalation. Cargo fetch was approved and completed.
- The worktree had extensive existing httpx-to-httpxp rename changes on entry;
preserve those. User also formatted
src/*.rsduring this work.
- Inventory ALL builder/options/proxy/retry/redirect/WebSocket/cookie/DNS/TLS hooks in the pinned Rust sources; map each to actual implemented Python behavior. Include generic trait APIs (timer/executor, resolver, cookie store, session cache, Tower layer and connector_layer), not just scalar setters.
- Further audit streaming/cancellation edge cases: correct per-request connect timeout, socket-only write deadline semantics, client close while requests are active, synchronous producer cancellation limits, and early responses on a keep-alive connection with a known nonzero Content-Length. Initial streaming, write timeout, cancellation, source exception and early rejection tests pass.
- Implement native wreq retry policies (distinct from transport connection retries, which now work), custom proxy TLS config and multi-proxy rotation, encrypted client keys and the necessary SSLContext compatibility semantics.
- Complete client/request option coverage, including custom redirect policies with Python auth/history/cookie semantics, cookie providers, runtime selection, DNS callbacks, custom TLS session-cache providers, middleware, compression options, group, defaults, browser platform/header precedence, and request-local custom TLS/HTTP protocol options. Verify emulation actually controls on-wire headers and TLS/H2 settings, not only constructor acceptance.
- Finish WebSocket auth challenges/redirects, close-code/reason validation, client-owned socket cleanup, and header/emulation precedence. Sync/async upgrade/message APIs and HTTP/1+HTTP/2 example execution now pass local tests.
- Expose response trailers, original headers, peer chain, connection metadata, and other response/extension functionality needed by wreq examples.
- Replace obsolete httpcore-specific tests with meaningful native on-wire tests (especially actual HTTP/SOCKS/Unix proxies, TLS/H2 signatures, redirects, pooling/reuse, cancellation, retries). Do not count configuration inspection alone as proof of network behavior.
- Add runnable Python equivalents of ALL pasted examples and documentation for full option coverage, types, units, precedence, and build prerequisites. Update obsolete httpcore dependency/docs/extras/workflows/scripts as needed.
- Rebuild the final wheel/sdist, test isolated installation/import (without httpcore), normal supported-toolchain compilation, full suite, static checks, and all example/coverage gates. Audit every objective requirement against current authoritative evidence before calling the goal complete.
The preceding goal turn was progress (native backend implementation and tests). This turn added upload streaming, write deadlines, cancellation, async cleanup, connection retries, and empty-body handling. Nothing narrows the original scope.
- Streaming/cancellation/timeout/early-response suite: 33 passed before retry
and empty-body regressions were added. Log
/tmp/httpxp-streaming-final.log. - Full suite with retries: 1442 passed, 1 failed, 1 skipped in 25.87s;
/tmp/httpxp-full-streaming.log. Failure was an async OPTIONS empty-body race. - Fixed that race with native empty-body handling and added repeated GET/OPTIONS/
DELETE wire tests. The rerun log is
/tmp/httpxp-full-streaming-v2.log; inspect its terminal result before counting it as passing. - Current native binary was built normally with
cargo +nightly build --lib --lockedand copied into the source package after build completion. - Keep using Rust nightly here (>=1.98 required) to avoid rebuilding all dependencies back and forth between the system's old stable and nightly toolchains.
testappeared untracked before this continuation; it contains an OpenSSL TLS secrets-log banner. It was not created or removed by this turn.
-
Full rerun v2: 1444 passed, 1 failed, 1 skipped. Streaming POST exposed another cleanup race. Added upload stop flag and repeated early-response regression.
-
Focused v3: 90 passed, 2 failed; both failures involved cached bodies truncated at their declared Content-Length when a server replied early.
-
Fixed cached-body handling by keeping those bytes entirely in Rust. Final full rerun
/tmp/httpxp-full-streaming-v3.logcompleted: 1447 passed, 1 skipped in 27.54s. This includes streaming backpressure, source errors, write deadlines, cancellation at headers/body/pool/upload, early responses, retries, and repeated empty requests, under both asyncio and Trio. -
Ruff/mypy/Rust check passed before the final rebuild. No claim of full goal completion: WebSockets, trait hooks/runtime selection, complete option coverage, on-wire protocol validation, examples/docs, and final packaging remain required.
-
Final Rust
cargo +nightly check --locked, Ruff lint/format, mypy, andgit diff --checkall pass. No native test/build processes remain live.
- Added native split WebSocket send/receive with independent locks, cancellation,
connection permits, handshake metadata, subprotocols, and the wreq WebSocket
builder options. Exposed
WebSocket,AsyncWebSocket,WebSocketMessage, top-levelwebsocket, and client methods. Async sending and receiving can run concurrently. The HTTP version string for HTTP/2 is normalized toHTTP/2. - WebSocket auth currently applies only the initial auth request. Native upgrade errors occur before a failed handshake response can enter Python auth/redirect flows. Full challenge/redirect semantics and close validation remain required.
- Added structured native proxies at client/request scopes: scheme selection, basic/custom authorization, custom headers, exclusions, Unix sockets. Added ordered client proxy lists, native rule clearing, and nullable IPv4/IPv6 bind pairs. Ordered rules select the first match; they are not proxy rotation.
- Ordinary Python
Proxy.headersnow reaches native CONNECT requests. Tests confirm credentials/custom headers are absent from tunneled origin requests. - Added native TLS file/environment key logging and LRU session-cache capacity. A local TLS 1.2 server proves session resumption on a new connection and checks CLIENT_RANDOM output. This does not yet expose custom session-cache callbacks.
- Real network tests cover authenticated HTTP proxy requests, TLS CONNECT, request overrides, exclusions, ordered scheme rules, SOCKS5 auth, SOCKS5H remote DNS, and client/request Unix socket proxies. Updated the deprecated Click download test helper and the oversized WebSocket message expectation (native wreq maps it to ReadError).
- Removed the final test import of httpcore. Public transport exception exports are checked directly; real network exception tests remain in place.
- Added
examples/private_websocket.pyandexamples/private_proxy.py. Tests invoke their CLI entry points: ten echo messages in sync/async HTTP/1 and HTTP/2 modes, plus client/request proxy examples. Remaining pasted examples are still required, especially middleware/background connector runtime and Compio. - Added
docs/advanced/wreq.mdand navigation. The page explicitly documents this implemented subset and current WebSocket limitations. Examples/docs/work log are included in the sdist; a rebuilt archive was inspected for the expected Rust sources, lockfile, examples, docs, and absence of caches/native binaries. - Native build/check and Rust formatting pass. Ruff lint/format and mypy pass
for 68 source files. Full suite before additional proxy/example regressions:
1472 passed, 1 skipped in 41.09s. A test-server cleanup traceback seen in
that run was fixed. Focused final proxy+WebSocket+example suite: 35 passed
in 19.38s, no server traceback. Final full-suite log:
/tmp/httpxp-full-final.log: 1482 passed, 1 skipped in 46.87s, terminal exit 0 with no server cleanup traceback. - Packaging validation here covers sdist contents only. A fresh wheel, isolated install, all configuration coverage, and the complete example inventory are still required. This continuation does not complete or narrow the objective.
- Added
src/dns.rs: native wreq Resolve implementation invokes a synchronous Python callback with the hostname on a Tokio blocking worker. It accepts an iterable of(IP string, u16 port)pairs. Static overrides retain precedence; URL-explicit ports retain wreq precedence. Numeric IPs bypass resolution. - Native error conversion now walks the source chain to preserve original Python callback exceptions, including object identity. No shared error slot is used, so concurrent resolver failures cannot overwrite one another.
- Async clients support the same synchronous resolver. Connect deadlines and cancellation abandon waiting and release pool capacity while an already executing Python callback finishes independently. Async callable resolvers are not supported yet; this limitation is documented.
- Exposed request
groupas a string or unsigned 64-bit integer, retaining distinct string/numeric identities. On-wire peer-port tests prove same-group connection reuse and different-group separation, including"1"versus1. This partitions native connections, not the Python client's cookies/auth. - Added
docs/advanced/wreq-coverage.md, auditing all ClientBuilder and RequestBuilder method names in the pinned source, with explicit missing or partially covered behavior. This is a builder inventory, not a full audit of every nested type/trait or feature-gated API. Broader completion is still due. - DNS focused tests: 10 passed, including sync/async routing, original
callback exceptions, invalid results, static overrides, connect timeout, and
cancellation while the worker is blocked. Full native regression suite:
1495 passed, 1 skipped in 51.86s, terminal exit 0;
/tmp/httpxp-dns-group-suite.log. - Rust native build/check and formatting pass. Mypy initially found a missing annotation on the new group test helper; the annotation was added and static checks rerun. The native library was rebuilt and copied only between test runs.
- Next required implementations remain native middleware/connector runtime, Compio timer/executor, retry/redirect callbacks, custom cookie/session stores, complete header/emulation/compression precedence, TLS identities, response metadata, remaining examples, and isolated packaging validation.
- Python-facing names were normalized: clients, transports, helpers, and request
extensions use
privacy_optionsandextensions={"private": ...}. Example modules were renamed toexamples/private_proxy.pyandexamples/private_websocket.py; Rust dependency references remainwreq. - Audited
/home/jerlendds/Projects/uiray/scripts/wasm-harness/src/chrome.rsandsrc/lib.rs: it is a separate Rust/wasm Vercel challenge client with a fixed Chrome149 profile, cookies, challenge headers, and solver integration. It is not part of httpxp and does not represent generic browser support. httpxp now documents the supported Chrome, Firefox/private/Android, and Safari/iOS emulation profiles and supports independent clients with different profiles.