std/http
On this page
Index
- const
CONTINUE - const
SWITCHING_PROTOCOLS - const
PROCESSING - const
EARLY_HINTS - const
OK - const
CREATED - const
ACCEPTED - const
NON_AUTHORITATIVE_INFO - const
NO_CONTENT - const
RESET_CONTENT - const
PARTIAL_CONTENT - const
MULTI_STATUS - const
ALREADY_REPORTED - const
IM_USED - const
MULTIPLE_CHOICES - const
MOVED_PERMANENTLY - const
FOUND - const
SEE_OTHER - const
NOT_MODIFIED - const
USE_PROXY - const
TEMPORARY_REDIRECT - const
PERMANENT_REDIRECT - const
BAD_REQUEST - const
UNAUTHORIZED - const
PAYMENT_REQUIRED - const
FORBIDDEN - const
NOT_FOUND - const
METHOD_NOT_ALLOWED - const
NOT_ACCEPTABLE - const
PROXY_AUTH_REQUIRED - const
REQUEST_TIMEOUT - const
CONFLICT - const
GONE - const
LENGTH_REQUIRED - const
PRECONDITION_FAILED - const
REQUEST_ENTITY_TOO_LARGE - const
REQUEST_URI_TOO_LONG - const
UNSUPPORTED_MEDIA_TYPE - const
REQUESTED_RANGE_NOT_SATISFIABLE - const
EXPECTATION_FAILED - const
TEAPOT - const
MISDIRECTED_REQUEST - const
UNPROCESSABLE_ENTITY - const
LOCKED - const
FAILED_DEPENDENCY - const
TOO_EARLY - const
UPGRADE_REQUIRED - const
PRECONDITION_REQUIRED - const
TOO_MANY_REQUESTS - const
REQUEST_HEADER_FIELDS_TOO_LARGE - const
UNAVAILABLE_FOR_LEGAL_REASONS - const
INTERNAL_SERVER_ERROR - const
NOT_IMPLEMENTED - const
BAD_GATEWAY - const
SERVICE_UNAVAILABLE - const
GATEWAY_TIMEOUT - const
HTTP_VERSION_NOT_SUPPORTED - const
VARIANT_ALSO_NEGOTIATES - const
INSUFFICIENT_STORAGE - const
LOOP_DETECTED - const
NOT_EXTENDED - const
NETWORK_AUTHENTICATION_REQUIRED - type
Router- method
Router.handle - method
Router.handle_stream - method
Router.wrap - method
Router.mount - method
Router.not_found - method
Router.method_not_allowed - method
Router.call
- method
- type
Next - type
Status - type
StatusError - type
Request- method
Request.param - method
Request.param_opt - method
Request.param_int - method
Request.query - method
Request.query_all - method
Request.form - method
Request.multipart_form - method
Request.header - method
Request.json - method
Request.with_header - method
Request.with_timeout - method
Request.with_host - method
Request.with_expect_continue - method
Request.with_idle_timeout - method
Request.with_body_reader - method
Request.with_trailers - method
Request.header_values - method
Request.host - method
Request.tls - method
Request.tls_state - method
Request.raw_query - method
Request.escaped_path - method
Request.add_header - method
Request.client_ip - method
Request.with_value - method
Request.value - method
Request.cookie - method
Request.cookies - method
Request.with_cookie
- method
- type
ProxyHeader - type
TlsState - type
Cookie- method
Cookie.display
- method
- type
SameSite - type
CookieErr- method
CookieErr.display
- method
- type
Key- method
Key.name
- method
- type
Response- method
Response.with_trailer_names - method
Response.with_full_duplex - method
Response.with_header - method
Response.header - method
Response.header_values - method
Response.add_header - method
Response.with_cookie - method
Response.cookies - method
Response.text - method
Response.decode_json
- method
- type
BodyReader- method
BodyReader.read - method
BodyReader.read_all - method
BodyReader.multipart - method
BodyReader.trailers
- method
- type
PartReader- method
PartReader.next - method
PartReader.read
- method
- type
StreamPart- method
StreamPart.header_values
- method
- type
BodyWriter- method
BodyWriter.write - method
BodyWriter.flush - method
BodyWriter.set_trailer
- method
- type
PipeWriter- method
PipeWriter.write - method
PipeWriter.close - method
PipeWriter.close_with_error
- method
- type
Server- method
Server.serve - method
Server.addr - method
Server.with_tls - method
Server.with_client_auth - method
Server.with_read_timeout - method
Server.with_read_header_timeout - method
Server.with_idle_timeout - method
Server.with_max_header_bytes - method
Server.with_max_body - method
Server.with_protocols - method
Server.with_h2_config
- method
- type
Protocol - type
H2Config - type
TlsCert - type
TlsErr- method
TlsErr.display
- method
- type
HttpErr- method
HttpErr.display
- method
- type
Client- method
Client.get - method
Client.send - method
Client.post_json - method
Client.with_roots - method
Client.with_server_name - method
Client.with_verify_conn - method
Client.with_verify - method
Client.tls_options - method
Client.with_cert - method
Client.with_protocols - method
Client.with_h2_config - method
Client.open - method
Client.with_redirects
- method
- type
TlsOptions - type
ReverseProxy- method
ReverseProxy.with_rewrite - method
ReverseProxy.serve
- method
- type
ResponseHead - type
ClientStream- method
ClientStream.head - method
ClientStream.read - method
ClientStream.read_all - method
ClientStream.close - method
ClientStream.trailers
- method
- type
ClientErr- method
ClientErr.display
- method
- type
Url - type
UrlErr- method
UrlErr.display
- method
- fn
router - fn
serve_component - fn
parse_cookie - fn
parse_set_cookie - fn
key - fn
new_request - fn
json - fn
serve_content - fn
text - fn
empty - fn
redirect - fn
status_text - fn
error_page - fn
not_found - fn
error_html - fn
stream - fn
pipe - fn
server - fn
max_body - fn
tls_cert - fn
client - fn
reverse_proxy - fn
parse_url - fn
gzip_responses
Constants
CONTINUE
const CONTINUE: Status = Status(100)The codes Go’s net/http names (std.md 4).
SWITCHING_PROTOCOLS
const SWITCHING_PROTOCOLS: Status = Status(101)PROCESSING
const PROCESSING: Status = Status(102)EARLY_HINTS
const EARLY_HINTS: Status = Status(103)OK
const OK: Status = Status(200)CREATED
const CREATED: Status = Status(201)ACCEPTED
const ACCEPTED: Status = Status(202)NON_AUTHORITATIVE_INFO
const NON_AUTHORITATIVE_INFO: Status = Status(203)NO_CONTENT
const NO_CONTENT: Status = Status(204)RESET_CONTENT
const RESET_CONTENT: Status = Status(205)PARTIAL_CONTENT
const PARTIAL_CONTENT: Status = Status(206)MULTI_STATUS
const MULTI_STATUS: Status = Status(207)ALREADY_REPORTED
const ALREADY_REPORTED: Status = Status(208)IM_USED
const IM_USED: Status = Status(226)MULTIPLE_CHOICES
const MULTIPLE_CHOICES: Status = Status(300)MOVED_PERMANENTLY
const MOVED_PERMANENTLY: Status = Status(301)FOUND
const FOUND: Status = Status(302)SEE_OTHER
const SEE_OTHER: Status = Status(303)NOT_MODIFIED
const NOT_MODIFIED: Status = Status(304)USE_PROXY
const USE_PROXY: Status = Status(305)TEMPORARY_REDIRECT
const TEMPORARY_REDIRECT: Status = Status(307)PERMANENT_REDIRECT
const PERMANENT_REDIRECT: Status = Status(308)BAD_REQUEST
const BAD_REQUEST: Status = Status(400)UNAUTHORIZED
const UNAUTHORIZED: Status = Status(401)PAYMENT_REQUIRED
const PAYMENT_REQUIRED: Status = Status(402)FORBIDDEN
const FORBIDDEN: Status = Status(403)NOT_FOUND
const NOT_FOUND: Status = Status(404)METHOD_NOT_ALLOWED
const METHOD_NOT_ALLOWED: Status = Status(405)NOT_ACCEPTABLE
const NOT_ACCEPTABLE: Status = Status(406)PROXY_AUTH_REQUIRED
const PROXY_AUTH_REQUIRED: Status = Status(407)REQUEST_TIMEOUT
const REQUEST_TIMEOUT: Status = Status(408)CONFLICT
const CONFLICT: Status = Status(409)GONE
const GONE: Status = Status(410)LENGTH_REQUIRED
const LENGTH_REQUIRED: Status = Status(411)PRECONDITION_FAILED
const PRECONDITION_FAILED: Status = Status(412)REQUEST_ENTITY_TOO_LARGE
const REQUEST_ENTITY_TOO_LARGE: Status = Status(413)REQUEST_URI_TOO_LONG
const REQUEST_URI_TOO_LONG: Status = Status(414)UNSUPPORTED_MEDIA_TYPE
const UNSUPPORTED_MEDIA_TYPE: Status = Status(415)REQUESTED_RANGE_NOT_SATISFIABLE
const REQUESTED_RANGE_NOT_SATISFIABLE: Status = Status(416)EXPECTATION_FAILED
const EXPECTATION_FAILED: Status = Status(417)TEAPOT
const TEAPOT: Status = Status(418)MISDIRECTED_REQUEST
const MISDIRECTED_REQUEST: Status = Status(421)UNPROCESSABLE_ENTITY
const UNPROCESSABLE_ENTITY: Status = Status(422)LOCKED
const LOCKED: Status = Status(423)FAILED_DEPENDENCY
const FAILED_DEPENDENCY: Status = Status(424)TOO_EARLY
const TOO_EARLY: Status = Status(425)UPGRADE_REQUIRED
const UPGRADE_REQUIRED: Status = Status(426)PRECONDITION_REQUIRED
const PRECONDITION_REQUIRED: Status = Status(428)TOO_MANY_REQUESTS
const TOO_MANY_REQUESTS: Status = Status(429)REQUEST_HEADER_FIELDS_TOO_LARGE
const REQUEST_HEADER_FIELDS_TOO_LARGE: Status = Status(431)UNAVAILABLE_FOR_LEGAL_REASONS
const UNAVAILABLE_FOR_LEGAL_REASONS: Status = Status(451)INTERNAL_SERVER_ERROR
const INTERNAL_SERVER_ERROR: Status = Status(500)NOT_IMPLEMENTED
const NOT_IMPLEMENTED: Status = Status(501)BAD_GATEWAY
const BAD_GATEWAY: Status = Status(502)SERVICE_UNAVAILABLE
const SERVICE_UNAVAILABLE: Status = Status(503)GATEWAY_TIMEOUT
const GATEWAY_TIMEOUT: Status = Status(504)HTTP_VERSION_NOT_SUPPORTED
const HTTP_VERSION_NOT_SUPPORTED: Status = Status(505)VARIANT_ALSO_NEGOTIATES
const VARIANT_ALSO_NEGOTIATES: Status = Status(506)INSUFFICIENT_STORAGE
const INSUFFICIENT_STORAGE: Status = Status(507)LOOP_DETECTED
const LOOP_DETECTED: Status = Status(508)NOT_EXTENDED
const NOT_EXTENDED: Status = Status(510)NETWORK_AUTHENTICATION_REQUIRED
const NETWORK_AUTHENTICATION_REQUIRED: Status = Status(511)Types
Router
struct Router {}Router.handle
fn (var r: Router) handle[E: Error, fx: Effects](pattern: Str, h: fn(Request) -> Response ! E uses fx) uses fxRouter.handle_stream
fn (var r: Router) handle_stream[E: Error, fx: Effects](pattern: Str, h: fn(Request, BodyReader) -> Response ! E uses fx) uses fxA route whose handler reads the request body as a stream (decision 0310): the server calls h before reading the body; req.body is empty.
Router.wrap
fn (var r: Router) wrap[E: Error, fx: Effects](m: fn(Request, Next) -> Response ! E uses fx) uses fxRouter.mount
fn (var r: Router) mount(prefix: Str, sub: Router)Adds every route of sub under prefix, behind the middleware of sub
(std.md 4.1).
Router.not_found
fn (var r: Router) not_found[E: Error, fx: Effects](h: fn(Request) -> Response ! E uses fx) uses fxThe response of a request no route matches, in place of the 404 (std.md 4.1); a mounted router’s hook is not copied.
Router.method_not_allowed
fn (var r: Router) method_not_allowed[E: Error, fx: Effects](h: fn(Request) -> Response ! E uses fx) uses fxThe response of a request whose path a route matches with another method, in place of the 405 (std.md 4.1); it gets the Allow header when it lacks one.
Router.call
fn (r: Router) call(req: Request) -> ResponseNext
type Next = fn(Request) -> ResponseStatus
type Status struct(Int)An HTTP status code (decision 0269): a distinct integer type, so a status cannot be mixed up with another Int.
StatusError
interface StatusError {
fn status(self) -> Int
fn display(self) -> Str
}Request
struct Request {
method: Str
path: Str
url: Url
headers: Map[Str, Str]
body: Bytes
remote_ip: Str
}Request.param
fn (r: Request) param(name: Str) -> StrThe path parameter name of the matched route; faults if the route has no such segment (param_opt answers
None instead).
Request.param_opt
fn (r: Request) param_opt(name: Str) -> Str?The path parameter name, or None when the route has no such segment.
Request.param_int
fn (r: Request) param_int(name: Str) -> IntRequest.query
fn (r: Request) query(name: Str) -> Str?Request.query_all
fn (r: Request) query_all(name: Str) -> List[Str]Every value of name in the query, in order (decision 0279).
Request.form
fn (r: Request) form() -> url.Values ! url.EscapeErrThe body of an application/x-www-form-urlencoded POST, PUT, or
PATCH as Values; empty Values for any other request (decision 0279).
Request.multipart_form
fn (r: Request) multipart_form() -> multipart.Form ! multipart.MultipartErrThe body of a multipart/form-data request as a Form (Go’s
ParseMultipartForm with its 32 MB limit); MultipartErr request Content-Type isn't multipart/form-data or no multipart boundary param in Content-Type for any other (decision 0282).
Request.header
fn (r: Request) header(name: Str) -> Str?Request.json
fn (r: Request) json[T: Json]() -> T ! json.DecodeErrRequest.with_header
fn (r: Request) with_header(name: Str, value: Str) -> RequestRequest.with_timeout
fn (r: Request) with_timeout(d: Duration) -> RequestThe request with its own time limit in place of its client’s, for the whole exchange with the body (Go’s Client.Timeout); a client side builder (decision 0404).
Request.with_host
fn (r: Request) with_host(host: Str) -> RequestThe request sent with Host (HTTP/1.1) and :authority (HTTP/2) host in place of the URL’s (Go’s Request.Host); the connection and the TLS name stay the URL’s. "" is the URL’s host.
Request.with_expect_continue
fn (r: Request) with_expect_continue(timeout: Duration = 1s) -> RequestThe request with Expect: 100-continue (Go’s Transport.ExpectContinueTimeout,
default 1s): an HTTP/1.1 client sends the head, waits up to timeout for
the server’s 100 Continue, then sends the body; a final response
first (a 401, a 413) is the result and the body is never sent; other
1xx are skipped. A request without a body, and an HTTP/2 or
Client.open request, send as before.
Request.with_idle_timeout
fn (r: Request) with_idle_timeout(d: Duration) -> RequestThe limit for each read of an opened stream’s body in place of its client’s timeout; a client side builder (decision 0404).
Request.with_body_reader
fn (r: Request) with_body_reader(b: BodyReader) -> RequestThe request with its body read from b as it is sent (a handle_stream route’s body, decision 0404): chunked unless the header gives Content-Length, never sent twice (a 307 or 308 returns the 3xx).
Request.with_trailers
fn (r: Request) with_trailers(names: List[Str], f: fn() -> Map[Str, Str]) -> RequestThe request with trailers (Go’s Request.Trailer, decision 0433): names are declared in its head (an HTTP/2 server keeps only declared ones), f is asked once its body has been sent and its values for those names go after it; other names, and names Go forbids in a trailer, are dropped. An HTTP/1.1 body is then chunked.
Request.header_values
fn (r: Request) header_values(name: Str) -> List[Str]Every field of name, in order (decision 0288).
Request.host
fn (r: Request) host() -> StrGo’s Request.Host: the Host header as sent (host, or host:port;
HTTP/2’s :authority); url.host is the name alone. "" for a request
built as a struct literal (std.md 4.3).
Request.tls
fn (r: Request) tls() -> BoolWhether the request came over TLS (Go’s r.TLS != nil); url.scheme
is then “https”.
Request.tls_state
fn (r: Request) tls_state() -> TlsState?Go’s r.TLS (a tls.ConnectionState): what the connection’s handshake negotiated; None for a plain connection or a request built as a struct literal.
Request.raw_query
fn (r: Request) raw_query() -> StrGo’s URL.RawQuery: the query as sent, before any unescaping.
Request.escaped_path
fn (r: Request) escaped_path() -> StrGo’s URL.EscapedPath: the path as sent when it is a valid escaping of
path, else path escaped (std/url’s path_escape).
Request.add_header
fn (r: Request) add_header(name: Str, value: Str) -> RequestThe request with one more field of name.
Request.client_ip
fn (r: Request) client_ip(trusted: List[netip.Prefix] = [], header: ProxyHeader = ProxyHeader.XForwardedFor) -> netip.Addr?The client’s address behind trusted proxies (std.md 4.3): the peer
(remote_ip) when it is not inside a prefix of trusted, else the
rightmost address of header (every field of it, in order) that is not
inside one; None when an address does not parse.
Request.with_value
fn (r: Request) with_value[T](k: Key[T], v: T) -> RequestRequest.value
fn (r: Request) value[T](k: Key[T]) -> T?Request.cookie
fn (r: Request) cookie(name: Str) -> Cookie?The first cookie of that name in the Cookie fields (Go’s Request.Cookie, decision 0288).
Request.cookies
fn (r: Request) cookies() -> List[Cookie]Every cookie of the Cookie fields that parses (Go’s Request.Cookies).
Request.with_cookie
fn (r: Request) with_cookie(c: Cookie) -> RequestThe request with name=value appended to its Cookie field (Go’s Request.AddCookie).
ProxyHeader
enum ProxyHeader {
XForwardedFor
Forwarded
} derive DisplayThe header a server’s trusted proxies write the client chain to:
X-Forwarded-For: client, proxy1 or RFC 7239’s Forwarded: for=client, for=proxy1. Only that one is read: a proxy that writes one
passes a client’s own copy of the other through.
TlsState
struct TlsState {
version: Str
cipher_suite: Str
server_name: Str
resumed: Bool
peer_certificates: List[x509.Certificate]
verified_chains: List[List[x509.Certificate]]
}What a TLS connection’s handshake negotiated (std.md 4.3; Go’s tls.ConnectionState).
Cookie
struct Cookie {
name: Str
value: Str
quoted: Bool = false
path: Str = ""
domain: Str = ""
expires: Time? = None
max_age: Int = 0
secure: Bool = false
http_only: Bool = false
same_site: SameSite = SameSite.Default
partitioned: Bool = false
}An HTTP cookie (std.md 4.3, decision 0288; net/http’s Cookie).
Cookie.display
fn (c: Cookie) display() -> StrThe Set-Cookie value (Go’s Cookie.String); "" for a name that is not a token.
SameSite
enum SameSite {
Default
Lax
Strict
None
} derive DisplayCookieErr
struct CookieErr {
msg: Str
}CookieErr.display
fn (e: CookieErr) display() -> StrThe message (decision 0358).
Key
struct Key[T] {}A typed request value key (std.md 4.3).
Key.name
fn (k: Key[T]) name() -> StrResponse
struct Response {
status: Int
headers: Map[Str, Str]
body: Bytes
}Response.with_trailer_names
fn (r: Response) with_trailer_names(names: List[Str]) -> ResponseThe response declaring trailer names in its Trailer header (HTTP/1.1;
decision 0433); set_trailer sends a name whether declared or not.
Response.with_full_duplex
fn (r: Response) with_full_duplex() -> ResponseThe streamed response whose function may read the request’s body
while it writes (Go’s ResponseController.EnableFullDuplex, decision
0433): its head goes out at once, a 100 Continue before the first
read when asked. HTTP/1.1 only needs it; an HTTP/2 stream always is.
Response.with_header
fn (r: Response) with_header(name: Str, value: Str) -> ResponseResponse.header
fn (r: Response) header(name: Str) -> Str?Response.header_values
fn (r: Response) header_values(name: Str) -> List[Str]Every field of name, in order (decision 0288).
Response.add_header
fn (r: Response) add_header(name: Str, value: Str) -> ResponseThe response with one more field of name.
Response.with_cookie
fn (r: Response) with_cookie(c: Cookie) -> ResponseOne more Set-Cookie field (Go’s SetCookie); none for an invalid name.
Response.cookies
fn (r: Response) cookies() -> List[Cookie]Every Set-Cookie field that parses (Go’s Response.Cookies).
Response.text
fn (r: Response) text() -> Str?The body as text; None if it is not valid UTF-8 (std.md 4.3).
Response.decode_json
fn (r: Response) decode_json[T: Json]() -> T ! json.DecodeErrBodyReader
struct BodyReader {}The body of a request to a handle_stream route (decision 0310).
BodyReader.read
fn (b: BodyReader) read(max: Int = 32768) -> Bytes? ! IoErrThe next bytes of the body (at most max, at least 1), None at its end.
BodyReader.read_all
fn (b: BodyReader) read_all() -> Bytes ! IoErrThe rest of the body.
BodyReader.multipart
fn (b: BodyReader) multipart(req: Request) -> PartReader ! multipart.MultipartErrThe body as multipart/form-data parts, read as they arrive
(decision 0310 phase 3; Go’s Request.MultipartReader): MultipartErr
as Request.multipart_form’s for another Content-Type or no boundary.
BodyReader.trailers
fn (b: BodyReader) trailers() -> Map[Str, Str]The request’s trailers (Go’s Request.Trailer, decision 0433), names canonical; empty until read has returned None.
PartReader
struct PartReader {}A multipart body read part by part (Go’s multipart.Reader).
PartReader.next
fn (p: PartReader) next() -> StreamPart? ! multipart.MultipartErrThe next part, the open part’s unread data dropped (NextPart); None after the last part. An error sticks.
PartReader.read
fn (p: PartReader) read(max: Int = 32768) -> Bytes? ! multipart.MultipartErrThe open part’s next bytes (at most max, at least 1; decoded when quoted-printable, as Go’s NextPart), None at its end or before the first next.
StreamPart
struct StreamPart {
name: Str
filename: Str?
headers: Map[Str, Str]
}A part of a PartReader: multipart.Part’s fields but its data, which PartReader.read reads; headers holds each header’s first value.
StreamPart.header_values
fn (p: StreamPart) header_values(name: Str) -> List[Str]Every value of the part’s header name, in order (MIMEHeader’s values); [] when it has none.
BodyWriter
struct BodyWriter {}The body of a streamed response (std.md 4.3).
BodyWriter.write
fn (w: BodyWriter) write(data: Bytes) -> () ! IoErrBodyWriter.flush
fn (w: BodyWriter) flush() -> () ! IoErrBodyWriter.set_trailer
fn (w: BodyWriter) set_trailer(name: Str, value: Str)A trailer sent after the body (Go’s TrailerPrefix, decision 0433), the name made canonical; a name Go forbids in a trailer (Content-Length, Host, Trailer, …) is dropped. Not sent on a response with a Content-Length.
PipeWriter
struct PipeWriter {}The writing end of http.pipe.
PipeWriter.write
fn (w: PipeWriter) write(data: Bytes) -> () ! IoErrIo(“io: read/write on closed pipe”) once either end is closed.
PipeWriter.close
fn (w: PipeWriter) close()The reader’s next read is None (the body’s end).
PipeWriter.close_with_error
fn (w: PipeWriter) close_with_error(e: IoErr)The reader’s next read is Err(e) (Go’s CloseWithError).
Server
struct Server {}Server.serve
fn (s: Server) serve() -> () ! HttpErr uses net.listenServer.addr
fn (s: Server) addr() -> StrServer.with_tls
fn (s: Server) with_tls(certs: List[TlsCert]) -> ServerThe server with HTTPS (std.md 4.6): certs[0] unless SNI names another certificate’s host.
Server.with_client_auth
fn (s: Server) with_client_auth(mode: tls.ClientAuth, roots: tls.Roots? = None) -> ServerThe server asks a TLS client for its certificate (Go’s tls.Config.ClientAuth and ClientCAs; decision 0433): roots verify it, the system’s when None. A request’s tls_state has the client’s certificates and verified chains.
Server.with_read_timeout
fn (s: Server) with_read_timeout(d: Duration) -> ServerGo’s Server.ReadTimeout: the time a request’s head and body may take to arrive, from its first byte; a connection whose request is late closes without a reply, as net/http’s does; over TLS the handshake’s waits count too.
Server.with_read_header_timeout
fn (s: Server) with_read_header_timeout(d: Duration) -> ServerGo’s Server.ReadHeaderTimeout: the time the head alone may take.
Server.with_idle_timeout
fn (s: Server) with_idle_timeout(d: Duration) -> ServerGo’s Server.IdleTimeout: how long a kept alive connection waits for its next request’s first byte (the read timeout when 0).
Server.with_max_header_bytes
fn (s: Server) with_max_header_bytes(n: Int) -> ServerGo’s Server.MaxHeaderBytes (plus net/http’s 4096 bytes of slack): a
longer head is 431 Request Header Fields Too Large (1 MB when 0, as
Go’s DefaultMaxHeaderBytes).
Server.with_max_body
fn (s: Server) with_max_body(n: Int) -> ServerThe largest request body the server reads before a handler (64 MB when
0, XO_HTTP_MAX_BODY’s default); a longer one is 413 Content Too Large. A route that needs a smaller cap wraps max_body(n).
Server.with_protocols
fn (s: Server) with_protocols(p: Set[Protocol]) -> ServerThe server speaking the protocols of p (Go’s Server.Protocols; decision 0434): #{Http1, Http2} by default; UnencryptedHttp2 serves h2c with prior knowledge on a plain listener. serve fails on an empty set or a TLS server with neither Http1 nor Http2.
Server.with_h2_config
fn (s: Server) with_h2_config(c: H2Config) -> ServerThe server’s HTTP/2 settings (Go’s Server.HTTP2; decision 0434).
Protocol
enum Protocol {
Http1
Http2
UnencryptedHttp2
} derive DisplayThe protocols a server or client speaks (Go’s http.Protocols, decision 0434).
H2Config
struct H2Config {
max_concurrent_streams: Int = 0
max_read_frame_size: Int = 0
max_receive_buffer_per_connection: Int = 0
max_receive_buffer_per_stream: Int = 0
max_decoder_header_table_size: Int = 0
max_encoder_header_table_size: Int = 0
send_ping_timeout: Duration = 0s
ping_timeout: Duration = 0s
write_byte_timeout: Duration = 0s
}HTTP/2 settings (Go’s http.HTTP2Config, decision 0434); 0 is the default of each, and an out of range value is clamped as Go does.
TlsCert
type TlsCert = tls.TlsCertA certificate chain with its private key (std.md 4.6): std/tls’s (decision 0433).
TlsErr
struct TlsErr {
msg: Str
}TlsErr.display
fn (e: TlsErr) display() -> StrThe message (decision 0358).
HttpErr
enum HttpErr {
Io(msg: Str)
Canceled
}HttpErr.display
fn (e: HttpErr) display() -> StrMSG for an Io, canceled (decision 0358).
Client
struct Client {}Client.get
fn (c: Client) get(url: Str) -> Response ! ClientErr uses net.dialClient.send
fn (c: Client) send(req: Request) -> Response ! ClientErr uses net.dialClient.post_json
fn (c: Client) post_json[T: Json](url: Str, v: T) -> Response ! ClientErr uses net.dialClient.with_roots
fn (c: Client) with_roots(pem: Bytes) -> Client ! TlsErrThe client trusting the certificates of pem instead of the system’s roots for https (std.md 4.6).
Client.with_server_name
fn (c: Client) with_server_name(name: Str) -> ClientThe client’s name for the server (Go’s tls.Config.ServerName): sent as SNI and verified against the certificate in place of the URL’s host; "" keeps the URL’s. A client with one has its own connections (decision 0541).
Client.with_verify_conn
fn (c: Client) with_verify_conn(f: fn(List[x509.Certificate]) -> () ! Str) -> ClientThe client calling f with the server’s certificates (leaf first) after the TLS handshake and its verification, before any request byte is sent (Go’s tls.Config.VerifyConnection); Err(text) fails the connection with that text. It runs on every new connection, so a pinning check works with a self signed server. A client with one has its own connections.
Client.with_verify
fn (c: Client) with_verify(v: tls.Verify) -> ClientHow the client checks the server’s certificate for https (Go’s InsecureSkipVerify when Verify.None, with Verify.ChainOnly the chain without the name); the default is Verify.Full. UNSAFE alone: Verify.None accepts any certificate, so a request on such a client fails (“tls: Verify.None needs a verify_conn …”) unless with_verify_conn is set, which should pin the certificate (tls.pin_sha256, tls.pin_sha1). A client with one has its own connections.
Client.tls_options
fn (c: Client) tls_options() -> TlsOptionsClient.with_cert
fn (c: Client) with_cert(cert: TlsCert) -> ClientThe client presenting cert when an https server asks for a certificate (Go’s tls.Config.Certificates on a client; decision 0433).
Client.with_protocols
fn (c: Client) with_protocols(p: Set[Protocol]) -> ClientThe client speaking the protocols of p (Go’s Transport.Protocols; decision 0434): with UnencryptedHttp2 and not Http1, an http:// URL opens HTTP/2 with prior knowledge.
Client.with_h2_config
fn (c: Client) with_h2_config(cfg: H2Config) -> ClientThe client’s HTTP/2 settings (Go’s Transport.HTTP2; decision 0434).
Client.open
fn (c: Client) open(req: Request) -> ClientStream ! ClientErr uses net.dialThe request sent and the response’s head read; its body follows on the stream (redirects followed as send follows them).
Client.with_redirects
fn (c: Client) with_redirects(max: Int) -> ClientThe client following at most max redirects (10 by default); 0 returns a 3xx response as it came, its Location as the server sent it (Go’s ErrUseLastResponse; decision 0404).
TlsOptions
struct TlsOptions {
server_name: Str
verify_conn: Bool
custom_roots: Bool
client_cert: Bool
verify: tls.Verify
}What a client’s TLS settings are, for tests and diagnostics.
ReverseProxy
struct ReverseProxy {}ReverseProxy.with_rewrite
fn (p: ReverseProxy) with_rewrite(f: fn(Request, Request) -> Request) -> ReverseProxyThe proxy applying f(in, out) to each outgoing request out after its own rewrite, in being the request received (httputil’s Rewrite with ProxyRequest.In and Out).
ReverseProxy.serve
fn (p: ReverseProxy) serve(req: Request, body: BodyReader) -> Response uses net.dialForwards req, its body read from body, and returns the target’s response with its body streamed back.
ResponseHead
struct ResponseHead {
status: Int
headers: Map[Str, Str]
}A response’s status and header, without its body (decision 0404).
ClientStream
struct ClientStream {}A response whose body is read as it arrives (decision 0404): from Client.open, read with read or read_all and released with close (or when the last copy goes): a body read to its end gives its connection back to the client’s pool, any other is closed.
ClientStream.head
fn (s: ClientStream) head() -> ResponseHeadClientStream.read
fn (s: ClientStream) read(max: Int = 32768) -> Bytes? ! ClientErr uses net.dialThe next bytes of the body, at most max, None at its end; a body cut short is Protocol (unexpected EOF), never an end.
ClientStream.read_all
fn (s: ClientStream) read_all(max_size: Int = 1073741824) -> Bytes ! ClientErr uses net.dialThe rest of the body; Protocol past max_size bytes.
ClientStream.close
fn (s: ClientStream) close()Releases the stream’s connection; again does nothing.
ClientStream.trailers
fn (s: ClientStream) trailers() -> Map[Str, Str]The response’s trailers (Go’s Response.Trailer, decision 0433), names canonical; empty until read has returned None.
ClientErr
enum ClientErr {
InvalidUrl(msg: Str)
Connect(msg: Str)
Timeout
Protocol(msg: Str)
Canceled
}ClientErr.display
fn (e: ClientErr) display() -> Strinvalid URL: MSG, MSG for a Connect, request timed out, protocol error: MSG, canceled (decision 0358).
Url
struct Url {
scheme: Str
host: Str
port: Int?
path: Str
query: Map[Str, Str]
}UrlErr
struct UrlErr {
msg: Str
}UrlErr.display
fn (e: UrlErr) display() -> StrThe message (decision 0358).
Functions
router
fn router() -> Routerserve_component
fn serve_component(r: Router)Serves the request a wasi:http component was called with through r (decision 0447): main builds the router and calls this; faults off the wasm backend.
parse_cookie
fn parse_cookie(line: Str) -> List[Cookie] ! CookieErrThe cookies of a Cookie field’s value (Go’s ParseCookie).
parse_set_cookie
fn parse_set_cookie(line: Str) -> Cookie ! CookieErrThe cookie of a Set-Cookie field’s value (Go’s ParseSetCookie).
key
fn key[T](name: Str) -> Key[T]new_request
fn new_request(method: Str, url: Str, headers: Map[Str, Str] = {}, body: Bytes = b"") -> Requestjson
fn json[T: Json](status: Int, v: T) -> Responseserve_content
fn serve_content(req: Request, name: Str, modtime: Time?, content: Bytes, headers: Map[Str, Str] = {}) -> ResponseThe response net/http’s ServeContent writes for req from content (decision 0306): Range requests (206, or multipart/byteranges for several), the conditional requests against modtime and an ETag in headers (304, 412), 416 for a range outside the content, the Content-Type from headers, name’s extension, or the content, and Last-Modified, Accept-Ranges, Content-Length. headers are the fields a Go handler sets on its ResponseWriter before the call.
text
fn text(status: Int, s: Str) -> Responseempty
fn empty(status: Int) -> Responseredirect
fn redirect(req: Request, url: Str, status: Int) -> ResponseGo’s Redirect: a response of status with Location: url; a url with
no scheme and no host is resolved against req’s escaped path (Go’s
rules: the path’s directory, . and .. cleaned, a trailing slash
kept, the query kept apart), non ASCII bytes of the Location percent
encoded; a GET or HEAD gets text/html; charset=utf-8 and a GET the
body <a href="URL">Status Text</a>. on a line.
status_text
fn status_text(code: Int) -> StrThe text of an HTTP status code, as Go’s http.StatusText (Not Found for 404); empty for a code Go does not name.
error_page
fn error_page(status: Int, msg: Str) -> ResponseGo’s Error: text/plain; charset=utf-8, X-Content-Type-Options: nosniff, the body msg and a newline.
not_found
fn not_found() -> ResponseGo’s NotFound: error_page(404, “404 page not found”).
error_html
fn error_html(status: Int, title: Str, detail: Str) -> ResponseAn HTML error page: text/html (nosniff), the title in <title> and <h1>, the detail in <p>, both escaped (std.md 4.3).
stream
fn stream[fx: Effects](status: Int, f: fn(BodyWriter) -> () ! IoErr uses fx) -> Response uses fxpipe
fn pipe() -> (PipeWriter, BodyReader)A body written by one task while another sends it (Go’s io.Pipe, decision 0433): the reader goes to Request.with_body_reader, each write waits until the request has taken its bytes.
server
fn server(l: Listener, r: Router) -> Servermax_body
fn max_body(n: Int) -> fn(Request, Next) -> ResponseA middleware that answers 413 with Go’s MaxBytesReader text
(http: request body too large) for a body over n bytes (a streamed
body is capped at n as it is read).
tls_cert
fn tls_cert(cert_pem: Bytes, key_pem: Bytes) -> TlsCert ! TlsErrParses a PEM certificate chain and its PEM private key (std.md 4.6).
client
fn client(net: Net, timeout: Duration = 30s) -> Clientreverse_proxy
pub fn reverse_proxy(client: Client, target: Url) -> ReverseProxyA reverse proxy to target, for a handle_stream route:
r.handle_stream("/api/", fn(req, body) { p.serve(req, body) }). It forwards each request to
target (decision 0404, httputil.ReverseProxy with SetURL and
SetXForwarded): the target’s scheme and host, its path joined before
the request’s, the queries merged; hop-by-hop fields removed both
ways; X-Forwarded-For, -Host and -Proto set; rewrite applied last;
the body streamed both ways, redirects returned as they came. A
failure to reach the target is 502, a timeout 504.
parse_url
fn parse_url(s: Str) -> Url ! UrlErrgzip_responses
fn gzip_responses(min_size: Int = 1024, level: compress.Level = compress.Level.Default) -> fn(Request, Next) -> ResponseA middleware that compresses responses with gzip when the request
accepts it (std.md 4.7, decision 0305): r.wrap(http.gzip_responses()).