Documentation
¶
Overview ¶
Package wsproxy demonstrates the embedded WebSocket proxy pattern using jisr/server, with a complete implementation for the OpenAI Realtime API at /v1/responses.
Protocol: OpenAI Realtime WebSocket (/v1/responses) ¶
The client sends one message to start a response:
{"type":"response.create","model":"gpt-4o-mini","input":[...],"max_output_tokens":N}
The server streams events back:
{"type":"response.created", ...}
{"type":"response.output_text.delta", "delta":"Hi"} // text chunks
{"type":"response.output_text.done", ...}
{"type":"response.completed", "response":{"usage":{"input_tokens":N,"output_tokens":M}}}
The WSProxy taps every frame:
- Client → Upstream: extracts model name from response.create
- Upstream → Client: extracts token usage from response.completed
Architecture ¶
Client ──WS──► Envoy (port 10000, upgrade route)
│ ──► ws-proxy-local cluster (127.0.0.1:<random>)
│ │
│ WSProxy.ServeHTTP
│ │ ──► wss://api.openai.com/v1/responses
│ │ Authorization: Bearer $OPENAI_API_KEY
│
Normal HTTP ──► upstream cluster (TLS + ws-auth upstream filter)
Index ¶
Constants ¶
const AuthExtensionName = "ws-auth"
const ExtensionName = "ws-proxy"
Variables ¶
This section is empty.
Functions ¶
func ResolveEnv ¶
ResolveEnv expands ${ENV_VAR} references in v using os.Expand. Returns v unchanged if the variable is unset.
Types ¶
type AuthConfig ¶
type AuthConfig struct {
// StripHeaders are request headers removed before forwarding upstream
// (e.g. "authorization" — strip the client's key, inject the provider's).
StripHeaders []string
// InjectHeaders are headers added to the upstream request.
// Values support ${ENV_VAR} expansion.
InjectHeaders map[string]string
}
AuthConfig holds credentials for a single upstream cluster. Loaded once at filter config time from environment variables.
func DefaultAuthConfig ¶
func DefaultAuthConfig() AuthConfig
DefaultAuthConfig returns a default config reading from well-known env vars.
type Config ¶
type Config struct {
// UpstreamURL is the upstream wss:// base URL.
// Default: "wss://api.openai.com"
UpstreamURL string `json:"upstream_url"`
// AuthHeader is the HTTP header name to inject when dialing upstream.
// Default: "authorization"
AuthHeader string `json:"auth_header"`
// AuthValue is the header value. Supports ${ENV_VAR} expansion.
// Default: "Bearer ${OPENAI_API_KEY}"
AuthValue string `json:"auth_value"`
// ShutdownTimeout for graceful shutdown. Default: "5s".
ShutdownTimeout string `json:"shutdown_timeout"`
// ListenAddress is the loopback address for the embedded proxy server.
// Default: "127.0.0.1:0" (random free port).
ListenAddress string `json:"listen_addr"`
// OTELEndpoint enables actor-side OTLP/gRPC metrics export when set.
// Example: "127.0.0.1:4317".
OTELEndpoint string `json:"otel_endpoint"`
// OTELExportInterval controls actor-side metric export cadence.
// Default: "1s".
OTELExportInterval string `json:"otel_export_interval"`
}
Config is the JSON config for the ws-proxy filter.
type SessionTap ¶
type SessionTap struct {
// contains filtered or unexported fields
}
SessionTap extracts the model name and token usage from OpenAI Realtime frames. It is created fresh for each WebSocket session. Exported for unit testing.
func (*SessionTap) FeedClient ¶
func (t *SessionTap) FeedClient(data []byte)
FeedClient taps the response.create frame (first client message) to extract the model name. All subsequent client frames are ignored after model is known.
OpenAI Realtime client frame format:
{"type":"response.create","model":"gpt-4o-mini","input":[...],"max_output_tokens":20}
func (*SessionTap) FeedUpstream ¶
func (t *SessionTap) FeedUpstream(data []byte)
FeedUpstream taps the response.completed frame (final server event) to extract token usage. All other upstream frames are ignored.
OpenAI Realtime server frame format:
{"type":"response.completed","response":{"usage":{"input_tokens":N,"output_tokens":M}}}
func (*SessionTap) Model ¶
func (t *SessionTap) Model() string
Model returns the model name extracted from response.create, or "" if not yet seen.
func (*SessionTap) Usage ¶
func (t *SessionTap) Usage() TokenUsage
Usage returns the token usage extracted from response.completed.
type TokenUsage ¶
TokenUsage holds the token counts from the completed response.
type WSProxy ¶
type WSProxy struct {
// OnClientFrame is called for each text frame the client sends.
// Runs in the pump goroutine — must be fast and non-blocking.
OnClientFrame func(websocket.MessageType, []byte)
// OnUpstreamFrame is called for each text frame received from upstream.
// Runs in the pump goroutine — must be fast and non-blocking.
OnUpstreamFrame func(websocket.MessageType, []byte)
// contains filtered or unexported fields
}
WSProxy is an http.Handler that proxies WebSocket connections to an upstream provider, tapping frames for model extraction and token counting.