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
-
NoActiveRequestNo request body context:
read_bodywas called outside an active HTTP request. A programming error. -
BodyUnavailableAn 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.
-
BodyReadTimeoutNo bytes arrived within
body_read_timeout_ms. -
RequestDeadlineExceededThe request ran past
request_timeout_msbefore 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.ipdoes).Noneon a plain HTTP request, which nothing has resolved yet.
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.
0binds an OS-assigned free port; read it back withget_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.
0kills 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(bytes_tree.BytesTree)Bytes response body wrapping a BytesTree.
-
File(path: String, offset: Int, length: Int)lengthbytes of the file atpath, starting at byteoffset. The listener writes them withfile:sendfile, so they never enter the BEAM heap. Content-Length islength. 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).
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.
-
TcpClosedTCP 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 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.