h1_connection (h1 v0.9.0)

View Source

HTTP/1.1 connection gen_statem.

Owns a single TCP or TLS socket and drives the h1_parse_erl parser in both client and server modes. Emits protocol events to the owner pid (or a per-stream handler if set) using a tuple shape identical to erlang_h2 / erlang_quic_h3 so callers can swap protocols:

{h1, Conn, connected} {h1, Conn, {request, StreamId, Method, Path, Headers}} % server {h1, Conn, {response, StreamId, Status, Headers}} % client {h1, Conn, {informational, StreamId, Status, Headers}} % 1xx {h1, Conn, {data, StreamId, Data, EndStream}} {h1, Conn, {trailers, StreamId, Trailers}} {h1, Conn, {upgrade, StreamId, Protocol, Headers}} % server {h1, Conn, {upgraded, StreamId, Protocol, Sock, Buf, Hs}} % client {h1, Conn, {stream_reset, StreamId, Reason}} {h1, Conn, {goaway, LastStreamId, Reason}} {h1, Conn, {closed, Reason}}

Keep-alive, client-side pipelining, Expect: 100-continue, trailers and Upgrade (101 Switching Protocols) are all handled here.

Summary

Functions

Server: reply 200 Connection Established to a classic HTTP/1.1 CONNECT and take ownership of the raw socket in one step. ExtraHeaders are written as-is; no Connection/Upgrade/framing headers are injected, so bytes after the terminating CRLF belong to the tunnel.

Server: reply to an upgrade request. Extra headers are added to the 101 response; Connection: upgrade + Upgrade: <token> are auto-added.

Abort a stream. Because H1 has no RST_STREAM equivalent, this advertises Connection: close and closes the socket once the current exchange is drained.

Server: emit a 100 Continue informational response.

Address and port of the connected peer, recorded when the connection process started.

Server: send a complete response (status, headers, body) in one socket write and end the stream.

As respond/5, with per-response options. early_response_drain overrides the listener's early-response drain budget for this response (see drain_budget_from_opts/1 for accepted forms).

Advertise Connection: close on the next response (server) or on the next request (client), then shut the socket.

Server: emit an interim (1xx) response, e.g. 103 Early Hints, before the final response. May be called multiple times per stream. 101 is rejected (that is the Upgrade path), as is any call after the final response headers went out, or to an HTTP/1.0 client (RFC 9110 §15.2 forbids 1xx to HTTP/1.0).

Client: send a request. Headers should not include Host/Content-Length (they're auto-added). Returns the assigned stream id.

Server: send a response header block. If Headers does not include Content-Length or Transfer-Encoding, the caller is expected to follow up with chunked send_data/4 + send_trailers/3 / send_data with end_stream=true.

Transport module for a socket. h1_connection infers it from the socket itself; h1_server and h1:serve_socket/2 need the same atom for their own close/transfer dispatch.

Client: send an Upgrade request and block until either 101 arrives (returning the raw socket) or a non-101 response is received.

Functions

accept_connect(Pid, StreamId, ExtraHeaders)

Server: reply 200 Connection Established to a classic HTTP/1.1 CONNECT and take ownership of the raw socket in one step. ExtraHeaders are written as-is; no Connection/Upgrade/framing headers are injected, so bytes after the terminating CRLF belong to the tunnel.

accept_connect(Pid, StreamId, ExtraHeaders, Timeout)

accept_upgrade(Pid, StreamId, ExtraHeaders)

Server: reply to an upgrade request. Extra headers are added to the 101 response; Connection: upgrade + Upgrade: <token> are auto-added.

activate(Pid)

callback_mode()

cancel_stream(Pid, StreamId)

Abort a stream. Because H1 has no RST_STREAM equivalent, this advertises Connection: close and closes the socket once the current exchange is drained.

cancel_stream(Pid, StreamId, Reason)

close(Pid)

code_change(OldVsn, State, Data, Extra)

continue(Pid, StreamId)

Server: emit a 100 Continue informational response.

controlling_process(Pid, NewOwner)

get_peer_settings(Pid)

get_settings(Pid)

handle_event(EventType, Msg, OtherState, State)

init(_)

peername(Pid)

Address and port of the connected peer, recorded when the connection process started.

respond(Pid, StreamId, Status, Headers, Body)

Server: send a complete response (status, headers, body) in one socket write and end the stream.

respond(Pid, StreamId, Status, Headers, Body, Opts)

As respond/5, with per-response options. early_response_drain overrides the listener's early-response drain budget for this response (see drain_budget_from_opts/1 for accepted forms).

send_data(Pid, StreamId, Data)

send_data(Pid, StreamId, Data, EndStream)

send_goaway(Pid)

Advertise Connection: close on the next response (server) or on the next request (client), then shut the socket.

send_goaway(Pid, Reason)

send_informational(Pid, StreamId, Status, Headers)

Server: emit an interim (1xx) response, e.g. 103 Early Hints, before the final response. May be called multiple times per stream. 101 is rejected (that is the Upgrade path), as is any call after the final response headers went out, or to an HTTP/1.0 client (RFC 9110 §15.2 forbids 1xx to HTTP/1.0).

send_request(Pid, Method, Path, Headers, Opts)

Client: send a request. Headers should not include Host/Content-Length (they're auto-added). Returns the assigned stream id.

send_request_with_body(Pid, Method, Path, Headers, Body)

send_response(Pid, StreamId, Status, Headers)

Server: send a response header block. If Headers does not include Content-Length or Transfer-Encoding, the caller is expected to follow up with chunked send_data/4 + send_trailers/3 / send_data with end_stream=true.

send_trailers(Pid, StreamId, Trailers)

set_pipeline(Pid, Enabled)

set_stream_handler(Pid, StreamId, Handler)

set_stream_handler(Pid, StreamId, Handler, Opts)

start_link(_, Socket, Opts)

start_link(Mode, Socket, Owner, Opts)

terminate(Reason, State, _)

transport_of(Socket)

-spec transport_of(term()) -> gen_tcp | ssl.

Transport module for a socket. h1_connection infers it from the socket itself; h1_server and h1:serve_socket/2 need the same atom for their own close/transfer dispatch.

unset_stream_handler(Pid, StreamId)

upgrade(Pid, Protocol, Headers)

Client: send an Upgrade request and block until either 101 arrives (returning the raw socket) or a non-101 response is received.

upgrade(Pid, Protocol, Headers, Timeout)

wait_connected(Pid)

wait_connected(Pid, Timeout)