Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

http.stream

import http.stream

http lifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelled http.stream.* needs import http.stream.

The transport underneath everything else: a byte stream with buffering, timeouts and optional TLS.

Connection is what both the client and the server read and write through, so the protocol layers above never have to know whether they are talking over TCP or over TLS.

Functions

is_timeout_error()

http.stream.is_timeout_error(message) -> bool

Whether a transport error message describes a timeout (or a would-block, which a socket with a receive timeout reports as the same condition) rather than a genuine failure.

Parameters

  • message (string)

Returns bool

connect()

http.stream.connect(host: string, port: int, options: ?dict) -> Connection

Opens a connection to host on port, optionally wrapping it in TLS.

Timeouts are applied to the raw socket before any TLS handshake runs, which is both the only place they can be applied and what keeps a stalled handshake from hanging forever.

Parameters

  • host (string)
  • port (int)
  • options (?dict) — secure (bool), tls_config (a net.tls.TlsConfig), server_name (the SNI/verification name, defaulting to host), connect_timeout, read_timeout and write_timeout (all milliseconds)

Returns Connection

Raises ConnectionError, TimeoutError

tunnel()

http.stream.tunnel(proxy: dict, host: string, port: int, options: ?dict) -> Connection

Opens a connection to host:port through an HTTP proxy’s CONNECT tunnel, running a TLS handshake with host inside it when secure is set.

The proxy sees only where the tunnel goes. Everything sent through it after the handshake is between this end and host, encrypted, and the certificate checked is host’s own.

Parameters

  • proxy (dict) — host and port of an HTTP proxy, and authorization, the Proxy-Authorization value to send, or nil.
  • host (string)
  • port (int)
  • options (?dict) — as connect() takes them.

Returns Connection

Raises ConnectionError when the proxy cannot be reached or refuses the tunnel, or the handshake through it fails

accept()

http.stream.accept(client, options: ?dict) -> Connection

Turns a freshly accepted TcpStream into a Connection, running a server-side TLS handshake first when tls_config is given.

Parameters

  • client (TcpStream) — the stream TcpStream.accept() returned
  • options (?dict) — tls_config (a net.tls.TlsConfig; when present the connection is wrapped in TLS), read_timeout and write_timeout (milliseconds)

Returns Connection

Raises ConnectionError if the TLS handshake fails

Classes

Connection

class http.Connection

A buffered, message-oriented view of a connected socket.

HTTP/1.1 is parsed a line at a time and then a body at a time, and HTTP/2 a frame at a time; both want to read a few bytes without paying for a syscall each time, and to write a head made of many small pieces as one write. Connection sits between the protocol code and either a plain net.TcpStream or a net.tls.TlsStream and provides exactly that, plus the peer information the transports stop reporting once TLS has consumed the underlying socket.

Instances are created by connect() and accept() below, or by from_transport() when the socket already exists.

  • printable — has a @to_string(), so echo and print() show something useful

Fields

FieldTypeDescription
peer_address?SocketAddrThe remote peer’s address, captured before any TLS wrap consumed the underlying socket.
local_address?SocketAddrThis side’s address.
secureboolWhether the connection is TLS-protected.
alpn?stringThe ALPN protocol negotiated during the TLS handshake ('h2', 'http/1.1'), or nil on a plaintext…

Constructor

http.Connection(transport, peer, local)

Wraps an already-connected transport.

Parameters

  • transport (TcpStream|TlsStream)
  • peer (?SocketAddr) — the peer address, which a TlsStream can no longer report on its own
  • local (?SocketAddr)

Connection.transport()

http.Connection.transport() -> TcpStream|TlsStream

The underlying TcpStream or TlsStream. Needed by the protocol upgrade paths (WebSocket, HTTP/2) that take a connection over wholesale.

Returns TcpStream|TlsStream

Connection.peer_certificate()

http.Connection.peer_certificate() -> ?PeerCertificate

The peer’s certificate on a TLS connection, or nil on a plaintext one or when the peer presented none.

Returns ?PeerCertificate

Connection.buffered()

http.Connection.buffered() -> number

How many bytes are already buffered and available without touching the socket.

Returns number

Connection.bytes_read()

http.Connection.bytes_read() -> number

How many bytes have been read off the transport over this connection’s whole life.

Returns number

Connection.is_eof()

http.Connection.is_eof() -> bool

Whether the peer has closed its side and the buffer is drained.

Returns bool

Connection.is_closed()

http.Connection.is_closed() -> bool

Whether close() has been called on this connection.

Returns bool

Connection.read_line()

http.Connection.read_line(limit)

Reads one CRLF-terminated line and returns it as a string with the terminator removed.

A bare LF is accepted as a line terminator as well. RFC 9112 §2.2 permits a recipient to do so, and enough real clients send one that refusing would break them; a bare CR, on the other hand, is left in the data where it belongs.

Parameters

  • limit (?number) — the longest line to tolerate, in bytes; defaults to 8192

Returns — ?string: the line, or nil at a clean EOF before any bytes of a line arrived

Raises TooLargeError if the line exceeds limit

Raises ProtocolError if EOF arrives mid-line

Raises TimeoutError, ConnectionError

Connection.read_exactly()

http.Connection.read_exactly(length: number) -> bytes

Reads exactly length bytes.

Parameters

  • length (number)

Returns bytes

Raises ProtocolError if EOF arrives first

Raises TimeoutError, ConnectionError

Connection.read_some()

http.Connection.read_some(length: number)

Reads whatever is available, up to length bytes, blocking only until the first byte arrives.

Parameters

  • length (number)

Returns — bytes: empty at EOF

Raises TimeoutError, ConnectionError

Connection.read_to_eof()

http.Connection.read_to_eof(limit) -> bytes

Reads until the peer closes its write half.

This is the framing of last resort - a response with neither Content-Length nor chunked encoding is delimited by the close itself (RFC 9112 §6.3). limit bounds how much will be accumulated so a peer that never closes cannot exhaust memory.

Parameters

  • limit (?number) — the most to accept, in bytes; nil for no limit

Returns bytes

Raises TooLargeError if limit is exceeded

Connection.discard()

http.Connection.discard(length: number)

Discards exactly length bytes without materialising them. Used to drain the body of a request whose response has already been decided, so the connection stays usable.

Parameters

  • length (number)

Raises ProtocolError if EOF arrives first

Connection.unread()

http.Connection.unread(data)

Pushes bytes back to the front of the read buffer so the next read sees them again. Used by protocol detection, which has to look at the first bytes of a connection before deciding which parser gets them.

Parameters

  • data (bytes)

Connection.write()

http.Connection.write(data)

Queues data for sending. Nothing reaches the socket until the buffer fills or flush() is called.

Parameters

  • data (bytes|string)

Connection.flush()

http.Connection.flush()

Sends everything queued and blocks until the transport has taken all of it.

Raises TimeoutError, ConnectionError

Connection.set_read_timeout()

http.Connection.set_read_timeout(milliseconds)

Sets how long a read may block before raising TimeoutError. Only effective on a plaintext connection; a TlsStream no longer owns a socket whose timeout can be changed, so a TLS connection’s timeouts have to be set on the TcpStream before it is wrapped (which connect() and accept() below both do).

Parameters

  • milliseconds (number) — 0 or negative to block indefinitely

Connection.set_write_timeout()

http.Connection.set_write_timeout(milliseconds)

Sets how long a write may block before raising TimeoutError. Carries the same TLS caveat as set_read_timeout().

Parameters

  • milliseconds (number)

Connection.set_nodelay()

http.Connection.set_nodelay(enabled)

Turns off Nagle’s algorithm, so a response head goes out immediately rather than waiting for more data to coalesce with. Every HTTP server wants this; a request is answered by a burst that is then followed by silence, which is the exact case Nagle handles badly.

Parameters

  • enabled (bool)

Connection.close()

http.Connection.close()

Flushes anything still queued and closes the transport. Safe to call more than once. A failure while flushing is swallowed - the connection is going away regardless, and the caller has usually already handled whatever went wrong.

Connection.to_string()

http.Connection.to_string()

2026, Richard Ore and Zuri contributors