httpapi

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 45 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 DefaultOpTimeout = 10 * time.Second

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

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
	// 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) 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) 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