Files
hop-gate/ARCHITECTURE.md
T
dalbodeule ebd8463c19 docs: align architecture and API docs with Go 1.27 ingress support
- document HTTP/1.1, HTTP/2, and HTTP/3 ingress
- describe SSE streaming and timeout behavior
- document HTTP/2 and HTTP/3 Extended CONNECT
- update yamux stream and deployment architecture
- document Go 1.27 and UDP HTTP/3 requirements
2026-09-04 16:58:14 +09:00

80 lines
3.4 KiB
Markdown

# HopGate Architecture
HopGate exposes public HTTP traffic and forwards it to a private HTTP service
through one outbound TLS connection per client.
```text
TCP :80/:443 HTTP/1.1, HTTP/2
public clients -------------------------------> HopGate server
UDP :443 HTTP/3 |
| TLS/TCP
v
yamux logical streams
|
v
HopGate client
|
v
localhost HTTP
```
## Connection Model
The client opens one TLS connection to the server and the connection is
multiplexed by yamux. The first logical stream is a bounded JSON control stream
containing the registered domain, local target, and client API key. The server
authenticates this stream before registering the session for the domain.
Each public request creates one bidirectional yamux stream. Every stream starts
with a bounded JSON `StreamMeta` record and then carries HTTP/1.1 wire data.
The stream kinds currently used are:
- `control`: client registration and authentication metadata.
- `http`: ordinary HTTP requests and responses.
- `websocket`: HTTP/1.1 Upgrade and HTTP/2/HTTP/3 Extended CONNECT traffic.
Request and response bodies are copied between stream endpoints instead of
being accumulated in memory. Long-lived SSE connections therefore occupy one
yamux stream for their lifetime.
## Ingress Protocols
The public server uses one common `http.Handler` for all ingress protocols:
- HTTP/1.1: ordinary reverse proxy and raw WebSocket Upgrade.
- HTTP/2: ordinary reverse proxy, SSE, and RFC 8441 Extended CONNECT.
- HTTP/3: ordinary reverse proxy, SSE, and RFC 9220 Extended CONNECT.
HTTP/3 runs on a separate UDP listener using `quic-go/http3`, while the TCP
HTTP/HTTPS listeners continue to serve HTTP/1.1 and HTTP/2. HTTP/1.1 and HTTP/2
responses advertise HTTP/3 with `Alt-Svc`.
For HTTP/2 Extended CONNECT, Go's compatibility setting must be enabled when
starting the process:
```bash
GODEBUG=http2xconnect=1 ./bin/hop-gate-server
```
## Streaming Policies
Requests accepting `text/event-stream` are treated as SSE. They bypass the
normal request-level proxy timeout, and response writes are flushed to the
public client as they arrive. The client or upstream service is responsible for
closing the SSE request context.
WebSocket Extended CONNECT is translated to a local HTTP/1.1 WebSocket
handshake. After the handshake, the payload is relayed as a bidirectional raw
stream. HTTP/3 Extended CONNECT follows the same application path as HTTP/2.
## Packages
- `internal/tunnel`: TLS dialing, yamux sessions, metadata, and stream lifecycle.
- `cmd/server`: public HTTP/HTTPS/HTTP/3 ingress and yamux tunnel listener.
- `cmd/client`: outbound yamux client and local HTTP/WebSocket forwarding.
- `internal/admin`: domain registration and API-key validation.
- `internal/acme`: certificate acquisition, renewal, and TLS configuration.
The tunnel is intentionally stream-oriented. It does not implement application
ACKs or retransmission; TLS over TCP and yamux provide ordered reliable delivery.