Standard library
std/http
HTTP/1.1: a server built on tasks, scopes and cancellation, and a small client.
HTTP/1.1: a server built on tasks, scopes and cancellation, and a small client. Plain HTTP only (no TLS).
struct Hello {
fn serve(self, req: http.Request) -> http.Response {
return http.text(200, "hello " + (req.param("name") ?? "world"))
}
}
fn main() ! io.Error {
let ln = try net.listen(":8080")
http.serve(ln, Hello{}, http.Options{})
}Every connection is a task in the server's scope, so cancelling the task
that runs serve cancels the requests in flight. Every request runs under a
deadline (Options.deadline): a handler still running then is cancelled and
the client gets 504. A client that hangs up cancels its request too: the
handler's blocking calls return early.
Types: struct Header, struct Request, struct Response, interface Handler, struct Options, struct Stats
Functions: findHeader, text, json, statusText, serve, serveCounting, request, get, post, decode, encode
Types
struct Header
pub struct Header {
pub name: String
pub value: String
}A header line. Names are matched without regard to case.
struct Request
pub struct Request {
pub method: String
// the path, without the query
pub path: String
// what follows `?` in the target, still percent-encoded
pub rawQuery: String = ""
pub headers: Vec[Header] = []
pub body: Vec[byte] = []
}A request, as a handler gets it: the whole body has been read (up to
Options.maxBody).
Request.header
pub fn header(self, name: str) -> ?StringThe value of header name (any case).
Request.param
pub fn param(self, name: str) -> ?StringA query parameter, decoded: "/search?q=a+b" has param("q") == "a b".
Request.segments
pub fn segments(self) -> Vec[String]The path's parts: "/todos/7" -> ["todos", "7"].
Request.text
pub fn text(self) -> StringThe body, as a string.
struct Response
pub struct Response {
pub status: int = 200
pub headers: Vec[Header] = []
pub body: Vec[byte] = []
}What a handler answers, and what the client gets back. Content-Length and Connection are set by the server; line breaks in header names and values become spaces.
Response.header
pub fn header(self, name: str) -> ?StringThe value of header name (any case).
Response.setHeader
pub fn setHeader(inout self, name: str, value: str)Adds a header.
Response.text
pub fn text(self) -> StringThe body, as a string.
interface Handler
pub interface Handler {
fn serve(self, req: Request) -> Response
}Answers requests. serve runs in a goroutine of its own for each
connection, under the deadline of Options.deadline; it is cancelled when
the deadline passes, the client hangs up or the server stops.
struct Options
pub struct Options {
// how long a handler may run
pub deadline: int = 30 * time.second
// the largest request body accepted
pub maxBody: int = 8 * 1024 * 1024
}How the server treats requests.
struct Stats
pub struct Stats {
pub served: int = 0
pub timedOut: int = 0
pub hungUp: int = 0
pub stopped: int = 0
pub rejected: int = 0
}What happened to the requests a server has handled (see serveCounting):
answered, stopped at the deadline (answered 504), abandoned by the client,
cancelled when the server stopped, or rejected as malformed or too large.
Functions
findHeader
pub fn findHeader(hs: []Header, name: str) -> ?StringThe value of header name (any case) in hs.
text
pub fn text(status: int, body: str) -> ResponseA plain-text response.
json
pub fn json(status: int, body: str) -> ResponseA JSON response; body is JSON text (see json.Value.encode).
statusText
pub fn statusText(status: int) -> strThe reason phrase for a status code: 404 -> "Not Found".
serve
pub fn serve[H: Handler + send](ln: net.Listener, h: H, opts: Options)Serves until the calling task is cancelled; then cancels the requests in flight and waits for them.
serveCounting
pub fn serveCounting[H: Handler + send](ln: net.Listener, h: H, opts: Options, stats: Mutex[Stats])Like serve, counting what happened to the requests in stats.
request
pub fn request(method: str, url: str, headers: []Header, body: []byte) -> Response ! io.ErrorSends a request and reads the whole response. url is
"http://host[:port]/path?query".
get
pub fn get(url: str) -> Response ! io.ErrorA GET request.
post
pub fn post(url: str, contentType: str, body: []byte) -> Response ! io.ErrorA POST request with a body of the given type.
decode
pub fn decode(s: str) -> ?StringPercent-decoding (and + as a space, as in query strings); none if malformed.
encode
pub fn encode(s: str) -> StringPercent-encoding of everything but letters, digits and -._~.