rightkit-http
Shared blocking HTTP client for Right Suite applications. It provides timeouts, bounded bodies, retry and backoff that honours Retry-After (never retrying unsafe methods), streaming responses, WHATWG Server-Sent Events decoding, redacted secrets, and tamper-evident wrapping of untrusted web text before it reaches a model.
Catalog capability: http-client. Published to crates.io (see INDEX.md).
What it owns
Client,ClientConfig,Request,Response,StreamResponse: timeouts, bounded bodies, redirect policy, streaming reads, andget_json.RetryPolicy: retry and backoff. Retries respectRetry-After. Non-idempotent methods are not retried.AsyncClient(featureasync):send,send_any,stream,get_jsonwith identical timeout, retry/backoff, redirect, user-agent, proxy (environment variables) and size-limit behaviour.streamreturns aBodyStreamofByteschunks or anSseStream(.sse(),.sse_with_limits(max_line, max_event)), bounded to 1 MiB per line and 4 MiB per event by default.sse:SseDecoder(new,with_limits),SseReader,SseEvent. WHATWG-compliant Server-Sent Events.untrusted:wrap_untrusted_web_textfor external text, with boundary markers and injection-signal reporting.secret: a redactedSecret, and theSecretStoretrait thatrightkit-secretsimplements.MemorySecretStoreis provided for tests.testing(feature): an in-process mock server that records exact requests.
When to use it
- Use it for blocking HTTP calls from Right Suite apps where timeouts, retries and bounded bodies must be consistent.
- Use it for SSE streams and for wrapping web text before model input.
The default client is blocking (ureq with rustls). For async code enable the async feature: AsyncClient on reqwest with rustls, run inside a tokio runtime.
Cargo features
| Feature | Default | Pulls in | Enables |
|---|---|---|---|
gzip |
yes | ureq/gzip |
Automatic Accept-Encoding: gzip and transparent decoding for buffered responses and stream readers. Matches ureq's default. |
async |
no | reqwest (rustls, no native-tls), tokio (time), futures-util, bytes |
AsyncClient, AsyncStreamResponse, BodyStream, SseStream. Same ClientConfig, Request, Response, HttpError and policy as the blocking client. With gzip, also enables reqwest/gzip. |
testing |
no | none | The testing module: MockServer, MockResponse, MockBody, RecordedRequest. |
To opt out of gzip:
= { = "<exact published version from INDEX.md>", = false }
Usage
Client configuration, from the crate README. Every field below exists in ClientConfig:
use Duration;
use ;
let client = new;
Request shape, from tests/e2e.rs: Request::post(url).bearer(token).json(&value)? then client.send(&req)?.
Timeouts
connect_timeoutandresponse_timeoutareOption<Duration>. The defaults areSome(10 s)for connect andSome(60 s)for response headers. UseNoneto disable a per-phase deadline. Disabling phase deadlines does not disable global deadlines.- Buffered calls use
request_timeout(60 s by default). Streams usestream_timeout(Noneby default). recv_body_timeoutdefaults toNone. When set, it limits total body-receive time after headers arrive. Progress does not reset it.- Buffered body timeouts return
HttpError::Timeout. Stream readers keep the underlyingstd::io::Error. Body reads are never retried. - Callers that passed bare durations to
connect_timeoutorresponse_timeoutmust wrap them inSome(...). The change is recorded in CHANGELOG.md.
Redirects
max_redirectsdefaults to 0, so redirects are not followed. With 0, a 3xx response is always returned, whatever the error policy.max_redirects_will_errordefaults totrue, matching ureq. When a nonzero limit is exhausted, the call returnsHttpError::Transport { connect_phase: false, .. }. That error is eligible for idempotent retries under the retry policy.- Set it to
falseto receive the final 3xx throughsend_any.
Platform support
Pure Rust over ureq with rustls. No platform-specific code in the crate. Certificate and TLS behaviour follows rustls.
Tests
tests/e2e.rs and, with --features async, tests/async_e2e.rs: a real local TCP server. Assertions use exact requests seen on the wire and exact bytes received.
Version and changes
Published version: see INDEX.md. Version history: CHANGELOG.md.