Documentation
¶
Overview ¶
Package webtransport implements a WebTransport (HTTP/3) gateway that lets web browsers connect to the Aqueduct broker over the same binary frame protocol that native QUIC clients use.
Why a separate listener? ¶
Browsers cannot open a raw QUIC stream with the `aqueduct-v1` ALPN — they only speak HTTP/3 + WebTransport. We multiplex the broker's binary frame protocol through WebTransport bidirectional streams (RFC 9298) so the browser can write a `[Magic:1][Cmd:1][StreamID:4][Len:4][Payload:…]` frame into a WT bidi stream and the broker's existing transport.Broker.HandleStream parses it without any protocol changes.
Architecture ¶
┌─────────────┐ ┌──────────────────────┐ ┌───────────────────┐ │ Browser │ ─WT─► │ internal/webtransport│ ─► │ internal/transport│ │ (HTTP/3) │ │ (this package) │ *qs │ (existing) │ └─────────────┘ └──────────────────────┘ └───────────────────┘ 1. Server wraps quic-go's http3.Server only to reuse the SETTINGS-frame and QPACK plumbing of the handshake (Extended CONNECT with `:protocol: webtransport`). 2. The handshake stream hijacks the response writer (so http3 does not close it after Handler returns — the WT spec mandates the session stream stays open for capsule protocol). 3. Subsequent QUIC bidi streams opened on the same connection are WebTransport data streams. We accept them ourselves (not via http3.Server's auto-loop) so the broker's existing dispatch path runs unchanged.
Index ¶
Constants ¶
const DefaultPathPrefix = "/aqueduct/wt"
DefaultPathPrefix is the URL path browser clients should send their Extended CONNECT request to. Configurable via Server.PathPrefix.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Gateway ¶
type Gateway struct {
// contains filtered or unexported fields
}
Gateway is the public WebTransport entry-point. Embed *transport.Broker (or pass one in via WithBroker) so the gateway reuses the broker's existing router / authz engine / AAL log.
func New ¶
New builds a Gateway that wraps the supplied broker. The caller is responsible for invoking ListenAndServe (or Listen followed by the internal accept loop).
func (*Gateway) Close ¶
Close stops the listener and waits for in-flight connections to drain. Safe to call multiple times.
func (*Gateway) ListenAndServe ¶
ListenAndServe binds to addr, configures TLS for HTTP/3 ALPN, and serves WebTransport sessions until Close is called.
ListenAndServe returns immediately after the QUIC listener has been created; the per-connection accept loop runs in a background goroutine. This makes the API composable with cmd-line `signal.Notify`-based shutdown patterns (Close cancels the loop and waits for drain).
The TLS config is fed through http3.ConfigureTLSConfig so the QUIC listener picks up the session-ticket workaround and the canonical "h3" ALPN. The caller's *tls.Config is not mutated.
type Option ¶
type Option func(*Gateway)
Option configures Gateway. Use WithPathPrefix / WithHandshakeTimeout to tweak defaults; everything else is intentionally hard-coded so the gateway's surface stays small and reviewable.
func WithBroker ¶
WithBroker wires an already-configured *transport.Broker. The gateway simply forwards every accepted bidi stream into broker.HandleStream, so router / authz / AAL / tracing all flow through the same code paths.
func WithHandshakeTimeout ¶
WithHandshakeTimeout overrides the maximum time the server waits for a client to complete the Extended CONNECT handshake.
func WithPathPrefix ¶
WithPathPrefix overrides the URL path the WebTransport handshake must use. Defaults to DefaultPathPrefix.