std/http
Types
ClientError
pub type ClientError =
| HttpsUnsupported
| InvalidUrl(String)
| TimedOut
| MalformedResponse(String)
| Closed
Why a client request failed before a response arrived.
ClientError.message
pub fn ClientError.message(self) -> String
Client
pub type Client = {
// Bounds each send and each response; connecting is bounded only by the OS.
pub mut timeoutMillis i64
// Responses larger than this fail instead of being buffered.
pub mut maxBodyBytes usize
// A response's status line and header fields, CRLFs included.
pub mut maxHeaderBytes usize
// private fields omitted
}
An HTTP/1.1 client over plain TCP. Resolving and connecting are direct-blocking, so they go through pool; reads and writes suspend the task instead.
Client.new
pub fn Client.new(n: net.Net, pool: task.BlockingPool) -> Client
Client.open
pub async fn Client.open(self, url: String) -> Session!
Opens a connection to the host and port of url (its path is ignored).
Client.send
pub async fn Client.send(self, url: String, req: Request) -> Response!
Opens a connection, sends req to url's path and closes it after the response.
Client.get
pub async fn Client.get(self, url: String) -> Response!
Client.post
pub async fn Client.post(self, url: String, contentType: String, body: Bytes) -> Response!
Client.postJson
pub async fn Client.postJson[T: json.Encode](self, url: String, value: T) -> Response!
Posts value encoded as JSON.
Session
pub type Session = resource {
// private fields omitted
}
One connection that can carry several requests in turn (keep-alive). A send that fails leaves it closed, since a late response could otherwise answer the next request.
Session.send
pub async fn Session.send(mut self, req: Request) -> Response!
Sends req (its target as given) and reads the whole response; a response that closes the connection leaves the session unusable.
Header
pub type Header = {
pub name String
pub value String
}
One header field as received or to be sent.
Headers
pub type Headers = {
// private fields omitted
}
Header fields in arrival order; names compare case-insensitively and a name may repeat.
Headers.new
pub fn Headers.new() -> Headers
Headers.add
pub fn Headers.add(mut self, name: String, value: String)
Appends a field after any earlier one with the same name.
Headers.set
pub fn Headers.set(mut self, name: String, value: String)
Replaces every field named name with a single one holding value.
Headers.remove
pub fn Headers.remove(mut self, name: String)
Drops every field named name.
Headers.get
pub fn Headers.get(self, name: String) -> String?
The first value of name.
Headers.all
pub fn Headers.all(self, name: String) -> Array[String]
Every value of name, in arrival order.
Headers.len
pub fn Headers.len(self) -> usize
Headers.entries
pub fn Headers.entries(self) -> Array[Header]
The fields in arrival order.
Failure
pub type Failure = {
pub status Int
pub text String
}
A handler failure that names the status to answer with; the server sends text as the body. Any other error a handler fails with is answered with 500 and handed to the server's log instead.
Failure.message
pub fn Failure.message(self) -> String
Param
pub type Param = {
pub name String
pub value String
}
A path parameter a Router matched, such as id in /users/{id}.
Request
pub type Request = {
pub method String
// The request-target as sent, path plus any `?query`.
pub target String
// The target before `?`, still percent-encoded.
pub path String
// The target after `?`, or "".
pub query String
pub mut headers Headers
pub mut body Bytes
// Filled by the Router; decoded from percent-encoding.
pub mut params Array[Param]
}
An HTTP request: what a handler receives on the server and what a Client sends.
Request.new
pub fn Request.new(method: String, target: String) -> Request
A request with no headers and an empty body.
Request.param
pub fn Request.param(self, name: String) -> String?
The path parameter name.
Request.header
pub fn Request.header(self, name: String) -> String?
The first value of the header name.
Request.queryParam
pub fn Request.queryParam(self, name: String) -> String?
The first name=value pair of the query string, percent-decoded with + read as a space.
Request.text
pub fn Request.text(self) -> String!
The body as UTF-8 text; invalid UTF-8 fails with a 400 Failure.
Request.json
pub fn Request.json[T: json.Decode](self) -> T!
Decodes the body as JSON into a T; a malformed or mismatched body fails with a 400 Failure.
Response
pub type Response = {
pub mut status Int
pub mut headers Headers
pub mut body Bytes
}
An HTTP response: what a handler returns and what a Client receives.
Response.new
pub fn Response.new(status: Int) -> Response
A response with no headers and an empty body.
Response.ofText
pub fn Response.ofText(status: Int, text: String) -> Response
A text/plain; charset=utf-8 response.
Response.ofJson
pub fn Response.ofJson[T: json.Encode](status: Int, value: T) -> Response!
An application/json response holding value encoded.
Response.header
pub fn Response.header(self, name: String) -> String?
The first value of the header name.
Response.text
pub fn Response.text(self) -> String!
The body as UTF-8 text.
Response.json
pub fn Response.json[T: json.Decode](self) -> T!
Decodes the body as JSON into a T.
Router
pub type Router = {
// private fields omitted
}
Routes by method and path pattern, built by chaining: Router.new().get("/users/{id}", show). A {name} segment matches one non-empty segment and is read back with Request.param.
Router.new
pub fn Router.new() -> Router
Router.handle
pub fn Router.handle(move self, method: String, pattern: String, handler: escaping fn(Request) -> Response!) -> Router
Adds a route; the first route registered for a matching method and path wins.
Router.get
pub fn Router.get(move self, pattern: String, handler: escaping fn(Request) -> Response!) -> Router
Router.post
pub fn Router.post(move self, pattern: String, handler: escaping fn(Request) -> Response!) -> Router
Router.put
pub fn Router.put(move self, pattern: String, handler: escaping fn(Request) -> Response!) -> Router
Router.delete
pub fn Router.delete(move self, pattern: String, handler: escaping fn(Request) -> Response!) -> Router
Router.use
pub fn Router.use(move self, middleware: escaping fn(escaping fn(Request) -> Response!) -> fn(Request) -> Response!) -> Router
Adds middleware around every request the router sees, unmatched ones included; the first one added is the outermost.
Router.handler
pub fn Router.handler(move self) -> fn(Request) -> Response!
The router as one handler: 404 when no pattern matches the path, 405 with an Allow header when one does but not for this method; HEAD falls back to GET.
Limits
pub type Limits = {
// Request line plus header fields, CRLFs included; past it the answer is 431.
pub mut maxHeaderBytes usize
// Header field count; past it the answer is 431.
pub mut maxHeaders usize
// Decoded body size; past it the answer is 413 and the connection closes.
pub mut maxBodyBytes usize
// From a request's first byte to its last; past it the answer is 408.
pub mut readTimeoutMillis i64
// How long a kept-alive connection may wait for its next request before it is closed.
pub mut idleTimeoutMillis i64
// How long one response may take to send.
pub mut writeTimeoutMillis i64
// Connections served at once, at least 1; further ones wait in the listener's backlog.
pub mut maxConnections usize
}
Bounds on what one connection may send and how long it may take.
Limits.defaults
pub fn Limits.defaults() -> Limits
8 KiB of head, 100 fields, 1 MiB of body, 10 s to read or write, 30 s idle, 1024 connections.
Server
pub type Server = {
pub mut limits Limits
// private fields omitted
}
An HTTP/1.1 server around one handler.
Server.new
pub fn Server.new(handler: escaping fn(Request) -> Response!, log: escaping fn(String) -> Void) -> Server
A server answering every request with handler. log receives one line for each handler error that is not a Failure (the client gets a bare 500) and for each failed accept; nothing else is logged.
Server.serve
pub async fn Server.serve(self, listener: net.Listener, stop: Shutdown) -> Void!
Serves each accepted connection on its own child task until stop is requested, then closes the listener and returns once every connection has finished its current exchange; cancelling abandons them at their next await.
Shutdown
pub type Shutdown = {
// private fields omitted
}
A shutdown request shared between a Server and whoever stops it; clones see the same request. It is a single-thread cell, so a task holding one stays on its executor's thread.
Shutdown.new
pub fn Shutdown.new() -> Shutdown
Shutdown.clone
pub fn Shutdown.clone(self) -> Shutdown
Shutdown.request
pub fn Shutdown.request(self)
Asks every server watching this Shutdown to stop accepting and to close each connection once its current exchange is done.
Shutdown.requested
pub fn Shutdown.requested(self) -> Bool
Functions
failure
pub fn failure(status: Int, text: String) -> Failure
A Failure answering with status and text.
reason
pub fn reason(status: Int) -> String
The standard reason phrase of a status code, or "" for an unregistered one.
percentDecode
pub fn percentDecode(text: String) -> String?
Decodes %XX escapes; None for a broken escape or a result that is not UTF-8.