brazier/transport/server

Types

Why read_body returned no bytes. After any of these but NoActiveRequest and ReadPastBody the body is marked failed: the connection answers and closes, because the rest of the body can no longer be found in the stream.

pub type BodyReadError {
  NoActiveRequest
  BodyUnavailable
  ReadPastBody(requested: Int, remaining: Int)
  BodyReadTimeout
  RequestDeadlineExceeded
  SocketFailed(reason: String)
}

Constructors

  • NoActiveRequest

    No request body context: read_body was called outside an active HTTP request. A programming error.

  • BodyUnavailable

    An earlier read of this body failed.

  • ReadPastBody(requested: Int, remaining: Int)

    The read asked for a negative count or for more bytes than remain of the declared Content-Length. A programming error.

  • BodyReadTimeout

    No bytes arrived within body_read_timeout_ms.

  • RequestDeadlineExceeded

    The request ran past request_timeout_ms before the body arrived.

  • SocketFailed(reason: String)

    The socket failed: the peer closed it or reset it.

Connection type — used as the body parameter for gleam_http Request. Carries the socket reference so handlers can read the request body.

pub type Connection {
  Connection(
    socket: Socket,
    resolved: option.Option(ip.Resolved),
  )
}

Constructors

  • Connection(socket: Socket, resolved: option.Option(ip.Resolved))

    Arguments

    resolved

    The upgrade’s one resolution of the client (address and scheme behind the trusted proxies). A WebSocket upgrade resolves its client once, for the per-IP cap and the Origin check, and sets this before the middleware gate runs; every gate on that request must reuse it rather than parse the forwarding header again (client.ip does). None on a plain HTTP request, which nothing has resolved yet.

A running listener.

pub opaque type Listener

Options for starting a listener.

pub type ListenerOptions {
  ListenerOptions(
    port: Int,
    acceptors: Int,
    backlog: Int,
    max_connections: Int,
    max_connections_per_ip: Int,
    trusted_proxies: List(String),
    send_timeout_ms: Int,
    drain_timeout_ms: Int,
  )
}

Constructors

  • ListenerOptions(
      port: Int,
      acceptors: Int,
      backlog: Int,
      max_connections: Int,
      max_connections_per_ip: Int,
      trusted_proxies: List(String),
      send_timeout_ms: Int,
      drain_timeout_ms: Int,
    )

    Arguments

    port

    Port to bind. 0 binds an OS-assigned free port; read it back with get_port.

    acceptors

    Number of acceptor processes.

    backlog

    Listen backlog.

    max_connections

    Maximum live connections on this listener. Further connections are answered with 503 and closed by the acceptor.

    max_connections_per_ip

    Maximum live connections from one peer IP.

    trusted_proxies

    Peers in these networks (reverse proxies) are exempt from the per-IP cap, because every client behind them shares their address.

    send_timeout_ms

    Socket send timeout. A peer that stops reading is disconnected instead of blocking its handler forever.

    drain_timeout_ms

    How long a stopping listener waits for its connections to finish before killing them, in milliseconds. 0 kills them at once.

Response body type.

Reference: mist’s ResponseData (Bytes and File), Plug’s send_file/5.

pub type ResponseBody {
  Bytes(bytes_tree.BytesTree)
  File(path: String, offset: Int, length: Int)
}

Constructors

  • Bytes response body wrapping a BytesTree.

  • File(path: String, offset: Int, length: Int)

    length bytes of the file at path, starting at byte offset. The listener writes them with file:sendfile, so they never enter the BEAM heap. Content-Length is length. If the file holds fewer bytes when it is sent, the response is cut short and the connection closed. Static files are served this way (brazier/static).

Opaque socket type wrapping an Erlang gen_tcp socket (port).

pub type Socket

TCP message classification — used to decode raw Erlang {tcp,…} messages.

pub type TcpMsg {
  TcpData(BitArray)
  TcpClosed
  TcpError(String)
}

Constructors

  • TcpData(BitArray)

    TCP data received from the socket.

  • TcpClosed

    TCP connection was closed by the peer.

  • TcpError(String)

    TCP error occurred.

Values

pub fn accept(listen_socket: Socket) -> Result(Socket, String)

Accept a connection on a listening socket (blocks until connection arrives).

pub fn classify_tcp_message(
  raw: dynamic.Dynamic,
) -> Result(TcpMsg, Nil)

Classify a raw Erlang message into a TcpMsg. Used with process.selecting_anything to decode {tcp,…} messages.

pub fn close(socket: Socket) -> Nil

Close a socket.

pub fn controlling_process(
  socket: Socket,
  pid: process.Pid,
) -> Result(Nil, String)

Transfer socket ownership to another process.

pub fn default_listener_options(port: Int) -> ListenerOptions

Default listener options for a port.

pub fn describe_body_read_error(error: BodyReadError) -> String

A one-line description of a BodyReadError, for logs and replies.

pub fn get_connection_count(listener: Listener) -> Int

Number of live connections on this listener.

pub fn get_connection_count_for_ip(
  listener: Listener,
  address: String,
) -> Result(Int, Nil)

Number of live connections from one peer IP (textual address).

pub fn get_connection_owner(
  listener: Listener,
) -> Result(process.Pid, Nil)

Pid of the listener’s current connection owner process.

pub fn get_connection_pids(
  listener: Listener,
) -> List(process.Pid)

Pids of the live connection handler processes.

pub fn get_local_port(socket: Socket) -> Result(Int, String)

The local port a connected socket was accepted on. Equals the listener’s bound port, which differs from the configured port when the listener was started on port 0.

pub fn get_peer_ip(socket: Socket) -> Result(String, String)

The socket peer’s IP address as a normalized string (IPv4-mapped IPv6 addresses are reported as plain IPv4).

pub fn get_port(listener: Listener) -> Int

The port the listener is bound to (the OS-assigned one for port 0).

pub fn get_supervisor(listener: Listener) -> process.Pid

The listener’s supervisor pid.

pub fn get_ws_connection_count_for_ip(
  listener: Listener,
  address: String,
) -> Int

Number of live WebSockets on this listener from one client IP: the address the per-IP WebSocket cap counts, which behind a trusted proxy is the forwarded client.

pub fn listen(port: Int, backlog: Int) -> Result(Socket, String)

Listen on a port with the given backlog size.

pub fn read_body(
  socket: Socket,
  length: Int,
) -> Result(BitArray, BodyReadError)

Read exactly length bytes of the current request’s body.

Reads go through the per-request body context registered by the connection loop: a read can never go past the declared Content-Length, never wait longer than the body read timeout or the total request deadline, and fails loudly when called outside an active request. Application code should normally use brazier/transport/http.read_body.

pub fn release(listener: Listener) -> Bool

Forget the remembered bound port of a listener that has stopped for good. A restarted listener rebinds the port it bound first (so a port-0 listener keeps its port across restarts); once its parent tree has been stopped, that memory must go. stop calls this itself, and a tree that exits with nothing left to restart it, and no holder (hold), forgets its port on its own. Returns whether a port was remembered: a caller that knows the listener ran warns when it was not.

pub fn send_bytes(
  socket: Socket,
  data: BitArray,
) -> Result(Nil, String)

Send raw bytes over a socket.

pub fn send_close_frame(socket: Socket) -> Result(Nil, String)

Send a WebSocket close frame.

pub fn send_text_frame(
  socket: Socket,
  text: String,
) -> Result(Nil, String)

Send a WebSocket text frame.

pub fn set_active_once(socket: Socket) -> Nil

Set socket to {active, once} mode — delivers one {tcp,…} message.

pub fn start(
  options: ListenerOptions,
  handler: fn(Socket) -> Nil,
) -> Result(Listener, String)

Start a supervised listener. The listener’s supervisor is linked to the calling process.

A listener that cannot start is an Error naming the cause, such as "cannot listen on port 4000: eaddrinuse (address already in use)"; nothing of it is left running and the caller gets no exit signal, so a caller that does not trap exits survives it.

pub fn stop(listener: Listener) -> Nil

Stop a listener started with start: closes the listen socket, shuts down every live connection, and forgets the remembered port.

pub fn supervised(
  options: ListenerOptions,
  handler: fn(Socket) -> Nil,
) -> Result(supervision.ChildSpecification(Listener), String)

A child specification for embedding a listener in another supervision tree (for example the application supervisor). A start that fails is InitFailed naming the cause, as start’s error does.

The parent supervisor holds the listener’s remembered entries (its connection owner and bound port) for as long as the parent runs, so a terminated listener restarted with supervisor:restart_child rebinds its port. A listener removed from a running parent for good (supervisor:terminate_child then supervisor:delete_child) must be released with release, or its entries stay until the parent exits: nothing tells the listener its spec was deleted. Ranch’s stop_listener likewise cleans up a listener’s options itself between the terminate and the delete.

✨ Search Document