Module std.net.http.codec
Build HTTP/1.1 requests and parse buffered responses over std.net.
Call conn.recv() directly; pending reads can suspend the caller.
Use fork for concurrent work and await for the resulting task.
The codec buffers bodies and uses one connection per request; HTTPS and
connection pooling are not provided here.
Example
import std.net;
import std.net.http.codec;
import std.encoding.utf8;
actor Fetcher {
let addr: string; // "127.0.0.1:8080"
let path: string; // "/hello"
let host: string; // "127.0.0.1"
receive fn go(unused: i64) {
let conn = match net.connect(addr) { .Ok(value) => value, .Err(error) => panic("network operation failed"), };
conn.send(codec.build_get(host, path).expect("valid request fields").to_bytes()).expect("send succeeds");
var raw = "";
var reads = 0;
var done = false;
while !done {
let chunk = match conn.recv() {
.Some(data) => utf8.decode(data) handle error {
println(f"invalid UTF-8: {error}");
return;
},
.None => "",
}; // suspends the worker
reads = reads + 1;
if (chunk).is_empty() {
done = true;
} else {
raw = raw + chunk;
if codec.response_over_limit(raw) { // F2: fail closed
done = true;
}
}
if reads > codec.CLIENT_MAX_READS { // F2: read ceiling
done = true;
}
}
let _ = conn.close();
let resp = codec.parse_response(raw).expect("valid response").expect("complete response");
println(resp.body());
}
}
Contents
- fn build_get
- fn build_request
- fn split_address
- fn host_of
- fn default_port
- fn response_over_limit
- fn parse_response
- struct Response
- enum BuildError
- enum ResponseError
- const CLIENT_MAX_HEADER_BYTES
- const CLIENT_MAX_BODY_BYTES
- const CLIENT_MAX_RESPONSE_BYTES
- const CLIENT_MAX_READS
Functions
Function build_get
pub fn build_get(host: string, path: string) -> string fails BuildError
Build a GET request line + headers for path on host, with the
Connection: close framing this buffered codec relies on (read-to-close).
Function build_request
pub fn build_request(method: string, host: string, path: string, body: string, content_type: string) -> string fails BuildError
Build an HTTP/1.1 request: the request line, Host, Connection: close,
and — for a non-empty body — Content-Type + Content-Length, then the
body. path is normalised to / when empty.
FAILS CLOSED on header smuggling (F4): a method, host, path, or
content_type carrying a \r/\n or other control character would inject
extra headers (or split the request line), so any such value is rejected and
a checked error is returned before any request bytes are emitted.
Function split_address
pub fn split_address(url_str: string) -> (string, string)
Parse url_str into a (host:port, path) pair ready for net.connect and
build_request. Plaintext HTTP/1.1 only: a scheme
prefix (http://) is stripped, the authority is split into host + optional
port (defaulting to 80, or 443 for an https scheme so a caller can detect
it), and the path defaults to /. Parsed with string ops — no dependency on
the opaque url engine.
Function host_of
pub fn host_of(url_str: string) -> string
Return the host component of url_str for the Host: header (no port).
Function default_port
pub fn default_port(scheme: string) -> i64
Default TCP port for a URL scheme (https → 443, everything else → 80).
Function response_over_limit
pub fn response_over_limit(raw: string) -> bool
Whether raw has exceeded a size bound and the read loop must STOP and fail
closed (F2). True when the buffered bytes exceed the total ceiling, the head
exceeds the header ceiling (even before a terminator is seen), or the declared
Content-Length exceeds the body ceiling. The response read loop checks this
each iteration so a malicious server cannot OOM the client with an unbounded
head/body or an enormous Content-Length.
Function parse_response
pub fn parse_response(raw: string) -> Option<Response> fails ResponseError
Parse a buffered HTTP response. None means more header or declared body
bytes are needed; malformed framing and size limits return an error.
Responses without Content-Length use the caller's read-to-close framing.
Types
Struct Response
A validated HTTP/1.1 response parsed from buffered text. code is the
HTTP status code and body_text is the response body. header_section is the raw header block (the lines
between the status line and the blank line, CRLF-separated), parsed on demand
by Response.header.
Fields
Methods
fn status(self) -> i64
The validated HTTP status code (e.g. 200, 404).
fn body(self) -> string
The response body as a string.
Enum BuildError
A request or response that cannot be serialized safely.
Variants
InvalidField(string)InvalidStatus(i64)
Enum ResponseError
A malformed or oversized buffered HTTP response.
Variants
Malformed(string)TooLarge
Constants
Constant CLIENT_MAX_HEADER_BYTES
pub const CLIENT_MAX_HEADER_BYTES: i64 = 65536
Maximum bytes accepted in the response head (status line + headers). A head
larger than this returns ResponseError.TooLarge before further buffering.
Constant CLIENT_MAX_BODY_BYTES
pub const CLIENT_MAX_BODY_BYTES: i64 = 16777216
Maximum bytes accepted in the response body — also the Content-Length
ceiling. A declared or buffered body larger than this fails closed.
Constant CLIENT_MAX_RESPONSE_BYTES
pub const CLIENT_MAX_RESPONSE_BYTES: i64 = 16842752
Maximum total response bytes buffered before the read loop fails closed
(CLIENT_MAX_HEADER_BYTES + CLIENT_MAX_BODY_BYTES). Bounds the accumulator
regardless of framing so a malicious server cannot OOM the client.
Constant CLIENT_MAX_READS
pub const CLIENT_MAX_READS: i64 = 8192
Maximum number of read iterations a response loop will accept before failing closed. Bounds an endless-trickle server that never closes the connection.