By Christian Findlay

HTTP

Runtime surface [BUILTIN-HTTP]

The native runtime provides an HTTP server and two client request surfaces. Handles and status codes are int; a negative value reports a runtime or transport failure.

Server [HTTP-SERVER]

Request handlers receive the method, path, raw headers, and body. They return the built-in HttpResponse record:

type HttpResponse = {
    status: int,
    headers: string,
    contentType: string,
    streamFd: int,
    isComplete: bool,
    partialBody: string
}

httpCreateServer(port: int, address: string) -> int
httpListen(serverID: int,
           handler: fn(string, string, string, string) -> HttpResponse) -> int
httpStopServer(serverID: int) -> int

httpCreateServer returns a positive handle. httpListen and httpStopServer return 0 on success. The runtime uses status, headers, and partialBody to form the response and computes Content-Length from the body. The other record fields remain required by the callback ABI but do not affect response transport.

The listener rejects malformed framing, transfer encoding, timeouts, and oversized requests before invoking the handler. It drains response headers and the body with retry-on-interrupt writes.

Status-only client [HTTP-STATUS-CLIENT]

httpCreateClient(baseUrl: string, timeoutMilliseconds: int) -> int
httpGet(clientID: int, path: string, headers: string) -> int
httpPost(clientID: int, path: string, body: string, headers: string) -> int
httpPut(clientID: int, path: string, body: string, headers: string) -> int
httpDelete(clientID: int, path: string, headers: string) -> int
httpCloseClient(clientID: int) -> int

Each request returns the HTTP status code, such as 200 or 404, and a negative value on transport failure. These calls discard the response body and headers.

Response handles [HTTP-RESPONSE-HANDLE]

httpGetResponse(clientID: int, path: string, headers: string)
    -> Result<int, Error>
httpResponseStatus(responseID: int) -> int
httpResponseBody(responseID: int) -> Result<string, Error>
httpResponseHeader(responseID: int, name: string) -> Result<string, Error>
httpResponseFree(responseID: int) -> Result<int, Error>

httpGetResponse retains one GET response and returns its opaque handle. httpResponseBody returns a copy, header lookup is case-insensitive, and chunked bodies are decoded before they are returned. Every successful handle must be released once with httpResponseFree; an invalid handle or double free returns Error.