yao/tai/docs/proxy.md
Max d70694b7ac ci: update Tai to 1.2.0 with new default ports and fix documentation
- Update CI (unit-test.yml, pr-test.yml) to use yaoapp/tai:1.2.0
  with new default ports (gRPC:19100, HTTP:8099, VNC:16080, Docker:12375)
- Add explicit 0.0.0.0 bind for containerized Tai instances
- Fix sandbox/v2 grpc.go default port fallback (9100 → 19100)
- Fix tai/tunnel/proxy.go fallback ports (8080→8099, 6080→16080)
- Sync tai SDK and sandbox/v2 documentation with implementation
- Add new docs: api.md, registry.md, tunnel.md

Made-with: Cursor
2026-03-08 11:33:56 +08:00

4.3 KiB

Package proxy

HTTP reverse proxy URL resolution. Resolves service URLs for containers so that HTTP services running inside sandboxes can be accessed from the host.

Interface

type Proxy interface {
    URL(ctx context.Context, containerID string, port int, path string) (string, error)
    Connect(ctx context.Context, containerID string, opts ConnectOptions) (*Connection, error)
    Healthz(ctx context.Context) error
}

Implementations

Implementation Constructor Mode URL Pattern
Remote NewRemote(host, port, hc) Via Tai HTTP proxy http://tai-host:8099/{containerID}:{port}/{path}
Local NewLocal(sb) Direct host port lookup http://127.0.0.1:{hostPort}/{path}
Tunnel NewTunnel(taiID, yaoBase) Via Yao reverse proxy {yaoBase}/tai/{taiID}/proxy/{containerID}:{port}/{path}

Constructors

NewRemote

func NewRemote(host string, port int, hc *http.Client) Proxy

Creates a Proxy that routes through Tai's HTTP reverse proxy. URLs are constructed by combining the Tai server address with the container ID and port.

  • host — Tai server hostname/IP
  • port — Tai HTTP proxy port (default 8099)
  • hc — custom HTTP client, nil uses http.DefaultClient

NewLocal

func NewLocal(sb sandbox.Sandbox) Proxy

Creates a Proxy that resolves URLs by inspecting the container's port mappings via sandbox.Inspect. Looks up the host port bound to the requested container port.

Returns an error if the requested port is not mapped.

NewTunnel

func NewTunnel(taiID, yaoBase string) Proxy

Creates a Proxy that routes through Yao's HTTP reverse proxy for tunnel-mode connections.

  • taiID — the Tai node identifier in the registry
  • yaoBase — the Yao server base URL (e.g. "http://yao-server:5099")

Methods

URL

URL(ctx context.Context, containerID string, port int, path string) (string, error)

Resolves an HTTP URL to reach a service running on port inside the given container.

Remote example: container abc123 port 3000 path /api/healthhttp://tai-host:8099/abc123:3000/api/health

Local example: container abc123 port 3000 mapped to host port 32768http://127.0.0.1:32768/api/health

Connect

Connect(ctx context.Context, containerID string, opts ConnectOptions) (*Connection, error)

Establishes a persistent connection to a container service. Supports WebSocket and SSE protocols.

ConnectOptions

type ConnectOptions struct {
    Port     int    // container port
    Path     string // URL path (e.g. "/ws" or "/events")
    Protocol string // "ws" or "sse"
}

Connection

type Connection struct {
    Messages <-chan []byte         // incoming data; closed when connection ends
    Send     func(data []byte) error // write data (only valid for "ws" protocol)
    Close    func() error            // terminate the connection
}
Protocol Messages Send Description
"ws" WebSocket messages write to WS Full-duplex WebSocket
"sse" SSE data: lines returns error Read-only Server-Sent Events

Healthz

Healthz(ctx context.Context) error

Checks the health of the proxy backend.

  • Remote: sends GET /healthz to the Tai HTTP proxy server
  • Local: always returns nil (no external dependency)
  • Tunnel: always returns nil

Example

c, _ := tai.New("tai://192.168.1.100")
defer c.Close()

// Get URL for a web service running on port 3000
url, _ := c.Proxy().URL(ctx, containerID, 3000, "/api/status")
resp, _ := http.Get(url)

// Health check
if err := c.Proxy().Healthz(ctx); err != nil {
    log.Fatal("Tai HTTP proxy is down:", err)
}

// WebSocket connection to a service
conn, _ := c.Proxy().Connect(ctx, containerID, proxy.ConnectOptions{
    Port: 8080, Path: "/ws", Protocol: "ws",
})
defer conn.Close()
conn.Send([]byte(`{"action":"ping"}`))
for msg := range conn.Messages {
    fmt.Println(string(msg))
}

// SSE event stream
conn, _ = c.Proxy().Connect(ctx, containerID, proxy.ConnectOptions{
    Port: 8080, Path: "/events", Protocol: "sse",
})
defer conn.Close()
for msg := range conn.Messages {
    fmt.Println("event:", string(msg))
}