Documentation
¶
Overview ¶
Package httpapi assembles the ggscale-server HTTP router. The /v1 subtree holds all real routes; everything outside falls through to chi's NotFound (returning 404). /metrics is mounted at root and is intentionally versionless.
Index ¶
Constants ¶
const RealtimePath = v1Prefix + "/ws"
RealtimePath is the realtime WebSocket route.
Variables ¶
This section is empty.
Functions ¶
func OpenAPIDoc ¶
OpenAPIDoc builds the /v1 OpenAPI document by registering every operation into one shared doc. It needs no live dependencies: the handler closures are registered but never invoked, so a zero Deps suffices.
The register* list below MUST mirror NewRouter's registrations. NewRouter spreads them across middleware-scoped chi groups (for auth/scope binding); here they collapse onto one adapter because the document only needs the operation metadata, not the middleware. TestOpenAPIDoc_covers_expected_paths guards against drift.
Types ¶
type APIWork ¶
APIWork is the API server's meaning of work for the lifecycle contract. Draining refuses new realtime WebSocket upgrades; plain HTTP requests are still served, because the load balancer stops sending them once /readyz turns 503. A drain waits on open sockets plus in-flight HTTP requests. River and the matchmaker worker are deliberately not part of it: River's queue pause is cluster-wide, not per node, and both already stop in the normal shutdown path.
func NewAPIWork ¶
func NewAPIWork() APIWork
NewAPIWork returns the API server's work, with in-flight counting that leaves realtime upgrades to the realtime drain.
func (APIWork) ActiveWork ¶
ActiveWork reports open realtime sockets plus in-flight HTTP requests.
func (APIWork) RefusedWork ¶
RefusedWork reports realtime upgrades refused while draining.
type Deps ¶
type Deps struct {
// PartyEnqueueEnabled lets party leaders queue and rematch. When false,
// both return 503 party_enqueue_disabled.
PartyEnqueueEnabled bool
// PartyCodeLimits bound wrong party-code guesses. Zero fields use
// party.DefaultCodeLimits.
PartyCodeLimits party.CodeLimits
Version string
Commit string
// RequestTimeout bounds non-streaming requests; 0 disables the deadline
// middleware (used by unit-test fixtures). WebSocket paths are exempt.
RequestTimeout time.Duration
Pool *db.Pool
// ReadPool serves staleness-tolerant reads. nil defaults to Pool, so a
// deployment without a replica (or a test fixture) routes reads to the
// primary unchanged.
ReadPool *db.Pool
Lookup tenant.Lookup
Limiter ratelimit.Limiter
// RateLimitOverrides (may be nil) supplies per-tenant/project rate-limit
// overrides. Wrap the DB store in a CachedOverrideStore.
RateLimitOverrides ratelimit.OverrideStore
// TokenIPLimits (may be nil) overrides the tier→per-IP bucket derivation
// for the token auth routes; nil uses ratelimit.TokenIPLimitsForTier.
TokenIPLimits func(tenant.Tier) ratelimit.Limits
// StorageMaxValueBytes is the platform default cap on a storage object's
// value; 0 uses the compiled fallback (1 MiB).
StorageMaxValueBytes int64
// DeleteGracePeriod is how long a requested player deletion stays
// cancellable before the purge sweep hard-deletes the data; 0 uses the
// compiled fallback (30 days).
DeleteGracePeriod time.Duration
// StorageLimits (may be nil) resolves per-tenant/project storage-size
// overrides on top of StorageMaxValueBytes.
StorageLimits storagelimit.LimitStore
// ProxyTrust resolves the real client IP for per-IP limits when the server
// is behind a trusted reverse proxy / load balancer. nil = RemoteAddr only.
ProxyTrust *ratelimit.ProxyTrust
Signer *auth.Signer
Mailer mailer.Mailer
MailFrom string
// EnqueuePasswordReset inserts the durable forgot-password delivery job
// (jobs.PasswordResetEmailArgs). nil = no job queue; the web handlers
// fall back to in-process delivery.
EnqueuePasswordReset func(ctx context.Context, surface, email string) error
// TwoFactor encrypts TOTP secrets and signs 2FA pending cookies for the
// control panel and player surfaces. nil = 2FA enrollment unavailable.
TwoFactor *twofactor.Cipher
// CredentialCipher seals stored provider credentials (e.g. the Steam Web
// API key) at rest and unseals them on read. nil reads values as stored
// (unit tests; legacy plaintext rows).
CredentialCipher *secretseal.Cipher
// SteamAuth verifies Steam session tickets for POST /v1/auth/steam. nil
// defaults to the production Valve client; tests inject a fake.
SteamAuth steamauth.Verifier
// EmailVerifySigningKey signs verification cookies for both web surfaces.
EmailVerifySigningKey []byte
Cache cache.Store
Registry *prometheus.Registry
// Metrics carries the business/health counters. nil is a no-op (unit tests).
Metrics *observability.Metrics
RBAC *rbac.Authorizer
Now func() time.Time
// Fleet is the allocator for game-server slots. nil until a backend is
// wired. The matchmaker checks for nil and degrades to a not-implemented
// error when unset.
Fleet *fleet.Manager
// Hub fans WS messages out to connected players. nil disables /v1/ws.
Hub *realtime.Hub
RealtimeMaxPerTenant int64
RealtimeMaxPerPlayer int64
// RealtimeHeartbeat overrides the WS heartbeat/revalidation interval.
// Zero uses the production default (30s); tests shorten it.
RealtimeHeartbeat time.Duration
// TenantConnectionCap coordinates regional capacity through PostgreSQL
// leases while keeping socket admission in process memory.
TenantConnectionCap ratelimit.ConnectionCap
// Matchmaker is the ticket queue. nil disables /v1/matchmaker/*.
Matchmaker matchmaker.Queue
// MatchmakerTicketTTL bounds how long a queued ticket lives. 0
// disables expiry.
MatchmakerTicketTTL time.Duration
// GameSessions creates game sessions (shared with the matchmaker
// worker's game_session mode).
GameSessions *gamesession.Service
// ServerList is the in-memory game-server heartbeat registry that
// backs the server-browser endpoint. nil disables /v1/fleets/*.
ServerList *serverlist.Registry
// RelayIssuer mints TURN-REST credentials. nil disables /v1/relay/*.
RelayIssuer *relay.Issuer
// RelayNodes picks the relay URLs each credential set lists. nil lists
// none, so credential requests get 503.
RelayNodes RelayNodeSelector
// RelayNodeAdmin backs the platform-admin relay node routes. They mount
// only when it and PlatformAdminToken are both set.
RelayNodeAdmin RelayNodeAdmin
// PlatformAdminToken guards the platform-admin API (/v1/admin/*). Empty
// leaves it unmounted.
PlatformAdminToken string
// RelayMeter enforces the per-class monthly relay-session allowance at
// credential issuance. nil disables metering (unit tests).
RelayMeter *relaymeter.Meter
ControlPanel controlpanel.Config
ControlPanelBootstrap *controlpanel.Bootstrap
// BillingHandoffKey signs the control panel's short-lived billing upgrade
// handoff tokens. nil = no upgrade link renders.
BillingHandoffKey []byte
// ControlPanelPluginInfo is the closure the admin/plugins page calls to
// snapshot the running fleet plugin. nil when no plugin backend is
// configured — the page renders "no plugin backend" in that case.
ControlPanelPluginInfo func() *controlpanel.PluginSnapshot
// Players controls whether the player-facing /v1/players/p/{projectID}/
// site is mounted.
Players players.Config
// CORSAllowedOrigins lists the origins the API router answers preflight
// from. Empty in dev falls back to "*"; config.Validate refuses an
// empty list in production.
CORSAllowedOrigins []string
// MetricsAuthToken, when non-empty, gates /metrics behind a bearer token.
// Empty leaves /metrics open (dev / explicitly-unauthenticated deployments).
MetricsAuthToken string
// MCPEnabled mounts POST /mcp for coding agents (FEATURE_MCP_ENABLED).
// MCPTokenRatePerSecond / MCPTokenBurst set the per-token bucket.
MCPEnabled bool
MCPTokenRatePerSecond float64
MCPTokenBurst float64
// MCPAuthFailuresPerMinute / MCPAuthFailureBurst set the per-IP bucket
// for failed /mcp authentications. Zero uses the mcp package default.
MCPAuthFailuresPerMinute float64
MCPAuthFailureBurst float64
// MCPMaxProjectAPIKeys limits the create_api_key tool.
MCPMaxProjectAPIKeys int64
// CORSMaxProjectOrigins limits the set_allowed_origins tool.
CORSMaxProjectOrigins int
// EntitlementAPIToken, when non-empty, mounts the internal declarative
// entitlement API at /internal/entitlements behind this bearer token —
// outside /v1, so it never enters openapi.yaml or the SDKs. Empty (the
// default) leaves the surface unmounted entirely.
EntitlementAPIToken string
// Lifecycle, when non-nil, mounts /readyz and the /lifecycle routes at
// root next to /metrics. Operators keep them off the public edge the same
// way they keep /metrics off it.
Lifecycle *lifecycle.Controller
// RealtimeDrain, when non-nil, tracks open /v1/ws sockets and refuses new
// upgrades with 503 while the process drains.
RealtimeDrain *realtime.Drain
// contains filtered or unexported fields
}
Deps carries values the router needs but doesn't construct.
Pool / Lookup / Limiter / Signer are all required to mount the tenant-protected /v1/auth/* subgroup. When any is nil, only the public /v1/healthz + /metrics routes are mounted — useful for unit tests that don't need authenticated paths.
type RelayNodeAdmin ¶
type RelayNodeAdmin interface {
Create(ctx context.Context, spec relaynode.Spec) (relaynode.Node, error)
List(ctx context.Context) ([]relaynode.Node, error)
Retire(ctx context.Context, id int64) (relaynode.Node, error)
}
RelayNodeAdmin is the relay node registry the admin routes manage. relaynode.Store implements it.
Source Files
¶
- admin_relay_nodes.go
- auth.go
- auth_account.go
- auth_link.go
- auth_password_reset.go
- auth_steam.go
- bans.go
- config.go
- cors_origins.go
- friend_code.go
- friends.go
- game_session.go
- game_session_signal.go
- gameinvite.go
- health.go
- humaapi.go
- internalapi.go
- leaderboard_discovery.go
- leaderboard_periods.go
- leaderboards.go
- lifecycle.go
- matchmaker.go
- mount.go
- openapi.go
- parties.go
- player_sessions_verify.go
- players.go
- presence.go
- profile.go
- realtime_lifecycle.go
- realtime_ticket.go
- relay.go
- remoteaddr.go
- router.go
- server_tier.go
- serverlist.go
- storage.go