Net.HTTP
module Net.HTTP
Buffered HTTP clients, responses, and a small declaration-ordered server router. Requests never follow redirects or perform generic retries implicitly.
using Net.HTTP
let response = HTTP.get("https://example.test/").try
response.status.success? # => true
For connection reuse and statistics, own a client explicitly:
let client = Client.open.try
let response = client.get("https://example.test/").try
client.close.try
record Headers
An insertion-ordered HTTP field collection. Names compare case-insensitively and duplicate fields are preserved.
Fields
Implements Showable, Inspectable.
Methods
add
add(name: String, value: String) -> Headers
Appends a field without replacing existing fields of the same name.
Examples
+Headers.empty.add("Accept", "text/plain")+
set
set(name: String, value: String) -> Headers
Replaces all fields of name with one value.
Examples
+headers.set("Content-Type", "application/json")+
remove
remove(name: String) -> Headers
Removes every field matching name case-insensitively.
Examples
Stripping hop-by-hop state before forwarding
let forwarded = incoming.remove("Connection")
get
get(name: String) -> String?
Returns the first matching field value.
Examples
Selecting a response decoder
let contentType = response.headers.get("Content-Type").or("application/octet-stream")
getAll
getAll(name: String) -> [String]
Returns every matching value in insertion order.
Examples
Preserving every Set-Cookie field
let cookies = response.headers.getAll("Set-Cookie")
showValue Showable
showValue : String
Renders fields while replacing authorization and cookie values with ***.
inspectValue Inspectable
inspectValue(colors: Bool) -> String
Structural inspection uses the same credential-safe rendering.
From Showable
record Status
A validated HTTP status code in 100..599.
Fields
codeInteger
Methods
record Response<B>
A typed HTTP response envelope whose body representation is explicit.
Fields
record Request<B>
A typed HTTP request envelope whose body representation is explicit.
Fields
record RouteContext
Route captures decoded after path segmentation.
Fields
Methods
record Context
Per-request server context.
Fields
routeRouteContext
type Handler
A buffered HTTP route handler. Handling a request is effectful: routes may read files, query a database, send messages, or perform other application IO.
record Route
One declared route; routers preserve declaration order.
Fields
record Router
An immutable, declaration-ordered HTTP router.
Fields
routes[Route]optional
Methods
route
route(method: String, path: String, handler: Handler) -> Router
Appends a route; earlier matching declarations win.
Use this for a method without a convenience function. Paths may include named or wildcard captures, which the handler reads from RouteContext.
Examples
Adding a custom method
router.route("PURGE", "/cache/:key", ~purge)
get
get(path: String, handler: Handler) -> Router
Appends a GET route. GET also supplies automatic HEAD fallback.
head
head(path: String, handler: Handler) -> Router
Appends an explicit HEAD route, overriding automatic GET fallback.
record ShutdownReport
Counts and elapsed time from graceful server shutdown.
Fields
record ServerOptions
Bounded HTTP server resources and default graceful-shutdown duration.
Fields
record PoolOptions
HTTP connection-pool bounds and idle lifetime.
Fields
record ClientOptions
Options owned by an explicit HTTP client.
Fields
poolPoolOptionsoptional
record ClientStatistics
Lifetime request/reuse counters plus current pooled connections.
Fields
record ClientCloseReport
Resources released by Client.close.
Fields
closedConnectionsInteger
type Client
The pooled HTTP client. An opaque handle over the connection pool that owns it; Client.open makes one and client.close releases it.
Methods
request
request(method: String, url: String, headers: Headers, body: Binary) -> Result<Response<Binary>, NetError>
Sends a buffered request. Redirects and generic retries are not implicit.
This keeps policy with the caller: inspect a redirect before following it, and retry only methods and failures your application knows are safe.
Examples
Sending JSON with an idempotency key
let headers = Headers.empty
.set("Content-Type", "application/json")
.set("Idempotency-Key", requestId)
client.request("POST", url, headers, JSON.stringify(order).to(Binary).try)
post
post(url: String, body: Binary) -> Result<Response<Binary>, NetError>
Sends a buffered binary POST request.
put
put(url: String, body: Binary) -> Result<Response<Binary>, NetError>
Sends a buffered binary PUT request.
patch
patch(url: String, body: Binary) -> Result<Response<Binary>, NetError>
Sends a buffered binary PATCH request.
delete
delete(url: String) -> Result<Response<Binary>, NetError>
Sends a DELETE request with an empty body.
head
head(url: String) -> Result<Response<Binary>, NetError>
Sends a HEAD request; the returned body is empty.
statistics
statistics : ClientStatistics
Reports current pool occupancy and lifetime request counters.
Returns current pool and lifetime request counters
Examples
Emitting client-pool diagnostics
let stats = client.statistics
IO.printLine("HTTP reuse: ${stats.reusedConnections}/${stats.requests}")
close
close : Result<ClientCloseReport, NetError>
Idempotently closes the client and every idle pooled connection.
Further requests fail with Closed; a second close is harmless.
module Net.HTTP.Headers
Construction and parsing of validated HTTP header collections.
empty constant
empty : Headers
Returns a field collection with no entries.
Examples
Building request headers immutably
Headers.empty
.add("Accept", "application/json")
.add("User-Agent", "inventory-sync/1.0")
from
from(entries: [(String, String)]) -> Result<Headers, NetError>
Validates header names and values without folding duplicates.
Duplicate fields stay in their original order. Invalid names and values containing line breaks are rejected instead of creating a malformed or injectable HTTP message.
Returns validated fields, or Parse
Examples
Forwarding an explicitly selected set of request headers
Headers.from([
("Accept", "application/json"),
("X-Request-ID", requestId)
]).try
parse
parse(text: String) -> Result<Headers, NetError>
Parses CRLF- or LF-separated header fields.
Use this at a protocol boundary when headers arrive as text. Application code normally builds them with from, add, and set.
Returns fields in source order, or Parse
Examples
Parsing headers captured from a diagnostic fixture
Headers.parse("Content-Type: text/plain\r\nX-Trace: abc\r\n").try
module Net.HTTP.Status
Validation for numeric HTTP status codes.
from
from(code: Integer) -> Result<Status, NetError>
Validates an HTTP status code.
Parameters
code- a status in
100..599
Returns the status, or Parse
Examples
Validating a configurable health-check success code
let code = ENV.get("HEALTH_STATUS").flatMap { |text| text.to(Integer) }.or(204)
let expected = Status.from(code).try
module Net.HTTP.Response
Buffered response constructors for route handlers.
binary
binary(status: Integer, body: Binary, headers: Headers) -> Response<Binary>
Builds a buffered binary response with validated headers.
Examples
Returning a downloaded file without decoding it as text
Response.binary(200, archive, Headers.empty.set("Content-Type", "application/zip"))
module Net.HTTP.Router
The empty starting point for an immutable route declaration chain.
build constant
Examples
+Router.build.get("/health", { |request, context| Response.text(200, "ok") })+
module Net.HTTP.Server
Starting, observing, and gracefully stopping HTTP servers.
start
start(endpoint: Net.Socket.TCP.Endpoint, router: Router, options: ServerOptions) -> Result<Running, NetError>
Starts a server with conservative defaults and returns immediately.
The returned handle owns the listener and active handlers. Use start when the process has other work to do; use serve for a foreground server whose main job is handling HTTP.
Examples
let router = Router.build.get("/health", do |request, context|
Response.text(200, "ok")
end)
let endpoint = Net.Socket.TCP.Endpoint.loopback(Net.Port.from(0).try)
let server = Server.start(endpoint, router).try
Server.stop(server).try
serve
serve(endpoint: Net.Socket.TCP.Endpoint, router: Router, options: ServerOptions) -> Result<Void, NetError>
Starts with defaults and blocks until the server stops.
stop
stop(server: Running, grace: Duration) -> Result<ShutdownReport, NetError>
Gracefully stops using the duration captured at start.
New requests stop being accepted while in-flight handlers get their grace period to finish. The report says how much work completed or was forced down during shutdown.
Examples
Shutting down from an application lifecycle hook
let report = Server.stop(server).try
IO.printLine("closed after ${report.completed} requests")
localAddress
localAddress(server: Running) -> Net.Socket.TCP.Endpoint
Returns the bound address, including an operating-system-assigned port.
Returns the bound address
Examples
Publishing the actual address of a test server
let endpoint = Server.localAddress(server)
IO.printLine("test server: http://${endpoint.host}:${endpoint.port.string}")
type Running
An opaque asynchronous HTTP server handle.
module Net.HTTP.Client
Constructors for explicitly owned, connection-pooling HTTP clients.
open
open : Result<Client, NetError>
open(options: ClientOptions) -> Result<Client, NetError>
Opens an explicit pooled client with conservative defaults.
Reuse one client for related requests so keep-alive connections and DNS work can be reused. Close it when the owning service shuts down.
Examples
Fetching several pages through one connection pool
let client = Client.open.try
let first = client.get("https://api.example.com/items?page=1").try
let second = client.get("https://api.example.com/items?page=2").try
client.close.try
module Net.HTTP.HTTP
Stateless HTTP convenience calls for scripts and occasional requests.
request
request : String -> String -> Headers -> Binary -> Result<Response<Binary>, NetError>
Sends one stateless buffered request with no redirect or hidden retry.
Each call owns a short-lived client. This is convenient for scripts and occasional requests; use Client for a service making repeated calls.
Examples
A one-off authenticated request in a command-line tool
let headers = Headers.empty.set("Authorization", "Bearer ${token}")
HTTP.request("GET", url, headers).try
get
get(url: String) -> Result<Response<Binary>, NetError>
Sends one stateless buffered GET.
Examples
+HTTP.get("https://example.test/").try+
delete
delete(url: String) -> Result<Response<Binary>, NetError>
Sends one stateless DELETE with an empty body.
head
head(url: String) -> Result<Response<Binary>, NetError>
Sends one stateless HEAD and returns an empty response body.
options
options(url: String) -> Result<Response<Binary>, NetError>
Sends one stateless OPTIONS request.
post
post(url: String, body: Binary) -> Result<Response<Binary>, NetError>
Sends one stateless buffered binary POST.
Submodules
Net.HTTP.WebSocketHigh-level RFC 6455 client messages. The runtime handles fragmentation and ping/pong frames; reconnect and heartbeat policies remain application-owned.