Documentation
¶
Overview ¶
Package staticserver is the shared static-site origin proxy (w1/m21): one always-on HTTP server, behind Traefik, that serves every static_site App's built output from the object-store origin. It dispatches by request Host to the App's current revision prefix, fetches objects with signed GETs (the bucket stays private), and applies the App's edge rules — redirects/rewrites (Spec.Routes, Render's /routes) and custom response headers (Spec.Headers, Render's /headers) — plus index.html defaulting and SPA fallback. Objects are cached in memory: a revision prefix is immutable, so a hit is never stale, and caching keeps egress inside the object store's fair-use budget.
The handler is decoupled from Kubernetes and S3 via two seams — Resolver (host → Site) and Origin (key → bytes) — so the edge-rule behavior is unit tested with fakes (staticserver_test.go); the real wiring lives in resolver.go (a controller-runtime cache over static_site Apps) and s3origin.go.
Index ¶
Constants ¶
const DefaultCacheBytes = 256 << 20 // 256 MiB
DefaultCacheBytes is the default in-memory object cache budget (main.go may override it via BEX_STATIC_CACHE_BYTES).
Variables ¶
var ErrNotFound = errors.New("staticserver: object not found")
ErrNotFound is what an Origin returns when the requested key does not exist.
var ErrObjectTooLarge = errors.New("staticserver: object too large")
ErrObjectTooLarge is what an Origin returns when a tenant-controlled object exceeds maxOriginObjectBytes, so a single oversized asset can't be allocated whole and OOM the shared single-replica server (codex-security #10).
var ErrOverloaded = errors.New("staticserver: origin fetch capacity reached")
ErrOverloaded is returned when the origin-fetch admission gate is at capacity; the handler sheds it as 503 rather than buffering unbounded misses (finding 12).
Functions ¶
This section is empty.
Types ¶
type CachedResolver ¶
type CachedResolver struct {
// contains filtered or unexported fields
}
CachedResolver serves the host→Site map by periodically listing static_site Apps and atomically swapping an immutable snapshot. Polling (rather than an informer) keeps the standalone binary simple; static-site config changes are infrequent and a few seconds of edit propagation is acceptable (Render is not instant either). Only Apps that are static_site, not suspended, and already published (Status.ActiveRevision set) are served.
func NewCachedResolver ¶
func NewCachedResolver(reader client.Reader, namespace, baseDomain string) *CachedResolver
NewCachedResolver builds a resolver reading Apps in namespace (empty = all) from reader; baseDomain expands an App's Expose flag to "<name>.<baseDomain>".
func (*CachedResolver) Refresh ¶
func (c *CachedResolver) Refresh(ctx context.Context) error
Refresh rebuilds the host→Site snapshot from the current static_site Apps.
func (*CachedResolver) Resolve ¶
func (c *CachedResolver) Resolve(host string) (Site, bool)
Resolve returns the Site serving host, or ok=false when none does.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler is the static-site origin proxy. Construct with New.
type Object ¶
type Object struct {
Body []byte
ContentType string // from the origin; may be empty (then inferred from extension)
}
Object is a fetched origin object.
type Origin ¶
type Origin interface {
// Get returns the object at key, or ErrNotFound if it does not exist.
Get(ctx context.Context, key string) (Object, error)
}
Origin fetches objects from the static-site object store by key.
type Resolver ¶
type Resolver interface {
// Resolve returns the Site for host, or ok=false when no static_site App
// serves that host.
Resolve(host string) (Site, bool)
}
Resolver maps a request host to its Site config.
type S3Origin ¶
type S3Origin struct {
// contains filtered or unexported fields
}
S3Origin is an Origin backed by an S3-compatible object store (Wasabi/Hetzner today). It signs each GET, so the bucket stays private — the same credentials the publish Job uses to write (AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY from the environment). Path-style addressing is used because S3-compatibles rarely support virtual-host-style bucket subdomains.
func NewS3Origin ¶
NewS3Origin builds an S3-backed Origin. Credentials come from the standard AWS environment (the ServiceAccount-mounted Secret in-cluster). endpoint is the S3-compatible base URL (e.g. https://s3.eu-central-2.wasabisys.com); region defaults to us-east-1 when empty (required by the SDK even though path-style + a custom endpoint ignores it for routing).
func (*S3Origin) Check ¶
Check verifies the configured identity can list the dedicated origin bucket. It is called once at startup so a missing, wrong, or over-rotated read Secret fails the static-server Deployment immediately instead of leaving a Ready pod that answers every tenant request with an opaque 503.
type Site ¶
type Site struct {
AppID string // first object-key segment (legacy sites)
Revision string // last key segment (e.g. "rev-7"); immutable per revision
Prefix string // full object-key prefix including trailing slash when known
Routes []appv1alpha1.StaticRoute // ordered redirect/rewrite rules
Headers []appv1alpha1.StaticHeader // custom response headers by path
}
Site is the serving config for one static_site App, keyed by request host.