httpapi

package
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: MIT Imports: 56 Imported by: 0

Documentation

Overview

Package httpapi is backd's HTTP layer: routing, middleware, error envelope, the generic document handlers and the /_auth endpoints.

Index

Constants

View Source
const (
	DevDurationHeader = "X-Backd-Dev-Duration-Ms"
	DevLogsHeader     = "X-Backd-Dev-Logs"
)

DevDurationHeader and DevLogsHeader carry the function's timing and console output back to the caller, only in dev mode (BACKD_DEV): a production call never leaks another caller's function logs. `backd functions invoke` reads them.

View Source
const DefaultMaxBodyBytes = 1 << 20

DefaultMaxBodyBytes is the request body limit when none is configured.

View Source
const DefaultMaxUploadBytes = 100 << 20

DefaultMaxUploadBytes is the largest file a proxy upload carries when none is configured.

View Source
const DefaultOpTimeout = 10 * time.Second

DefaultOpTimeout is the per-request storage deadline when none is configured.

View Source
const (

	// DefaultRegenerateRate is how many files a second a regeneration makes when none is asked.
	DefaultRegenerateRate = 10
)

Variables

This section is empty.

Functions

func NewHandler

func NewHandler(cfg Config) http.Handler

NewHandler builds the complete HTTP handler.

func NewInternalHandler

func NewInternalHandler(cfg Config) http.Handler

NewInternalHandler builds the internal listener's handler, for the functions executor only: bundles by hash (with the executor's token) and the data routes for functions calling back (with callback tokens, and nothing else). It must never be reachable from outside.

func Run

func Run(ctx context.Context, srv *http.Server, ln net.Listener, shutdownTimeout time.Duration, log *slog.Logger) error

Run serves on ln until ctx is done, then shuts down gracefully: the listener closes at once (new connections are refused) and in-flight requests get up to shutdownTimeout to finish. Requests still running after that are aborted and Run returns an error.

func ServerTimeouts

func ServerTimeouts(srv *http.Server, opTimeout time.Duration)

ServerTimeouts returns HTTP server timeouts consistent with a per-request storage deadline: writes get opTimeout plus headroom (and at least 30s).

Types

type Config

type Config struct {
	Log      *slog.Logger
	Registry *registry.Registry
	Store    Store
	// Ready reports whether backd can serve requests (e.g. MongoDB reachable).
	Ready func(ctx context.Context) error
	// Now is the clock for _meta timestamps; defaults to time.Now.
	Now func() time.Time
	// MaxBodyBytes caps request bodies; defaults to DefaultMaxBodyBytes.
	MaxBodyBytes int64
	// MaxUploadBytes caps one file of a proxy upload (BACKD_MAX_UPLOAD_BYTES), apart
	// from MaxBodyBytes, which does not apply to file uploads; defaults to
	// DefaultMaxUploadBytes.
	MaxUploadBytes int64
	// ImageMaxPixels is the instance's limit on an image's pixels
	// (BACKD_IMAGE_MAX_PIXELS); a file field's max_pixels may only be lower. Zero
	// means 40 million.
	ImageMaxPixels int64
	// ImageTimeout and ImageConcurrency bound the workers making image versions
	// (BACKD_IMAGE_TIMEOUT, BACKD_IMAGE_CONCURRENCY); zero is 30 seconds, and a number
	// derived from the container's limits.
	ImageTimeout     time.Duration
	ImageConcurrency int
	// OpTimeout bounds the storage work of each document request;
	// defaults to DefaultOpTimeout.
	OpTimeout time.Duration
	// TrustedProxies are the networks whose X-Forwarded-For header is
	// believed when finding the client's address (for login throttling).
	TrustedProxies []netip.Prefix
	// Users returns the user service of a realm with auth enabled, or nil
	// (unknown realm or auth disabled). Nil Users disables /_auth routes.
	Users func(realm string) *auth.Users
	// ConfigFingerprint identifies the config this instance runs; /readyz
	// reports it so operators can check every instance runs the same one.
	ConfigFingerprint string
	// Functions runs function calls (the executor client); nil: calls get 503.
	Functions FunctionRunner
	// CallbackKey signs the callback tokens functions reach data with; the
	// internal listener verifies them.
	CallbackKey []byte
	// CallbackURL is backd's internal listener as the executor and
	// functions reach it (bundles and callbacks), e.g. http://backd:8081.
	CallbackURL string
	// ExecutorToken authenticates the executor's bundle fetches.
	ExecutorToken string
	// BackdURL is backd's public address, the base of the links in emails
	// (BACKD_URL); a realm's email.public_url overrides it.
	BackdURL string
	// Dev rereads function bundle manifests on every call instead of once
	// (BACKD_DEV), so a background rebuild is served without a restart.
	Dev bool
	// DisableAdminAPI leaves every /v1/{realm}/_admin route out: they answer
	// 404 like any route that doesn't exist (BACKD_ADMIN_API=false).
	DisableAdminAPI bool
	// UI, when set, is served at /_ui/ (the admin web interface).
	UI http.Handler
	// Metrics records what the API does; nil turns it off.
	Metrics *metrics.Metrics
}

Config holds the handler dependencies.

type Detail

type Detail struct {
	Path   string `json:"path"`
	Reason string `json:"reason"`
}

Detail points at one problem, e.g. a field failing schema validation.

type FunctionRunner

type FunctionRunner interface {
	Invoke(ctx context.Context, req executor.InvokeRequest) (executor.Result, error)
}

FunctionRunner runs an invocation: the executor client, or a fake in tests.

type Store

type Store interface {
	Repository(c *registry.Collection) storage.Repository
	// Transact runs fn once; every write made through a Repository, using
	// the context fn receives, either all commit or none do (batch writes,
	// roadmap F7). fn may run more than once on a transient conflict, so
	// it must have no side effects beyond the repositories it's given.
	Transact(ctx context.Context, fn func(ctx context.Context) error) error
}

Store gives access to the repository of each configured collection.

type Worker

type Worker struct {
	// contains filtered or unexported fields
}

Worker claims and runs async jobs (roadmap F11): `backd worker`, or `backd serve --with-worker` in the same process. It never listens: it reaches the executor and backd's own API (ctx.db) exactly like a function's own caller would, reusing the same bundle resolution, callback construction and invocation recording sync calls use.

func NewWorker

func NewWorker(cfg Config, id string) *Worker

NewWorker builds a worker from the same Config NewHandler uses. id identifies this process in job leases (so an operator can tell which instance claimed a stuck job).

func (*Worker) CheckImageDeclarations added in v0.8.1

func (w *Worker) CheckImageDeclarations(ctx context.Context)

CheckImageDeclarations looks, once at startup, for image versions whose declaration is new or changed since a worker last saw it, and logs how many files are affected: the copies made with other parameters, or no copy at all. It changes nothing but the fingerprints it keeps: `backd files regenerate` makes them again. A declaration that has not changed costs nothing; one that has makes one pass over its collection.

func (*Worker) EnqueueDue

func (w *Worker) EnqueueDue(ctx context.Context)

EnqueueDue creates the job of every scheduled function whose latest scheduled time is recent enough and has no job yet (roadmap F18). Every worker runs it; the run's deterministic id makes the insert succeed for exactly one of them.

func (*Worker) FilesDue added in v0.8.0

func (w *Worker) FilesDue(ctx context.Context)

FilesDue keeps the realms' file storage tidy (roadmap #149): an upload left writing or stored past the grace period (its process died, or its document write failed) is marked failed and its object queued for deletion, and the objects queued for deletion are deleted, with a growing wait after a failure. Every worker runs it; claiming a deletion holds it for a lease, so two never take the same one.

func (*Worker) LogImageLimits added in v0.8.1

func (w *Worker) LogImageLimits()

LogImageLimits logs the limits the worker makes image versions within, as they are in effect (derived values included).

func (*Worker) PurgeDue added in v0.4.0

func (w *Worker) PurgeDue(ctx context.Context)

PurgeDue deletes the accounts that never verified their address in the realms that ask for it (account.purge_unverified_after). Running it in every worker is harmless: deleting an account twice is not an error.

func (*Worker) Run

func (w *Worker) Run(ctx context.Context, concurrency int)

Run claims and runs jobs until ctx is done, with concurrency goroutines working the queue at once.

func (*Worker) RunOnce

func (w *Worker) RunOnce(ctx context.Context) bool

RunOnce claims and runs at most one job, across every realm with functions. It returns whether it found one — callers use that to decide whether to poll again immediately or back off.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL