Documentation
¶
Overview ¶
Package server is Backyard's HTTP layer (SPEC §2–§6): host/path routing, static site serving, the site API (identity, db, files, ai, warehouse, websocket), the hub (UI, docs, llms.txt, site list, tokens), the embedded deploy gateway mount, health checks, rate limiting and metrics.
Routing ¶
The request host (Host, or X-Forwarded-Host from server.trusted_proxies) is classified as the hub (server.base_domain or the public URL's host), a site (a single DNS label under base_domain, host mode only) or an unknown host (404). With server.dev, IP-literal and localhost host names also reach the hub (other names stay unknown, which defeats DNS rebinding against a local dev server). In path mode sites live under /s/<site>/ on the hub host. The path prefix /__backyard/ is reserved on every host: site files can never shadow it. /__backyard/healthz and /__backyard/readyz answer on any host without authentication.
Security ¶
Every other request is authenticated with the configured auth.Authenticator, except the SDK files, the auth endpoints, the deploy gateway (which authenticates by itself) and the machine paths of the Claude connector. Unauthenticated browser page loads are redirected to the login URL; API calls get 401 JSON with "login_url". State-changing API calls must carry "X-Backyard: 1" and, when present, an Origin equal to the request's own origin (path mode: the hub origin). Site API calls are rate limited per user (anonymous: per client IP).
Claude connector ¶
With mcp.enabled (SPEC §8.4, §14.1) the hub also serves the remote MCP endpoint /__backyard/mcp, the OAuth endpoints /__backyard/oauth/{register,token,revoke} and the discovery documents /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource/__backyard/mcp. These machine paths authenticate by themselves (the endpoint accepts only MCP access tokens) and never read cookies or identity-proxy headers; they exist on the canonical hub host only and answer 404 while the connector is off. The sign-in and consent page /__backyard/auth/authorize is an auth endpoint like the others, and /__backyard/api/mcp/grants a hub API. Registration and revocation are rate limited per client IP; authorize, the token endpoint and the MCP endpoint per user (authorize and token: per client IP for requests that identify no one).
Timeouts ¶
No http.TimeoutHandler is used: streaming responses (AI server-sent events, websockets, large downloads and uploads) extend or clear the connection deadlines themselves, and backend calls are bounded by contexts.
Large responses on Cloud Run ¶
Cloud Run rejects HTTP/1 responses that declare a Content-Length above 32 MiB. When K_SERVICE is set, static files and uploads above that size are streamed without a Content-Length (chunked), and byte ranges above it are shortened to 32 MiB (see serveObject).
Index ¶
- func ClientIP(r *http.Request) string
- func RequestOrigin(r *http.Request) string
- type Deps
- type Server
- func (s *Server) AllowAPI(key string) (bool, time.Duration)
- func (s *Server) Close(ctx context.Context) error
- func (s *Server) Handler() http.Handler
- func (s *Server) MetricsHandler() http.Handler
- func (s *Server) ObserveDeploy(method, result string)
- func (s *Server) OnWSFrame(dir string)
- func (s *Server) PurgeSite(site string)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ClientIP ¶ added in v0.2.0
ClientIP returns the client address of r (X-Forwarded-For from server.trusted_proxies honoured), as access logs and audit records show it. For a request that did not pass through the server's handler it is the address of r.RemoteAddr.
func RequestOrigin ¶ added in v0.2.0
RequestOrigin returns the client-visible origin of r (lowercase scheme://host[:port], default port removed), honouring X-Forwarded-Host and X-Forwarded-Proto from server.trusted_proxies as the router does. For a request that did not pass through the server's handler it falls back to r.TLS and r.Host.
Types ¶
type Deps ¶
type Deps struct {
Config *config.Config
Logger *slog.Logger
Blob blob.Store
Docs docstore.Store
Sites *sites.Registry
Auth auth.Authenticator
Tokens *auth.Tokens
Users *identity.UserCache
Realtime realtime.Hub
AI ai.Service
Warehouse warehouse.Service
// Gateway is the embedded deploy gateway, mounted at /__backyard/api/deploy
// on the hub host with that prefix stripped. GET /__backyard/api/info is
// served by forwarding to the gateway's /info.
Gateway http.Handler
// MCP is the Claude connector's authorization server (auth.MCPOf(Auth));
// nil while mcp.enabled is false. It serves the discovery documents and
// /__backyard/oauth/*, and backs the grants API.
MCP *auth.MCP
// MCPEndpoint serves POST /__backyard/mcp (internal/mcpremote); nil
// answers the disabled 404.
MCPEndpoint http.Handler
// DevSites maps site names to local directories served live (backyard dev).
// Like deploys, they never expose hidden paths (a segment starting with
// "." other than ".well-known").
DevSites map[string]string
// Version string reported by /__backyard/api/info.
Version string
}
Deps are the components the server needs. AI, Warehouse, Realtime and Gateway may be nil (feature disabled → 404/unsupported responses).
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the assembled HTTP application.
func New ¶
New validates deps and builds the server.
Deps.Docs is wrapped with docstore.WithLimits(database.max_doc_bytes, database.max_docs_per_site) unless it already exposes an Unwrap method (i.e. the caller wrapped it). The embedded deploy gateway is mounted only when deploy.embedded_gateway is not false; GET /__backyard/api/info is forwarded to Deps.Gateway whenever it is set.
func (*Server) AllowAPI ¶ added in v0.2.0
AllowAPI consumes one request of the general API limit (ratelimit.api_per_minute) for key, e.g. "user:<id>" for the MCP endpoint. On refusal it counts rate_limited_total{category="api"} and returns how long to wait. A nil Server allows everything.
func (*Server) Close ¶
Close waits (bounded by ctx) for background work such as user-cache writes and audit records to finish. The handler keeps working after Close (work started meanwhile is waited for too); call it after the HTTP server has shut down and before closing Deps.Docs.
func (*Server) MetricsHandler ¶
MetricsHandler returns the Prometheus handler (for telemetry.metrics_listen).
func (*Server) ObserveDeploy ¶
ObserveDeploy counts a deploy for the deploys_total metric. Deploys through the embedded gateway are counted automatically; this is for other paths (the Claude connector's publishes, method "mcp"; a standalone gateway sharing the process).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package servertest holds end-to-end tests that run the HTTP server against real components: the filesystem blob store, the SQLite (and, when BACKYARD_TEST_POSTGRES_DSN is set, PostgreSQL) document store, the realtime hub over in-memory (and, when BACKYARD_TEST_REDIS_URL is set, Redis) pub/sub, the auth package in mode "none" and the embedded deploy gateway.
|
Package servertest holds end-to-end tests that run the HTTP server against real components: the filesystem blob store, the SQLite (and, when BACKYARD_TEST_POSTGRES_DSN is set, PostgreSQL) document store, the realtime hub over in-memory (and, when BACKYARD_TEST_REDIS_URL is set, Redis) pub/sub, the auth package in mode "none" and the embedded deploy gateway. |