The http module provides a typed HTTP client with Result-based error handling, a fluent request builder, and a mock transport for deterministic testing.
import http
let resp = http.get("https://api.example.com/users").unwrap()
print(resp.status()) # 200
print(resp.body()) # raw response body
Basic requests
| Function | Returns | Description |
http.get(url) | Result[HttpResponse, HttpError] | Send a GET request |
http.post(url, body) | Result[HttpResponse, HttpError] | Send a POST request |
http.put(url, body) | Result[HttpResponse, HttpError] | Send a PUT request |
http.del(url) | Result[HttpResponse, HttpError] | Send a DELETE request |
http.patch(url, body) | Result[HttpResponse, HttpError] | Send a PATCH request |
http.request(method, url) | Result[HttpResponse, HttpError] | Send with any method |
All functions accept optional keyword arguments: headers (Dict), params (Dict), timeout_ms (Int, default 10000). post, put, and patch also accept body (Str).
HttpResponse
| Method | Returns | Description |
.status() | Int | HTTP status code |
.body() | Str | Response body as text |
.headers() | Dict[Str, Str] | Response headers |
.header(name) | Str? | Single header value by name |
.ok() | Bool | True if status code is 2xx |
.url() | Str | The request URL |
JSON-first API
For JSON APIs, skip the intermediate HttpResponse and get a Result[Json, HttpError] directly:
import http
let data = http.get_json("https://api.example.com/items").unwrap()
let name = data.get_str("name")
let body = Json.empty_object().set_str("name", "alice")
let created = http.post_json("https://api.example.com/users", body).unwrap()
| Function | Returns | Description |
http.get_json(url) | Result[Json, HttpError] | GET and parse as JSON |
http.post_json(url, payload) | Result[Json, HttpError] | POST JSON payload and parse response |
Request builder
Use http.new(method, url) to construct requests with multiple headers or query parameters:
import http
let resp = http.new("GET", "https://api.example.com/search")
.header("Authorization", "Bearer " + token)
.query("q", "vary language")
.query("limit", "10")
.timeout(5000)
.send()
.unwrap()
| Method | Returns | Description |
.header(name, value) | HttpRequestBuilder | Add a request header |
.body(text) | HttpRequestBuilder | Set the request body |
.query(name, value) | HttpRequestBuilder | Add a query parameter |
.json(value) | HttpRequestBuilder | Set JSON request body |
.timeout(ms) | HttpRequestBuilder | Set timeout in milliseconds |
.send() | Result[HttpResponse, HttpError] | Execute the request |
Mock transport for testing
Replace the global transport with a mock to test HTTP-dependent code without real network calls:
import http
let m = http.mock()
m.addRoute("GET https://api.example.com/ping", 200, "pong", {})
m.addRoute("POST https://api.example.com/users", 201, '{"id": 42}', {})
http.set_transport(m)
let resp = http.get("https://api.example.com/ping").unwrap()
print(resp.body()) # "pong"
http.clear_transport() # restore real HTTP
| Function | Returns | Description |
http.mock() | HttpMockTransport | Create a mock transport |
http.set_transport(mock) | None | Install mock as global transport |
http.clear_transport() | None | Restore real HTTP transport |
mock.addRoute(key, status, body, headers) | None | Register a mock response (key is "METHOD url") |
mock.call_count() | Int | Number of requests made through the mock |
mock.last_call() | Str? | Key of the most recent mock call |
mock.all_calls() | List[Str] | All mock call keys in order |
mock.reset() | None | Clear all recorded calls |
HttpError
| Method | Returns | Description |
.kind() | Str | Error category (see below) |
.message() | Str | Human-readable error detail |
Error kinds:
| Kind | When |
"connection" | Could not connect to the server |
"timeout" | Request exceeded the timeout |
"protocol" | Invalid HTTP response |
"decode" | Response body could not be decoded |