Skip to main content

Module http

Module http 

Source
Expand description

A minimal blocking HTTP/1.1 client over any Read + Write. RFC 0006.

This is the single highest-leverage minimalism decision (RFC 0002): one ~250-line module replaces the ureq/url→IDNA→ICU dependency tax. It carries the intelligence wire over TCP, TLS, unix sockets, and vsock alike — the transport is just the stream.

Two request paths: send buffers the whole response (the LLM/intelligence path), and send_streaming returns the status + headers plus a live reader so the caller can either buffer it (application/json) or pump it as an SSE stream (SseReader) — the MCP Streamable HTTP transport, where a response may be a single JSON body or a text/event-stream, and a long-lived GET carries server→client notifications. connect_tcp is intentionally unguarded: agentd’s HTTP client only ever dials the operator-configured intelligence endpoint, which the model cannot influence. The SSRF classifier (net::ssrf) exists for any future model/agent-supplied URL surface and is composed at the call site that needs it.

Structs§

Response
A parsed HTTP response.
SseEvent
One parsed SSE event (RFC 6455-style text/event-stream). For MCP, data is a JSON-RPC message; event/id are the optional SSE field lines.
SseReader
A blocking, line-based SSE reader. next_event accumulates field: value lines and emits one SseEvent per blank-line separator (multiple data: lines join with \n), returning Ok(None) at end of stream. Bounded per event by MAX_RESPONSE so a hostile stream cannot exhaust memory.
StreamingResponse
A streamed response: status + headers, plus the reader positioned at the body. The caller decides how to drain it — [into_body] to buffer (application/json) or [sse] to pump it as an SSE event stream (text/event-stream). Owns the underlying stream, matching the MCP client’s per-request connection model.
Url
A parsed absolute URL (the subset we need: scheme/host/port/path).

Constants§

MAX_RESPONSE
Response body cap. LLM responses can be large; 8 MiB is generous without being an unbounded allocation from a hostile peer.

Traits§

Stream
Any bidirectional byte stream the HTTP client can run over. Box<dyn Stream> is itself Read + Write (via std’s impl<R: Read + ?Sized> Read for Box<R>), so an OWNED boxed stream can be handed to send_streaming by value — used by the long-lived MCP notification SSE reader.

Functions§

connect_tcp
Connect a plain TCP stream with connect + read/write timeouts. Intentionally unguarded — the only caller dials the operator-configured endpoint; the SSRF classifier (net::ssrf) is composed at any model/agent-supplied URL surface.
is_loopback_host
Whether host names the local loopback — the dev/test carve-out for plaintext http:// (production transports are TLS-only). Accepts the IPv4 loopback block (127.0.0.0/8), the IPv6 loopback (::1, bare or bracketed), and the literal name localhost. A resolvable-but-unresolved name is NOT loopback — this classifies the written form, without DNS.
send
Issue one request over stream and read the full response. Adds Host, Connection: close, and Content-Length; the caller supplies any other headers (e.g. Authorization, Content-Type).
send_streaming
Issue one request over an OWNED stream and return the status + headers + body reader WITHOUT draining the body (unlike send). Adds Host, Connection: close, and Content-Length; the caller supplies the rest (Accept, Authorization, Content-Type, Mcp-Session-Id, …).