HTTP Client API Reference

Full-featured HTTP client library with request building, response handling, connection pooling, and TLS support

Import

U std/http_client

Overview

The HTTP Client module provides a complete HTTP/HTTPS client implementation with support for:

  • All standard HTTP methods (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)
  • URL parsing and validation
  • Header management (set, add, remove, get)
  • Request/response body handling
  • JSON, form, and text content types
  • Authentication helpers (Bearer token, Basic auth)
  • Connection pooling and keep-alive
  • Automatic redirect following
  • Timeout configuration
  • TLS/HTTPS with SNI and certificate verification

Constants

HTTP Methods

ConstantValueDescription
CLIENT_GET1GET method
CLIENT_POST2POST method
CLIENT_PUT3PUT method
CLIENT_DELETE4DELETE method
CLIENT_PATCH5PATCH method
CLIENT_HEAD6HEAD method
CLIENT_OPTIONS7OPTIONS method

Buffer Sizes

ConstantValueDescription
CLIENT_MAX_HEADERS8192Maximum header buffer size
CLIENT_MAX_BODY1048576Maximum body size (1MB)
CLIENT_RECV_CHUNK4096Receive buffer chunk size
CLIENT_MAX_URL_LEN2048Maximum URL length

Default Configuration

ConstantValueDescription
CLIENT_DEFAULT_TIMEOUT30000Default timeout (30 seconds)
CLIENT_DEFAULT_MAX_REDIRECTS10Maximum redirects to follow
CLIENT_DEFAULT_PORT_HTTP80Default HTTP port
CLIENT_DEFAULT_PORT_HTTPS443Default HTTPS port

Connection Pool

ConstantValueDescription
POOL_MAX_CONNECTIONS16Maximum pooled connections
POOL_ENTRY_SIZE32Pool entry size in bytes

Error Codes

ConstantValueDescription
CLIENT_ERR_NONE0No error
CLIENT_ERR_DNS-1DNS resolution failed
CLIENT_ERR_CONNECT-2Connection failed
CLIENT_ERR_SEND-3Send failed
CLIENT_ERR_RECV-4Receive failed
CLIENT_ERR_TIMEOUT-5Request timed out
CLIENT_ERR_PARSE-6Response parse error
CLIENT_ERR_TOO_MANY_REDIRECTS-7Too many redirects
CLIENT_ERR_INVALID_URL-8Invalid URL
CLIENT_ERR_TLS_INIT-9TLS initialization failed
CLIENT_ERR_TLS_HANDSHAKE-10TLS handshake failed

Structs

Url

URL component parser and builder.

FieldTypeDescription
schemestrProtocol ("http" or "https")
hoststrHostname or IP address
porti64Port number (default: 80/443)
pathstrPath component
querystrQuery string (without ?)
rawstrOriginal URL string

Methods:

MethodSignatureDescription
parseF parse(raw_url: str) -> UrlParse URL string into components
is_httpsF is_https(&self) -> i64Check if URL uses HTTPS (1=yes, 0=no)
request_pathF request_path(&self) -> strGet path with query string
host_headerF host_header(&self) -> strGet Host header value (host:port)

HttpRequest

HTTP request builder with chainable methods.

FieldTypeDescription
methodi64HTTP method constant
urlUrlParsed URL
headersi64Pointer to header array
header_counti64Number of headers
header_capacityi64Header array capacity
bodyi64Pointer to body data
body_leni64Body length in bytes
timeout_msi64Request timeout in milliseconds

Constructors:

MethodSignatureDescription
newF new(method: i64, url_str: str) -> HttpRequestCreate request with method and URL
getF get(url: str) -> HttpRequestCreate GET request
postF post(url: str) -> HttpRequestCreate POST request
putF put(url: str) -> HttpRequestCreate PUT request
deleteF delete(url: str) -> HttpRequestCreate DELETE request
patchF patch(url: str) -> HttpRequestCreate PATCH request
headF head(url: str) -> HttpRequestCreate HEAD request
optionsF options(url: str) -> HttpRequestCreate OPTIONS request

Header Management:

MethodSignatureDescription
add_headerF add_header(&self, name: str, value: str) -> HttpRequestAdd header (allows duplicates)
set_headerF set_header(&self, name: str, value: str) -> HttpRequestSet/replace header
remove_headerF remove_header(&self, name: str) -> HttpRequestRemove header by name
get_headerF get_header(&self, name: str) -> str?Get header value (Option)

Body Methods:

MethodSignatureDescription
with_bodyF with_body(&self, data: i64, len: i64) -> HttpRequestSet raw body data
with_textF with_text(&self, text: str) -> HttpRequestSet text body (text/plain)
with_jsonF with_json(&self, json_str: str) -> HttpRequestSet JSON body (application/json)
with_formF with_form(&self, form_data: str) -> HttpRequestSet form body (application/x-www-form-urlencoded)

Configuration:

MethodSignatureDescription
with_timeoutF with_timeout(&self, ms: i64) -> HttpRequestSet request timeout
with_bearer_tokenF with_bearer_token(&self, token: str) -> HttpRequestSet Bearer token authentication
with_basic_authF with_basic_auth(&self, encoded: str) -> HttpRequestSet Basic authentication

Other Methods:

MethodSignatureDescription
method_strF method_str(&self) -> strGet method as string ("GET", "POST", etc.)
serializeF serialize(&self, buffer: i64, buffer_size: i64) -> i64Serialize request to buffer
dropF drop(&self) -> i64Free allocated memory

HttpResponse

Parsed HTTP response with status, headers, and body.

FieldTypeDescription
statusi64HTTP status code (200, 404, etc.)
status_textstrStatus text ("OK", "Not Found", etc.)
versionstrHTTP version ("HTTP/1.1")
headersi64Pointer to header array
header_counti64Number of headers
header_capacityi64Header array capacity
bodyi64Pointer to body data
body_leni64Body length in bytes
error_codei64Error code (0 on success)

Constructors:

MethodSignatureDescription
errorF error(code: i64) -> HttpResponseCreate error response

Status Checking:

MethodSignatureDescription
is_okF is_ok(&self) -> i64Check if no transport error (1=ok, 0=error)
is_successF is_success(&self) -> i64Check if status is 2xx
is_redirectF is_redirect(&self) -> i64Check if status is 3xx
is_client_errorF is_client_error(&self) -> i64Check if status is 4xx
is_server_errorF is_server_error(&self) -> i64Check if status is 5xx

Content Access:

MethodSignatureDescription
body_textF body_text(&self) -> strGet body as string
get_headerF get_header(&self, name: str) -> str?Get header value (case-insensitive)
has_headerF has_header(&self, name: str) -> i64Check if header exists
content_typeF content_type(&self) -> str?Get Content-Type header
content_lengthF content_length(&self) -> i64Get Content-Length (-1 if not present)
locationF location(&self) -> str?Get Location header (for redirects)

Error Handling:

MethodSignatureDescription
error_textF error_text(&self) -> strGet error description string
dropF drop(&self) -> i64Free allocated memory

ConnectionPool

Connection pool for keep-alive connection reuse.

FieldTypeDescription
entriesi64Pointer to pool entry array
counti64Number of active entries
capacityi64Maximum capacity

Methods:

MethodSignatureDescription
newF new() -> ConnectionPoolCreate new connection pool
getF get(&self, host: str, port: i64) -> i64Get cached connection fd (-1 if none)
putF put(&self, host: str, port: i64, fd: i64) -> i64Return connection to pool
close_allF close_all(&self) -> i64Close all pooled connections
dropF drop(&self) -> i64Free pool memory

HttpClient

Configurable HTTP client with connection pooling and redirect support.

FieldTypeDescription
timeout_msi64Default timeout in milliseconds
follow_redirectsi64Enable redirect following (1=on, 0=off)
max_redirectsi64Maximum redirects to follow
keep_alivei64Enable keep-alive (1=on, 0=off)
poolConnectionPoolConnection pool
default_headersi64Pointer to default header array
default_header_counti64Number of default headers
default_header_capacityi64Default header capacity

Constructor:

MethodSignatureDescription
newF new() -> HttpClientCreate HTTP client with defaults

Configuration:

MethodSignatureDescription
timeoutF timeout(&self, ms: i64) -> HttpClientSet default timeout
follow_redirectsF follow_redirects(&self, follow: i64) -> HttpClientEnable/disable redirects
max_redirectsF max_redirects(&self, max: i64) -> HttpClientSet maximum redirects
keep_aliveF keep_alive(&self, enabled: i64) -> HttpClientEnable/disable keep-alive
default_headerF default_header(&self, name: str, value: str) -> HttpClientAdd default header

Request Execution:

MethodSignatureDescription
sendF send(&self, request: &HttpRequest) -> HttpResponseExecute HTTP request

Convenience Methods:

MethodSignatureDescription
getF get(&self, url: str) -> HttpResponseSend GET request
post_jsonF post_json(&self, url: str, json_body: str) -> HttpResponseSend POST with JSON body
post_formF post_form(&self, url: str, form_data: str) -> HttpResponseSend POST with form data
post_textF post_text(&self, url: str, text: str) -> HttpResponseSend POST with text body
put_jsonF put_json(&self, url: str, json_body: str) -> HttpResponseSend PUT with JSON body
patch_jsonF patch_json(&self, url: str, json_body: str) -> HttpResponseSend PATCH with JSON body
deleteF delete(&self, url: str) -> HttpResponseSend DELETE request
headF head(&self, url: str) -> HttpResponseSend HEAD request

Cleanup:

MethodSignatureDescription
closeF close(&self) -> i64Close all pooled connections
dropF drop(&self) -> i64Free all memory

JSON Helper Functions

FunctionSignatureDescription
json_kvF json_kv(key: str, value: str) -> strBuild JSON object with one key-value pair
json_kv2F json_kv2(k1: str, v1: str, k2: str, v2: str) -> strBuild JSON object with two key-value pairs
json_kv_intF json_kv_int(key: str, value: i64) -> strBuild JSON object with integer value

Top-Level Convenience Functions

FunctionSignatureDescription
http_clientF http_client() -> HttpClientCreate new HTTP client
http_getF http_get(url: str) -> HttpResponseSimple GET request (one-shot)
http_postF http_post(url: str, json_body: str) -> HttpResponseSimple POST with JSON (one-shot)
http_putF http_put(url: str, json_body: str) -> HttpResponseSimple PUT with JSON (one-shot)
http_deleteF http_delete(url: str) -> HttpResponseSimple DELETE request (one-shot)
http_patchF http_patch(url: str, json_body: str) -> HttpResponseSimple PATCH with JSON (one-shot)

Usage Examples

Simple GET Request

U std/http_client

F main() -> i64 {
    resp := http_get("https://api.example.com/users")

    I resp.is_success() == 1 {
        body := resp.body_text()
        __println(body)
        __println("Status: ", resp.status)
    } E {
        __println("Error: ", resp.error_text())
    }

    resp.drop()
    0
}

POST JSON Request

U std/http_client

F main() -> i64 {
    json := json_kv2("name", "Alice", "email", "alice@example.com")
    resp := http_post("https://api.example.com/users", json)

    I resp.is_success() == 1 {
        __println("Created: ", resp.body_text())
    }

    resp.drop()
    0
}

Custom Request with Headers

U std/http_client

F main() -> i64 {
    req := HttpRequest::get("https://api.example.com/protected")
        .with_bearer_token("eyJhbGc...")
        .set_header("X-Custom-Header", "value")
        .with_timeout(10000)  # 10 seconds

    client := HttpClient::new()
    resp := client.send(&req)

    I resp.is_success() == 1 {
        __println("Response: ", resp.body_text())
    }

    req.drop()
    resp.drop()
    client.drop()
    0
}

Reusable Client with Connection Pooling

U std/http_client

F main() -> i64 {
    client := HttpClient::new()
        .timeout(5000)
        .follow_redirects(1)
        .keep_alive(1)
        .default_header("User-Agent", "MyApp/1.0")

    # First request (creates connection)
    resp1 := client.get("http://example.com/api/users")
    __println("Status: ", resp1.status)
    resp1.drop()

    # Second request (reuses connection)
    resp2 := client.get("http://example.com/api/posts")
    __println("Status: ", resp2.status)
    resp2.drop()

    client.drop()
    0
}

PUT Request with JSON

U std/http_client

F main() -> i64 {
    json := json_kv2("name", "Bob", "status", "active")

    req := HttpRequest::put("https://api.example.com/users/123")
        .with_json(json)
        .with_bearer_token("token123")

    client := HttpClient::new()
    resp := client.send(&req)

    I resp.is_success() == 1 {
        __println("Updated successfully")
    } E {
        __println("Error: ", resp.status, " - ", resp.error_text())
    }

    req.drop()
    resp.drop()
    client.drop()
    0
}

Handling Response Headers

U std/http_client

F main() -> i64 {
    resp := http_get("https://api.example.com/data")

    # Get specific headers
    content_type := resp.content_type()
    M content_type {
        Some(ct) => __println("Content-Type: ", ct),
        None => __println("No Content-Type header")
    }

    content_len := resp.content_length()
    I content_len >= 0 {
        __println("Content-Length: ", content_len)
    }

    # Check if header exists
    I resp.has_header("X-Custom-Header") == 1 {
        custom := resp.get_header("X-Custom-Header")
        M custom {
            Some(val) => __println("Custom: ", val),
            None => 0
        }
    }

    resp.drop()
    0
}

Basic Authentication

U std/http_client

F main() -> i64 {
    # Encode "user:password" in base64
    encoded := "dXNlcjpwYXNzd29yZA=="

    req := HttpRequest::get("https://api.example.com/secure")
        .with_basic_auth(encoded)

    client := HttpClient::new()
    resp := client.send(&req)

    I resp.status == 200 {
        __println("Authenticated: ", resp.body_text())
    } E I resp.status == 401 {
        __println("Authentication failed")
    }

    req.drop()
    resp.drop()
    client.drop()
    0
}

Redirect Handling

U std/http_client

F main() -> i64 {
    client := HttpClient::new()
        .follow_redirects(1)
        .max_redirects(5)

    resp := client.get("http://example.com/redirect")

    I resp.is_success() == 1 {
        __println("Final response: ", resp.body_text())
    } E I resp.error_code == CLIENT_ERR_TOO_MANY_REDIRECTS {
        __println("Too many redirects")
    }

    resp.drop()
    client.drop()
    0
}

Error Handling

U std/http_client

F main() -> i64 {
    resp := http_get("https://invalid-domain-xyz.com")

    I resp.is_ok() == 0 {
        M resp.error_code {
            CLIENT_ERR_DNS => __println("DNS resolution failed"),
            CLIENT_ERR_CONNECT => __println("Connection failed"),
            CLIENT_ERR_TIMEOUT => __println("Request timed out"),
            CLIENT_ERR_TLS_INIT => __println("TLS initialization failed"),
            CLIENT_ERR_TLS_HANDSHAKE => __println("TLS handshake failed"),
            _ => __println("Unknown error: ", resp.error_text())
        }
    } E {
        __println("Status: ", resp.status)
    }

    resp.drop()
    0
}

Form Data POST

U std/http_client

F main() -> i64 {
    form := "username=alice&password=secret123&remember=true"

    req := HttpRequest::post("https://example.com/login")
        .with_form(form)

    client := HttpClient::new()
    resp := client.send(&req)

    I resp.is_redirect() == 1 {
        location := resp.location()
        M location {
            Some(url) => __println("Redirect to: ", url),
            None => __println("No location header")
        }
    }

    req.drop()
    resp.drop()
    client.drop()
    0
}

Notes

  • HTTPS requires TLS support compiled into the runtime
  • Connection pooling is only available for plain HTTP connections (not HTTPS)
  • Default headers are applied to all requests sent through the client
  • Redirects automatically convert POST/PUT/PATCH to GET for 301/302/303 status codes
  • The client automatically adds default headers: User-Agent, Accept, Connection
  • All strings returned by the API should be freed by the caller when appropriate
  • Use drop() methods to free allocated memory for requests, responses, and clients