APIHttp.Server

Http.Server

A concurrent HTTP/1.1 server.

serve accepts connections with a pool of tasks and answers each request with a handler. A connection serves consecutive requests while each body was read to its end and neither side asked to close. Invalid request framing gets its error status and closes the connection; so does a response that fails its checks (500), and a body that fails after its head was written leaves the response incomplete and closes the connection.

Config

type Config =    { port : Int    , workers : Int    , requestLineLimit : Int    , headerLimit : Int    , bodyLimit : Int    , headerDeadlineMs : Int    , bodyDeadlineMs : Int    , writeDeadlineMs : Int    , shutdownGraceMs : Int    }Source

How serve listens and what it allows. defaultConfig fills in limits.

Fields

port

port : IntSource

The port to listen on, at every address.

workers

workers : IntSource

How many connections are served at once.

requestLineLimit

requestLineLimit : IntSource

The longest request line, in bytes, before 414.

headerLimit

headerLimit : IntSource

The largest header block, in bytes, before 431.

bodyLimit

bodyLimit : IntSource

The largest body, in bytes, before 413.

headerDeadlineMs

headerDeadlineMs : IntSource

How long reading a request’s head may take, in milliseconds.

bodyDeadlineMs

bodyDeadlineMs : IntSource

How long reading a request’s body may take, in milliseconds.

writeDeadlineMs

writeDeadlineMs : IntSource

How long writing a response may take, in milliseconds.

shutdownGraceMs

shutdownGraceMs : IntSource

How long stopping waits for active connections before cancelling them, in milliseconds.

Request

type Request e =    { method : String    , target : String    , version : Version    , headers : List Header    , body : Reader e    }Source

A request whose body reads perform e.

Fields

method

method : StringSource

The method, such as "GET".

target

target : StringSource

The raw request target, query included; Http.Server.Route.path extracts the path.

version

version : VersionSource

The protocol version.

headers

headers : List HeaderSource

The header fields in order.

body

body : Reader eSource

The body, framed to its declared length or chunks.

Response

type Response e =    { status : Int    , headers : List Header    , body : Body e    }Source

A response whose body writes perform e. Its status is final, 200 to 599 except 101, and its headers may not set Content-Length or Transfer-Encoding, which the server supplies from the body.

Fields

status

status : IntSource

The status code.

headers

headers : List HeaderSource

The header fields: names must be tokens, and values cannot hold control characters other than tab.

body

body : Body eSource

The body. 204 and 304 responses cannot carry one.

defaultConfig

defaultConfig : Int -> ConfigSource

The configuration for port: 64 workers, 8 KiB request lines, 64 KiB header blocks, 16 MiB bodies, 10 s to read a head, 30 s to read a body or write a response, and 5 s of shutdown grace.

import Http.Server

(Http.Server.defaultConfig 8080).workers == 64

serve

serve : Config -> Channel () -> (Request {Protocol, #s} ->{Protocol, #s} Response {Protocol, #s}) ->{Fail Error, Async, Network} ()Source

Serves handler on config.port until a value arrives on stop, then closes the listener, waits up to shutdownGraceMs for active connections, and cancels the rest, closing their sockets. Handlers and their bodies may raise Protocol: before the head is written the server answers with the error’s status, and afterwards it closes the connection, so Http.Server.Route.dispatch and Http.abortBody need no handler of their own. A handler of type Request e ->{e} Response e also fits. Handle application errors inside the handler. Connection failures are recovered inside workers and do not stop unrelated connections. Fatal accept errors trigger coordinated shutdown through the server’s event channel; serve raises the selected Net error in the caller after its workers are joined.

serveRequest

serveRequest : Int -> Int -> Int -> Reader e -> Writer e -> (Request {Protocol, #s} ->{Protocol, #s} Response {Protocol, #s}) ->{e} Maybe BoolSource

Parses and answers one request over input and output, with separate request-line, header, and body limits. Answers Nothing at a clean end of input, or Just whether the connection can serve another request: the response succeeded, the request body was consumed, and neither side asked to close. A response that reads the request body is consumed within its request scope.

Handles Protocol like serve: failures before a response get their error status, invalid response declarations get 500, and a body failure after the head leaves the response incomplete. Other effects propagate.

withRequest

withRequest : Int -> Int -> Int -> Reader e -> (Request {#s} ->{#s} a) ->{Protocol, e} Maybe (a, Bool)Source

Parses one request from reader and runs action with it, answering Nothing at a clean end of input, or Just the result and whether the body was read to its end. Request lines, header blocks, and bodies have separate byte limits. The parser requires an HTTP/1.1 request line and one Host field, and accepts one Content-Length or Transfer-Encoding: chunked; anything else raises Http.Protocol.invalid. Chunk trailers count against the header limit, and a fixed-length body that ends early fails with Malformed when the consumer reads past what arrived. A response whose body reads the request must be written inside action.

writeResponse

writeResponse : String -> Writer {Protocol, e} -> Response {Protocol, e} ->{Protocol, e} ()Source

Checks a response and writes it as the answer to a request with method. The server supplies Content-Length for empty, byte, and sized bodies and chunked encoding for streams; a HEAD request gets only the head. Every check runs before the first byte is written. A HEAD response includes a sized body’s length but runs no body.