HTTP
The HTTP module provides a complete HTTP client for making web requests. It supports all standard HTTP methods, custom headers, Bearer token authentication, and automatic retry with exponential backoff.
Basic Requests
HTTP.get
String -> Result Response HTTPError
Performs an HTTP GET request to the specified URL.
match HTTP.get "https://api.example.com/users"
| Ok response -> println response.body
| Err e -> println "Error: ${e}"
HTTP.post
String -> String -> Result Response HTTPError
Performs an HTTP POST request with a body.
body = "{\"name\": \"Alice\", \"email\": \"alice@example.com\"}"
match HTTP.post "https://api.example.com/users" body
| Ok response -> println "Created: ${response.body}"
| Err e -> println "Error: ${e}"
HTTP.put
String -> String -> Result Response HTTPError
Performs an HTTP PUT request with a body.
HTTP.put "https://api.example.com/users/1" "{\"name\": \"Bob\"}"
HTTP.delete
String -> Result Response HTTPError
Performs an HTTP DELETE request.
HTTP.delete "https://api.example.com/users/1"
HTTP.patch
String -> String -> Result Response HTTPError
Performs an HTTP PATCH request with a body.
HTTP.patch "https://api.example.com/users/1" "{\"status\": \"active\"}"
HTTP.head
String -> Result Response HTTPError
Performs an HTTP HEAD request (returns headers only, no body).
HTTP.head "https://api.example.com/users"
Convenience Functions
For quick scripts where you want to panic on errors, use the bang variants:
HTTP.get!
String -> String
GET request that returns the body directly. Panics on error.
body = HTTP.get! "https://api.example.com/data"
println body
HTTP.post!
String -> String -> Response
POST request that returns the response directly. Panics on error.
response = HTTP.post! "https://api.example.com/data" "{\"key\": \"value\"}"
println response.body
Custom Headers
HTTP.get-with-headers
String -> a -> Result Response HTTPError
GET request with custom headers. Headers should be a record with string keys and values.
headers = {
"Authorization": "Bearer my-token",
"Content-Type": "application/json"
}
match HTTP.get-with-headers "https://api.example.com/protected" headers
| Ok response -> println response.body
| Err e -> println "Error: ${e}"
HTTP.post-with-headers
String -> String -> a -> Result Response HTTPError
POST request with custom headers.
match HTTP.post-with-headers "https://api.example.com/data" body headers
| Ok response -> println response.body
| Err e -> println "Error: ${e}"
Bearer Authentication
Convenience functions for Bearer token authentication, commonly used with OAuth2 and API tokens.
HTTP.bearer-auth
String -> String
Creates an Authorization header value from a token.
auth-header = HTTP.bearer-auth "my-token"
# Returns: "Bearer my-token"
# Use with custom headers
headers = {authorization: auth-header, "X-Custom": "value"}
HTTP.get-with-headers url headers
HTTP.get-with-bearer
String -> String -> Result Response HTTPError
GET request with Bearer token authentication.
api-token = "my-secret-token"
match HTTP.get-with-bearer "https://api.example.com/protected" api-token
| Ok response -> println response.body
| Err e -> println "Error: ${e}"
HTTP.post-with-bearer
String -> String -> String -> Result Response HTTPError
POST request with Bearer token authentication.
body = "{\"data\": \"value\"}"
match HTTP.post-with-bearer "https://api.example.com/data" body api-token
| Ok response -> println response.body
| Err e -> println "Error: ${e}"
HTTP.parse-bearer-token
String -> Option String
Extracts a Bearer token from an Authorization header value.
match HTTP.parse-bearer-token "Bearer abc123"
| Some token -> println "Token: ${token}"
| None -> println "No bearer token found"
# Returns None for non-Bearer auth or empty tokens
HTTP.parse-bearer-token "Basic xyz" # None
HTTP.parse-bearer-token "Bearer " # None (empty token)
Retry Support
HTTP.fetch-with-retry
String -> a -> Result Response HTTPError
Fetch with automatic retry and exponential backoff for handling transient failures.
options = {
method: "GET",
retry: {
max-retries: 3,
backoff: "exponential",
base-delay-ms: 100
}
}
match HTTP.fetch-with-retry "https://api.example.com/data" options
| Ok response -> println response.body
| Err e -> println "Failed after retries: ${e}"
HTTP.fetch
String -> a -> Result Response HTTPError
Generic fetch with full control over method, headers, body, and timeout.
HTTP.request
String -> a -> Result Response HTTPError
Low-level request function with full control over method and options.
Response Helpers
Convenience functions for checking HTTP response status codes.
HTTP.success?
Response -> Bool
Returns
true if the response was successful (2xx status code).
HTTP.redirect?
Response -> Bool
Returns
true if the response was a redirect (3xx status code).
HTTP.client-error?
Response -> Bool
Returns
true if the response was a client error (4xx status code).
HTTP.server-error?
Response -> Bool
Returns
true if the response was a server error (5xx status code).
match HTTP.get "https://api.example.com/data"
| Ok response ->
if HTTP.success? response then
println "Success: ${response.body}"
else if HTTP.redirect? response then
println "Redirect (${response.status})"
else if HTTP.client-error? response then
println "Client error (${response.status})"
else if HTTP.server-error? response then
println "Server error (${response.status})"
else
println "Unknown status: ${response.status}"
| Err e -> println "Error: ${e}"
Error Types
All HTTP functions return Result with HTTPError for typed error handling.
type HTTPError =
| HTTPConnectionError { message: String }
| HTTPTimeoutError { message: String }
| HTTPRequestError { message: String }
| HTTPResponseError { message: String }
Handling Errors
match HTTP.get "https://api.example.com/users"
| Ok response -> println response.body
| Err (HTTPConnectionError { message }) ->
println "Connection failed: ${message}"
| Err (HTTPTimeoutError { message }) ->
println "Request timed out: ${message}"
| Err (HTTPRequestError { message }) ->
println "Request error: ${message}"
| Err (HTTPResponseError { message }) ->
println "Response error: ${message}"
# Or use the Error trait for generic handling
match HTTP.get "https://api.example.com/users"
| Ok response -> println response.body
| Err e -> println "Error (${Error.kind e}): ${Error.message e}"