Http

struct Response

A complete response: status, headers, and the whole body.

struct Request

An incoming request, as a handler receives it.

struct RequestLine

A request's first line, split.

struct RequestHead

A request's head, before its body has been read. leftover_body carries the bytes that arrived alongside the headers.

let request (method: String) (url: String) (headers: Array[Header]) (body: String): Result[Response, String]

fd has to stay reachable for the FINAL cleanup step regardless of http_do_request's own outcome — closure capture (fd bound by the outer and_then, still in scope in the block passed to the inner one) does this without needing the old two-armed "close then re-wrap Ok/Err separately" match at all.

let get (url: String): Result[Response, String]

Fetches a URL and reads the whole response.

HTTP only — https:// is not supported and is rejected rather than silently attempted in the clear.

Redirects are NOT followed: a 301 or 302 comes back as itself, with its Location header, so the caller decides. Following one changes which host you are talking to, which is not a decision a library should make quietly.

let post (url: String) (body: String): Result[Response, String]

POSTs a body and reads the whole response. Sets Content-Length; set Content-Type yourself if the server needs one.

HTTP only, and redirects are not followed — see Http.get.

let serve_once (port: Int) (handler: (Request) -> Response): Result[Unit, String]

Handles exactly ONE connection then returns — listens, accepts once, closes both the connection and the listening socket, and gives back whatever http_handle_connection produced. Real, useful on its own (a one-shot server, or a test fixture — this is what THIS module's own tests exercise directly), not just a building block for http_ serve below.

let serve (port: Int) (handler: (Request) -> Response): Result[Unit, String]

Serves HTTP on a port, calling handler once per request, forever.

Never returns unless the listen itself fails. One connection is handled at a time — a slow handler blocks the next request, which is fine for a local tool and is not a production server.