mirror of
https://github.com/dalbodeule/hop-gate.git
synced 2026-09-21 08:11:06 +09:00
- 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
80 lines
3.4 KiB
Markdown
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.
|