A reply head: the status and the fields. The body is read through the connection, because it may be larger than anything worth holding at once.
status : Int32
fields : Array[Field]
pub fn Response::field(Self, String) -> String?
pub(all) struct Stream
One exchange on a connection, named by the connection rather than by the protocol underneath: on a connection that carries one exchange at a time it is 1, and on one that multiplexes it is whatever that connection gave out.
id : Int32
pub(open) trait Conn
The one contract a connection presents, whatever carries it: HTTP/1.1, HTTP/2, HTTP/3 or WebSocket. Code written against this runs on any of them; an implementation is all a new protocol needs.
An exchange is opened, the request body is sent through it, and the reply's head and body are read from it. A connection that carries one exchange at a time says so through is_ready, which a caller waits on before opening the next.
async fn open(Self, Request) -> Stream
Open an exchange on request, and send its head and whatever body came with it.
async fn send(Self, Stream, Bytes, end~ : Bool) -> Unit
Send more of the request's body; end marks the last of it. Only an exchange opened with Body::Streaming takes this.
async fn response(Self, Stream) -> Response
The reply's head, once the peer has sent it.
async fn read(Self, Stream) -> Bytes?
The next run of the reply's body, read as it arrives; None ends it.
fn trailers(Self, Stream) -> Array[Field]
The fields that came after the body, once read has ended it.
fn is_ready(Self) -> Bool
Whether another exchange can start on this connection now. False while one is in flight on a connection that carries them one at a time, and after it has ended.
fn kind(Self) -> String
The protocol the connection settled on, as ALPN names it: http/1.1, h2, h3.
async fn close(Self) -> Unit
End the connection, in whatever way the protocol under it asks for.
moonnet/adapt/h1
HTTP/1.1, RFC 9112.
pub fnclient(@tcp.Conn, String) -> Conn
A client over a connection that is already open to authority, the host[:port] the Host field carries.
An HTTP/3 client connection: one QUIC connection, a control stream carrying this side's settings, and a bidirectional stream for every exchange (RFC 9114 §6).
A WebSocket session over a connection. The exchange is the upgrade: open sends the handshake, response is the 101, and from then on read yields whole messages and send writes them.
sock : @tcp.Conn
scheme : String
host : String
mut target : String
key : String
stream : Int32
mut held : Bytes
reader : @moonbitstack/moonhttp/ws.Reader
mut opened : Bool
mut closed : Bool
mut code : Int32
mut why : String
mut head : @spec.Response?
pub async fn Conn::close(Self) -> Unit
pub fn Conn::close_code(Self) -> Int32
The close code and reason the peer gave, once the session has closed; 0 before.
pub fn Conn::close_reason(Self) -> String
The reason the peer gave with its close, empty when it gave none.
How long a TLS handshake may take, in milliseconds: asyncio's and hypercorn's 60 seconds. A peer that connects and never finishes holds a connection slot until then.
pub lethost : String
The address a server listens on when none is given: loopback only, as uvicorn and Starlette default to, so a development server is not reachable from the network by accident.
One TCP connection, in the clear or under TLS 1.3. It reads and writes through @io.Reader and @io.Writer either way, so a protocol driver serves both with the same code.
One task may read while another writes. Writes are serialised, so two tasks writing at once put whole messages on the wire, one after the other, and TLS records stay in sequence.
pub async fn Conn::write_reader(Self, &@io.Reader) -> Unit
type Listener
A bound, listening socket. Connections queue from the moment listen returns, so a caller can connect to it, or hand its port out, without racing the server.
The clock QUIC counts in, milliseconds since the epoch.
pub(all) struct Quic
A QUIC connection driven by one task: the client half of what moonquic states and this package puts on a datagram socket. Reading is a poll, because a connection that also carries control and QPACK streams cannot hand every arrival to one caller.
socket : Socket
to : @socket.Addr
client : @conn.Client
mut bi : UInt64
mut uni : UInt64
mut dead : Bool
seen : Map[UInt64, Bool]
pub fn Quic::alpn(Self) -> String?
The ALPN the handshake settled on.
pub fn Quic::close(Self) -> Unit
Close the socket the connection runs on.
pub fn Quic::ended(Self, UInt64) -> Bool
Whether the peer has ended stream, with every octet of it read.
pub fn Quic::open_bi(Self) -> UInt64
The next bidirectional stream this side opens: 0, 4, 8, … as RFC 9000 §2.1 numbers them.
The octets that arrived on stream since the last call; empty when none have.
pub fn Quic::write(Self, UInt64, Bytes, fin? : Bool) -> Unit
Put bytes on stream, and end it when fin.
pub(all) suberror QuicRefused
What a QUIC connection will not do.
Timeout
The handshake did not complete in the time this waited.
Broken(String)
The socket or the connection under it failed.
Closed
The connection is over.
pub(all) struct Socket
A datagram socket. One task may receive while others send; two tasks receiving at once would each take half the datagrams, so a connection that needs one reader keeps one.
sock : @socket.UdpServer
pub fn Socket::addr(Self) -> @socket.Addr
The address bound; with port 0 asked for, the port the system chose.
pub async fn Socket::send(Self, @socket.Addr, Bytes) -> Unit
moonnet/pool
Connections kept by host, port and ALPN.
pub letdefaults : Config
The presets: an idle connection lives half a minute, a key keeps eight, the pool holds sixty-four, a reused one is peeked at, and a caller waits five seconds for a slot. These are the values curl and Go's transport settle near; what matters more is that all five are named and can be changed.
pub(all) struct Config
How a pool behaves. Every one of these is a number a caller will want to change, so all of them are here rather than in the code.
idle : Int32
max_idle : Int32
max_total : Int32
liveness : Liveness
wait : Int32
pub(all) struct Idle
A connection in the pool and the moment it stops being worth reusing.
conn : @tcp.Conn
until : Int64
pub(all) struct Key
What makes two connections interchangeable: the host, the port, and the protocol ALPN settled on. A connection kept under one key is never handed out for another.
What a reused connection is asked before it is handed out again.
None_
Nothing: a connection that served an exchange is taken on trust until the next one fails, which is what most clients do.
Peek
A read that does not wait. A peer that has closed is dropped; one that has said something while idle keeps what it said for the next exchange.
pub(all) struct Pool
The connections kept for another exchange. A caller takes one with get and gives it back with put, or closes it and takes another next time; a connection that is not given back is not counted as idle and stays against max_total.
dial : async (Key) -> @tcp.Conn
config : Config
mut idle : Map[String, Array[Idle]]
mut total : Int32
changed : @cond_var.Cond
mut closed : Bool
pub fn Pool::close(Self) -> Unit
Close every idle connection and refuse further use.
A pool that opens a connection with dial when it has none to hand out.
pub fn Pool::put(Self, Key, @tcp.Conn) -> Unit
Put a connection back for the next exchange. A pool that is closed, or that already keeps max_idle for this key, closes it instead; either way it stops counting against max_total.
pub fn Pool::total(Self) -> Int32
How many connections the pool holds open, in use or idle.
pub(all) suberror Refused
What a pool will not do.
Busy
The pool is full and no slot came free in time.
Closed
The pool was closed.
Failed(String)
Opening a connection failed.
moonnet
The front door: one import for the connection, the datagram socket and the contract.