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

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

code: i64
body_text: string
header_section: string

Methods

fn status(self) -> i64

The validated HTTP status code (e.g. 200, 404).

fn body(self) -> string

The response body as a string.

fn header(self, name: string) -> Option<string>

Look up a response header by name (case-insensitive), or None if absent.

fn content_type(self) -> Option<string>

The Content-Type response header, or None if absent.

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.