API: src

Generated from Geblang source declarations and docblocks.

gebweb.app

Source: gebweb/src/app.gb

Function setParameter

func setParameter(GebwebApp app, string key, any value): GebwebApp

Function getParameter

func getParameter(GebwebApp app, string key): any

Function hasParameter

func hasParameter(GebwebApp app, string key): bool

Function parameters

func parameters(GebwebApp app): dict<string, any>

Function registerViewContext

func registerViewContext(GebwebApp app, string name, callable fn): GebwebApp

Register a view-context injector. The framework wires injectors for csrf / flashes / errors / oldInput / cspNonce / asset map automatically when the relevant use* helpers are called; user code can register additional injectors here. Each call to gebweb.view(app, name, ctx, request) merges every registered injector's result into the context (under its name) before rendering. Earlier user-supplied keys win over injectors. The injector callable receives the rich Request (1.7.1+).

Function viewContextInjectors

func viewContextInjectors(GebwebApp app): dict<string, callable>

Function setInfo

func setInfo(GebwebApp app, dict<string, any> info): GebwebApp

Set the OpenAPI info object (title, version, description, etc.). Subsequent calls overwrite earlier values for the same keys.

Function useI18n

func useI18n(GebwebApp app, dict<string, any> opts = {...}): GebwebApp

Enable CSRF protection app-wide. opts.secret is required; cookieName / cookieOptions are optional. Once enabled, every state-changing method requires a valid token unless the route is @CsrfExempt. The token lives in the geb_csrf cookie and must be echoed in the X-CSRF-Token header or _csrf form field on POST/PUT/PATCH/DELETE. Mount the locale negotiator. opts accepts:

  • locales: list of supported BCP-47 tags. Default: ["en"].
  • default: fallback tag. Default: "en".
  • sources: ordered list of negotiation sources. Default: ["url", "cookie", "accept-language"].
  • cookieName: name of the sticky-choice cookie. Default: "gebweb_locale".
  • urlPrefix: when true, recognise a leading /<locale>/ path segment. Default: true.
  • urlStrip: when true and a URL prefix matched, rewrite request["path"] to drop the prefix so routes stay locale-agnostic. Default: true.
  • defaultZone: IANA time-zone name applied to the resolved Locale when the tag does not carry one.

The resolved Locale is stored at request["_locale"] and is injected into handlers that declare a parameter of type i18n.Locale.

Function useTenant

func useTenant(GebwebApp app, callable resolver, dict<string, any> opts = {...}): GebwebApp

Mount the tenant resolver. resolver(request) returns a Tenant value (or null when no tenant could be determined). The resolved tenant lives on request["_tenant"] and is injected into handlers that declare a Tenant parameter. When opts.required is true (the default) a null resolution short-circuits the request with a 400 problem document; set to false to let the request continue without a tenant.

Function useOidc

func useOidc(GebwebApp app, dict<string, any> opts): GebwebApp

Mount liveness + readiness endpoints. Walks instances for @HealthCheck methods and registers them. The endpoints default to /healthz (liveness) and /readyz (readiness); override with opts.livenessPath / opts.readinessPath. Each /healthz or /readyz hit runs every registered probe of that kind, returning 200 + JSON when all pass, 503 otherwise. Mount one or more OIDC / OAuth2 providers. Each provider gets a callback route at <callbackPathPrefix>/<provider.name>/callback (default prefix /auth). On a successful callback the framework exchanges the code with PKCE, validates the ID token (or fetches the user profile for GitHub), invokes opts.userResolver(claims, provider) to build the session data, saves it via the session store, and redirects to successRedirect.

Function oidcLoginUrl

func oidcLoginUrl(GebwebApp app, string providerName, any request): dict<string, any>

Build the authorization URL for providerName. Returns {url, stateCookie}; redirect the browser to url and write stateCookie as the geb_oidc cookie.

Function useWebhooks

func useWebhooks(GebwebApp app, dict<string, any> opts = {...}): GebwebApp

Mount the outbound webhook dispatcher. Requires useJobs(app, ...) (the dispatch path enqueues a job per subscription). Returns the same app so the call chains with other use* setup.

Function subscribeWebhook

func subscribeWebhook(GebwebApp app, string event, string url, string secret = ""): webhooksmod.WebhookSubscription

Add a subscription. Returns the new WebhookSubscription. useWebhooks must have been called first.

Function unsubscribeWebhook

func unsubscribeWebhook(GebwebApp app, string event, string url): bool

Function dispatchWebhook

func dispatchWebhook(GebwebApp app, string event, dict<string, any> payload): int

Dispatch event to every subscriber. Each delivery is queued as a separate job (see useJobs); failures retry with the job queue's configured backoff, and the configured deadLetter callback fires after the final attempt.

Function useServerTiming

func useServerTiming(GebwebApp app): GebwebApp

Mount Server-Timing emission. Registers a before-middleware that primes a per-request timing list and an after-middleware that encodes it into the Server-Timing response header. Application code adds entries via gebweb.recordTiming / gebweb.measureTiming.

Function recordTiming

func recordTiming(any request, string label, int durationMs): void

Function measureTiming

func measureTiming(any request, string label, callable fn): any

Function useEtag

func useEtag(GebwebApp app, dict<string, any> opts = {...}): GebwebApp

Mount the ETag middleware. On every 2xx response with a body within the configured size window, compute a weak SHA-256 ETag and respond 304 when the request's If-None-Match matches.

Function useHealth

func useHealth(GebwebApp app, list<any> instances, dict<string, any> opts = {...}): GebwebApp

Function t

func t(GebwebApp app, any locale, string key, dict<string, any> args = {...}): string

Translate key for the given locale (a tag like "en" or a Locale instance), substituting {name} placeholders from args. Falls back to the configured default locale, then to the key itself when no translation is found.

Function useCsrf

func useCsrf(GebwebApp app, dict<string, any> opts = {...}): GebwebApp

Function useSecurity

func useSecurity(GebwebApp app, dict<string, any> opts = {...}): GebwebApp

Mount browser-security headers. opts accepts:

  • csp - dict of CSP directives in camelCase (defaultSrc, scriptSrc, ...). Each value is a list of source expressions. The literal 'nonce' expands to 'nonce-<value>' per request and the nonce is auto-published as cspNonce in the view context.
  • cspReportOnly - bool. Switches to the report-only header.
  • hsts - dict with maxAge, includeSubdomains, preload. Omitted means no HSTS header (correct for dev).
  • frameOptions - string, defaults to "DENY". Set "" to suppress the header.
  • referrerPolicy - string, defaults to "strict-origin-when-cross-origin". Set "" to suppress.
  • contentTypeOptions - bool, defaults to true. Emits X-Content-Type-Options: nosniff.

Function app

func app(list<any> controllers = [], ?dict<string, any> opts = null): GebwebApp

Build a Gebweb app from a list of entries. Each entry may be one of three things:

  • an already-constructed controller instance
  • a controller class reference (DI auto-wires it)
  • a resource class decorated with @ApiResource (the framework generates the six CRUD endpoints and resolves the repository via DI from the class's static repositoryClass() method)

Controllers are processed first so any explicit @Get/@Post on a resource path takes precedence over the auto-generated route. SwaggerUI mounts at /docs and the spec at /openapi.json unless docs are disabled (see docsEnabled). Returns the app value to pass into serve or the TestClient.

Function loadConfig

func loadConfig(GebwebApp app, string configPath = "config/services.yaml"): GebwebApp

Loads YAML configuration into the app. Reads parameters, services, and bindings sections from configPath (and any imports + per-env overlay) and writes them onto the app. The parameter store is populated immediately; service and binding entries are stashed for the container wiring that runs during controller resolution (steps 5+ of the bundle).

Function addControllers

func addControllers(GebwebApp app, list<any> controllers): GebwebApp

Function registerPerRequest

func registerPerRequest(GebwebApp app, any classRef, callable factory): GebwebApp

Register a factory for a service class with this app's DI container. The factory is called at most once per app; the returned instance is reused for every controller constructor that asks for the type.

Function register

func register(GebwebApp app, any classRef, callable factory): GebwebApp

Function registerInstance

func registerInstance(GebwebApp app, any classRef, any instance): GebwebApp

Register an explicit pre-built instance for a service class. Useful for tests that want to stub out a dependency.

Function resolve

func resolve(GebwebApp app, any classRef): any

Resolve a class via the app's DI container directly. Mostly useful from tests and from extension code; routes get their controllers via app(...) automatically.

Function registerAssertion

func registerAssertion(GebwebApp app, string name, callable validator): GebwebApp

Register a custom @Assert. validator on the app. The validator is a callable receiving (value, positional args, named args) and returning null on success or an error-message string on failure.

Function useAuthenticator

func useAuthenticator(GebwebApp app, any userClass, callable authenticator): GebwebApp

Register an authenticator on the app. userClass is the class the framework should inject into handler parameters of that type (so user injection by type works on Geblang's typed parameter list without parameter-level decorators). The authenticator is a callable that takes the request dict and returns either the user value (any user-defined class) or null when authentication fails - the framework converts a null return into a 401 for any handler that carries @Auth or @RequiresRole. Subsequent calls replace the previous authenticator on the same app.

Function useApiKeyAuth

func useApiKeyAuth(GebwebApp app, any userClass, callable resolveByKey): GebwebApp

Wire an API-key authenticator on the app. The framework reads the key from the X-API-Key header (preferred) or the Authorization: Bearer <key> header (fallback). resolveByKey is a callable (string key): ?userClass that maps a key to a user value (or null when the key isn't valid).

The OpenAPI security scheme is set to apiKey (in header, named X-API-Key) instead of the default bearer/JWT scheme, so the generated spec describes the actual auth flow.

gebweb.useApiKeyAuth(app, ServiceAccount, func(string key): ?ServiceAccount { if (!keys.contains(key)) { return null; } return keys[key] as ServiceAccount; });

Function usePermissions

func usePermissions(GebwebApp app, callable extractor): GebwebApp

Override the permission extractor on the app's auth config. The callable receives the authenticated user value and returns list<string> - the permissions the user holds. The default extractor reads user.permissions; register a custom one when permissions live elsewhere (e.g. resolved from a database lookup by user id).

Function useMaxBodyBytes

func useMaxBodyBytes(GebwebApp app, int maxBytes): GebwebApp

Wire a session-backed authenticator on the app. store is any value with a load(request): dict<string, any> method - the stdlib provides web.session.{redisSessionStore, fileSessionStore, databaseSessionStore}. userClass is the class the framework injects into typed handler parameters. fromSession is a callable (dict<string, any> data): ?userClass that turns the loaded session dict into a user value (or null when the session is present but the data is not a valid user - e.g. tampered).

An empty session dict from store.load (no geb_sid cookie, or an expired entry) maps directly to a 401 without calling fromSession. The default OpenAPI security scheme is swapped to a cookie-based cookieAuth (apiKey / cookie / geb_sid) since the JWT bearer default doesn't describe a session-cookie flow.

import gebweb; import web.session as session;

class CurrentUser { string id; string name; list roles; }

let store = session.fileSessionStore("/tmp/app-sessions", 3600); gebweb.useSessionAuth(app, store, CurrentUser, func(dict<string, any> data): ?CurrentUser { if (!data.contains("id")) { return null; } return CurrentUser( data["id"] as string, (data["name"] ?? "") as string, (data["roles"] ?? []) as list); });

Login/logout flow stays the user's responsibility - call store.save(response, data, options) from the login handler and store.clear(response, request) from the logout handler. Register a response cache store on the app. store is any value with get(key): any and set(key, value): bool methods - the stdlib provides web.cache.{redisCacheStore, fileCacheStore, databaseCacheStore}. Once registered, any handler (or controller class) carrying @Cache(ttl: N) or @Cache(ttl: N, vary: [...]) opts the route into response caching: a cache hit short-circuits binding + handler dispatch, while a miss runs the handler and writes the (2xx) response back. The ttl named arg overrides the store's coarser TTL via an inner envelope; vary lists header names that augment the cache key (e.g. Authorization for per-user caches). Subsequent calls replace the previous store.

import gebweb; import web.cache as cachemod;

let store = cachemod.fileCacheStore("/tmp/app-cache", 3600); gebweb.useCacheStore(app, store);

class FeedController { @Get("/feed") @Cache(ttl: 60) func feed(): dict<string, any> { return expensiveLookup(); } } Set the app-wide request body cap in bytes (default 10 MB). The cap is enforced at the HTTP server (413 before any handler work) and in the dispatcher for in-process clients. 0 disables the cap. A route can lower it further with @MaxBody(bytes).

Function useMetrics

func useMetrics(GebwebApp app, dict<string, any> opts = {...}): GebwebApp

Mount a Prometheus metrics endpoint (default /metrics) fed by per-route request counters, latency totals, and an in-flight gauge. Protect the path at the proxy or with middleware if it should not be public.

Function useOps

func useOps(GebwebApp app, list<any> instances = [], dict<string, any> opts = {...}): GebwebApp

The production endpoint bundle: health liveness/readiness probes (gebweb.useHealth) plus the Prometheus metrics endpoint (gebweb.useMetrics) in one call.

Function bindConfig

func bindConfig(GebwebApp app, any configClass, dict<string, any> opts = {...}): any

Wire the request-context convention: every request gets a correlation id (inbound X-Request-Id or generated), readable via req.requestId(), echoed on the response, and bindable into a per-request logger with gebweb.requestLogger(req). Hydrate configClass from environment variables and the app's parameter store, validating @Assert constraints. Required fields with no value throw at boot, naming the env var to set.

Function cacheInvalidate

func cacheInvalidate(GebwebApp app, string tag): int

Drop every cached response recorded under tag (see @Cache(tags: [...])). Returns the number of entries removed.

Function useJwks

func useJwks(GebwebApp app, any keys, dict<string, any> opts = {...}): GebwebApp

Mount a JWKS document (default /.well-known/jwks.json) exposing the app's public signing keys. keys is a list accepted by crypt.jwks (PEM strings, {pem, kid, alg} dicts, or ready JWK dicts) or a prebuilt JWKS dict. The document is rendered once at mount time.

Function useRequestContext

func useRequestContext(GebwebApp app): GebwebApp

Function useCacheStore

func useCacheStore(GebwebApp app, any store): GebwebApp

Function useIdempotencyStore

func useIdempotencyStore(GebwebApp app, any store): GebwebApp

Function useViews

func useViews(GebwebApp app, string dir = "templates"): GebwebApp

Attach a view engine rooted at dir. Templates are loaded relative to that directory via gebweb.view(app, name, ctx).

Function preloadViews

func preloadViews(GebwebApp app, list<string> names): GebwebApp

Compile named templates now in production; development remains lazy.

Function views

func views(GebwebApp app): ?viewsmod.ViewEngine

Returns the registered view engine or null.

Function useJobs

func useJobs(GebwebApp app, db.Connection conn, dict<string, any> opts): GebwebApp

Attach a background-job queue to the app, backed by conn. Auto-creates the gebweb_jobs table if missing. Options:

  • pollIntervalMs (default 1000)
  • maxAttempts (default 5)
  • backoffMs (default [1s, 5s, 30s, 2m, 10m])

Function jobs

func jobs(GebwebApp app): ?jobsmod.JobConfig

Returns the registered job config or null.

Function useScheduler

func useScheduler(GebwebApp app, dict<string, any> opts): GebwebApp

Attach a scheduler to the app. Uses the connection from the already-registered job queue (or, when conn is provided explicitly, that connection). Options: tickIntervalMs, leaseSec, workerId.

Function scheduler

func scheduler(GebwebApp app): ?schedmod.ScheduleConfig

Returns the registered scheduler config or null.

Function useEvents

func useEvents(GebwebApp app): GebwebApp

Attach the in-process event bus to the app.

Function events

func events(GebwebApp app): ?eventsmod.EventConfig

Returns the registered event bus or null.

Function useMessaging

func useMessaging(GebwebApp app): GebwebApp

Lazily attach the broker-messaging registry. Safe to call multiple times - subsequent calls reuse the existing config.

Function messaging

func messaging(GebwebApp app): ?messagingmod.MessagingConfig

Returns the registered messaging config or null.

Function useMailer

func useMailer(GebwebApp app, mailingmod.MailerContract transport): GebwebApp

Attach a mailer transport. Also registers the _gebweb_mailer_deliver job handler when a job queue is available, so gebweb.send can defer delivery.

Function mailer

func mailer(GebwebApp app): ?mailingmod.MailerContract

Returns the registered mailer transport or null.

Function useLlm

func useLlm(GebwebApp app, llmmod.Client client): GebwebApp

Attach an LLM client (any llm.Client implementation). The client is then resolvable through the DI container so handler constructors can ask for llm.Client directly.

Function llm

func llm(GebwebApp app): ?llmmod.Client

Returns the registered LLM client or null.

Function service

func service(GebwebApp app, string id): any

Resolves a service by its registered string id. Services get ids via @Service("id") on the class (or the bare class name when the decorator carries no argument). The instance is built through the normal autowire path.

Function hasService

func hasService(GebwebApp app, string id): bool

True when a service with this id is registered.

Function serviceIds

func serviceIds(GebwebApp app): list<string>

All registered service ids.

Function interfaceBindings

func interfaceBindings(GebwebApp app): dict<string, string>

All registered interface->service-id bindings.

Function taggedServices

func taggedServices(GebwebApp app, string tag): list<any>

Resolve every service carrying tag, in service-registration order. Each instance is built through service(app, id) so per-service shared/transient policy still holds.

Function taggedServiceIds

func taggedServiceIds(GebwebApp app, string tag): list<string>

Service ids carrying tag, in registration order, without resolving the instances. Useful when the consumer wants to inspect the tag set or defer construction.

Function tagsForService

func tagsForService(GebwebApp app, string id): list<string>

Tags attached to a service id, in insertion order.

Function useSecrets

func useSecrets(GebwebApp app, secretsmod.SecretsProvider provider): GebwebApp

Attach a secrets provider so %secret(...)% markers in YAML parameters resolve. Built-in: gebweb.encryptedFileSecrets(path); custom providers implement SecretsProvider.

Function secrets

func secrets(GebwebApp app): ?secretsmod.SecretsProvider

Returns the registered secrets provider or null.

Function useStorage

func useStorage(GebwebApp app, storagemod.StorageContract backend): GebwebApp

Attach a storage backend (memory, local disk, custom).

Function storage

func storage(GebwebApp app): ?storagemod.StorageContract

Returns the registered storage backend or null.

Function useDocsAuth

func useDocsAuth(GebwebApp app, callable guard): GebwebApp

Register a session store. Required for flash messages and form-state rehydration. Any value with load(request) and save(response, data, opts) methods works (the stdlib provides FileSessionStore / RedisSessionStore / DatabaseSessionStore). useSessionAuth() also calls this internally so you don't need to register twice. Protect /docs and /openapi.json with a guard. The guard is a callable that receives the raw request dict and returns either null (pass-through) or a response dict (deny + short-circuit).

Pass any of the framework-provided builders or any custom callable that matches the contract:

gebweb.useDocsAuth(app, gebweb.basicAuthGuard("admin", "s3cret")); gebweb.useDocsAuth(app, gebweb.bearerTokenGuard("expected")); gebweb.useDocsAuth(app, gebweb.requireAppAuth(app)); gebweb.useDocsAuth(app, func(dict<string, any> req): ?dict<string, any> { // custom: check a header, IP allow-list, etc. return null; });

Set BEFORE the call to gebweb.serve so the guard wraps both docs routes at app-build time.

Function basicAuthGuard

func basicAuthGuard(string user, string password): callable

Builds a HTTP Basic-Auth guard. Compares the supplied user + password using constant-time comparison; on mismatch returns a 401 response with the WWW-Authenticate challenge.

Function bearerTokenGuard

func bearerTokenGuard(string expected): callable

Builds a Bearer-token guard with a hard-coded expected token. Useful for sharing a single shared-secret token (read-only API keys, CI access, etc.). For JWT-based protection that ties into the app's existing authenticator, use requireAppAuth(app) instead.

Function requireAppAuth

func requireAppAuth(GebwebApp app, list<string> requiredRoles = []): callable

Builds a guard that reuses the app's configured authenticator (whatever useAuthenticator, useJWT, useSessionAuth, etc. registered). Returns 401 when authentication fails; if requiredRoles is non-empty, returns 403 when the user has none of the listed roles.

// Any authenticated user gebweb.useDocsAuth(app, gebweb.requireAppAuth(app));

// Only users with the api_admin role gebweb.useDocsAuth(app, gebweb.requireAppAuth(app, ["api_admin"]));

// Multiple acceptable roles - any one matches gebweb.useDocsAuth(app, gebweb.requireAppAuth(app, ["api_admin", "owner"]));

Throws RuntimeError at registration time if the app has no authenticator configured.

Function useSession

func useSession(GebwebApp app, any store): GebwebApp

Function session

func session(GebwebApp app): ?any

Function useAdmissionControl

func useAdmissionControl(GebwebApp app, dict<string, any> opts): GebwebApp

Bound concurrent in-flight requests. When more than opts.maxConcurrent are being served, further requests get a 503 before any handler runs, so a load spike sheds load instead of exhausting memory. Set opts.onOverload to a (): response callable to customise the rejection. Wire it only with a value measured against per-request memory under load.

Function useStaticAssets

func useStaticAssets(GebwebApp app, string dir, dict<string, any> opts = {...}): GebwebApp

Mount a directory of static assets with content-hash fingerprinting. Files served from dir are accessible under opts.urlPrefix (default /assets) with a cache-busting hash in the filename: app.css -> /assets/app-7b2f9c4d.css. The asset() view helper resolves logical names to fingerprinted URLs.

Options:

  • urlPrefix: URL prefix for served files (default "/assets")
  • cacheControl: response header (default long-cache immutable)
  • fingerprint: set false to skip hashing (default true)
  • dev: set true to recompute hashes per request and also accept unhashed names (default false)

Function assets

func assets(GebwebApp app): ?assetsmod.AssetConfig

Function useSessionAuth

func useSessionAuth(GebwebApp app, any store, any userClass, callable fromSession): GebwebApp

Function useRoleExtractor

func useRoleExtractor(GebwebApp app, callable extractor): GebwebApp

Override the default role extractor (which reads .roles off the user value). The extractor takes the user value and returns the user's roles as list<string>. Useful when the user value is a dict, an opaque type, or stores roles under a different field. Must be called AFTER useAuthenticator.

Function useSecurityScheme

func useSecurityScheme(GebwebApp app, string name, dict<string, any> definition, bool setAsDefault): GebwebApp

Register (or replace) an OpenAPI security scheme on the app. The default useAuthenticator call already registers a bearerAuth scheme (HTTP / bearer / JWT). Call this to declare an additional scheme - e.g. API-key in header, OAuth2 - or to override the default. Pass setAsDefault: true to make this the scheme attached to every @Auth / @RequiresRole-gated operation. Must be called AFTER useAuthenticator.

gebweb.useSecurityScheme(app, "apiKey", { "type": "apiKey", "in": "header", "name": "X-API-Key", }, true);

Function use

func use(GebwebApp app, callable mw): GebwebApp

Register a response-phase middleware. The callable takes (request, response) and returns the (possibly transformed) response. Use this for CORS headers, security headers, request logging, response compression, etc.

Function before

func before(GebwebApp app, callable mw): GebwebApp

Register a request-phase middleware. The callable takes a rich Request and returns either null (continue to the handler) or a Response (short-circuit). Use this for auth gates, rate-limit checks, anything that needs to reject a request before it reaches the typed handler.

Function after

func after(GebwebApp app, callable mw): GebwebApp

Alias of use for readability when registering response-phase middleware near other after-handler code.

Function plugin

func plugin(GebwebApp app, pluginmod.PluginContract pluginInstance): GebwebApp

Register a plugin on the app. A plugin is any value with an install(app) method (typically a class extending gebweb.Plugin). The plugin is appended to app.plugins and install is invoked immediately so the plugin can register middleware, mount routes, configure authenticators, or extend the assertion registry through the existing public API.

Plugins are the standard extension point for sibling Geblang packages (e.g. gebweb-auth-oauth2) - they keep the core lean while letting opt-in features ship out-of-tree.

Function findPlugin

func findPlugin(GebwebApp app, string name): ?pluginmod.PluginContract

Find a registered plugin by name (matches plugin.name()). Returns the first match or null. Useful for plugins that want to look up peer plugins, and for tests that want to inspect installed plugins.

Function validateInstance

func validateInstance(GebwebApp app, any instance): list<validation.ValidationError>

Run the app's @Assert validators against an instance and return the list of failures (empty when the instance is valid). Called by binding.gb / resource.gb after body deserialization; user code can call it directly to validate values constructed outside the request path.

Function dispatcher

func dispatcher(GebwebApp app): callable

Returns the dispatch callable that runs a request through the registered routes. Suitable for handing to http.serve, http.listen, or for direct use by TestClient.

Function serve

func serve(GebwebApp app, string address, ?dict<string, any> opts = null): void

Serve the app on the given address. Blocks until the server stops. opts is forwarded to http.serve and accepts the same shape:

  • {reactor: true} to use the epoll/kqueue reactor backend (high-throughput, low memory under many concurrent connections).
  • {maxConns: N} to cap the goroutine pool when the default goroutine-per-connection model would push too much memory.
  • {overload: "drop"|"reject"|"queue"} to choose backpressure behaviour under reactor mode.

Pass null (the default) to use the goroutine-per-connection backend with no caps.

Function listen

func listen(GebwebApp app, string address, ?dict<string, any> opts = null): int

Start the app on the given address in the background, returning a handle (int64) suitable for passing to http.shutdown or http.close. opts accepts the same shape as serve for reactor / concurrency tuning.

Function trackServerHandle

func trackServerHandle(GebwebApp app, int handle): void

Record a listener handle so gebweb.shutdown drains it. listen calls this itself; register auxiliary listeners (HTTP-to-HTTPS redirects, extra ports) here too.

Function shutdown

func shutdown(GebwebApp app, dict<string, any> opts = {...}): void

Gracefully drain and stop the app's server: readiness flips to 503 (rolling deploys stop sending traffic), in-flight requests finish within opts.timeoutMs (default 10000), then the listener closes and any gebweb.serve / http.wait callers return. Safe to call from a signal handler.

Function isDraining

func isDraining(GebwebApp app): bool

True once gebweb.shutdown has started. Long-running loops (job workers, scheduler ticks) should exit when this flips.

Function router

func router(GebwebApp app): dict<string, any>

Exposes the underlying stdlib/web router for power users.

Function routes

func routes(GebwebApp app): list<dict<string, any>>

Returns the registered route table for introspection.

gebweb/src/assets.gb

Class AssetConfig

class AssetConfig

Per-app asset config. Holds the source directory, the URL prefix, response cache header, and the cached manifest.

Field sourceDir

string sourceDir

Field urlPrefix

string urlPrefix

Field cacheControl

string cacheControl

Field fingerprint

bool fingerprint

Field dev

bool dev

Field realRoot

string realRoot

Field manifest

dict<string, string> manifest

Field reverseMap

dict<string, string> reverseMap

Method AssetConfig

func AssetConfig(string sourceDir, dict<string, any> opts)

Function newConfig

func newConfig(string sourceDir, dict<string, any> opts): AssetConfig

Function assetUrl

func assetUrl(AssetConfig cfg, string logical): string

Look up the fingerprinted URL for a logical asset name. The lookup builds the entry on first call, caches it (in dev mode the cache is invalidated by the file's mtime; in prod the cache is permanent).

Function serveAsset

func serveAsset(AssetConfig cfg, dict<string, any> request): dict<string, any>

Build a request handler for the asset URL prefix. Reads the file from disk, returns it with the configured cache headers. 404 for unknown / unfingerprinted requests in prod mode; dev mode allows raw (non-fingerprinted) names through too.

Function makeAssetHandler

func makeAssetHandler(AssetConfig cfg): callable

gebweb.auth

Source: gebweb/src/auth.gb

Class AuthConfig

class AuthConfig

Holds the authenticator + role / permission extractors for a Gebweb app.

Field userClass

any userClass

Field authenticator

callable authenticator

Field roleExtractor

callable roleExtractor

Field permissionExtractor

callable permissionExtractor

Field securitySchemes

dict<string, any> securitySchemes

Field defaultSchemeName

string defaultSchemeName

Method AuthConfig

func AuthConfig(any userClass, callable authenticator, callable roleExtractor)

Function defaultPermissionExtractor

func defaultPermissionExtractor(any user): list<string>

Default permission extractor. Reads .permissions off the user value as a list<string>. Returns an empty list when the user doesn't expose permissions (so @RequiresPermission will deny by default).

Function defaultRoleExtractor

func defaultRoleExtractor(any user): list<string>

Default role extractor. Reads .roles off the user value as a list<string>. Returns an empty list when the user doesn't expose roles (so @RequiresRole will deny by default).

Function newConfig

func newConfig(any userClass, callable authenticator): AuthConfig

Build an AuthConfig with the default role extractor. Pass a non-null roleExtractor to override.

Function requiresAuth

func requiresAuth(any controllerClass, any handler): bool

True when the handler or its enclosing class carries an @Auth decorator OR a @RequiresRole(...) decorator (which implies Auth). The class-level decorator is reachable through the already-resolved class value passed in; null is tolerated for cases where the route has no enclosing class (e.g. synthetic resource routes).

Function requiredRoles

func requiredRoles(any controllerClass, any handler): list<string>

Returns the union of roles named in any @RequiresRole on the handler or its controller class. An empty list means "any authenticated user is allowed" (just @Auth, no role gate).

Function anyRoleMatches

func anyRoleMatches(list<string> userRoles, list<string> required): bool

True when at least one of userRoles matches one of required. OR semantics: any-of, not all-of. An empty required list is treated as "no role gate" by the caller, so this helper is only invoked with a non-empty required list.

Function requiredPermissions

func requiredPermissions(any controllerClass, any handler): list<list<string>>

Returns the union of permissions named in any @RequiresPermission on the handler or its controller class. An empty list means "no permission gate" (use @Auth alone for that).

Multiple @RequiresPermission("a") @RequiresPermission("b") decorators on the same target combine: the user must hold AT LEAST ONE matching permission. Use AND semantics by writing @RequiresPermission("a", "b") in a single decorator (all listed must be held).

Function allPermissionsHeld

func allPermissionsHeld(list<string> userPerms, list<list<string>> groups): bool

Returns true when the user holds the permissions required by EVERY group (groups are AND-combined; within a group, ALL listed permissions must be held). An empty group list means "no permission gate".

Function userClassName

func userClassName(?AuthConfig cfg): string

Returns the class name of the registered user class, or "" when the app has no authenticator configured. Used by the binder to recognise user-injection slots in a handler's parameter list.

Function securitySchemes

func securitySchemes(?AuthConfig cfg): dict<string, any>

Returns the components.securitySchemes dict the OpenAPI spec should publish, or {} when the app has no auth configured.

Function defaultSchemeName

func defaultSchemeName(?AuthConfig cfg): string

Returns the security-scheme name to attach to every gated operation, or "" when the app has no auth configured.

Function registerSecurityScheme

func registerSecurityScheme(AuthConfig cfg, string name, dict<string, any> definition, bool setAsDefault): void

Register (or replace) a security scheme on the AuthConfig. Pass setAsDefault: true to also make this scheme the one attached to every gated operation.

gebweb.authz

Source: gebweb/src/authz.gb

Function registerPolicies

func registerPolicies(any app, list<any> instances): void

Function authorize

func authorize(any app, any request, string action, any subject): any

Function authorizeIfPolicy

func authorizeIfPolicy(any app, any request, string action, any subject): void

Function can

func can(any app, any request, string action, any subject): bool

Function canChecksFor

func canChecksFor(any controllerClass, any handler): list<dict<string, string>>

Function enforceCan

func enforceCan(any app, any user, string action, string typeName): void

gebweb.binding

Source: gebweb/src/binding.gb

Function nativePathTemplate

func nativePathTemplate(string tmpl): string

Translates /users/{id}/posts/{slug} to /users/:id/posts/:slug for the native web router, which uses :name placeholders.

Function parseQueryString

func parseQueryString(string raw): dict<string, string>

Parses a raw query string ("a=1&b=hello&c=") into a dict. Repeated keys keep the last value; the dict shape leaves room for a future list-valued variant.

Function handlerParameters

func handlerParameters(any handler): list<dict<string, any>>

Returns the parameter metadata list for a handler method, suitable for building a binder. Always wraps reflect.parameters so the caller treats it as a list.

Function routingDecoratorAction

func routingDecoratorAction(dict<string, any> param): ?dict<string, any>

Function isRawHandler

func isRawHandler(list<dict<string, any>> params): bool

True when the handler is a raw-escape-hatch handler: a single parameter typed as the raw request (dict<string, any>, dict, any, Request). A handler with a single list<UserDTO> or other body-shaped parameter is NOT raw - it gets auto-bound.

Function bodyParameterIndex

func bodyParameterIndex(list<dict<string, any>> params, list<string> pathParamNames, string userClassName): int

Returns the index of the parameter that should receive the request body, or -1 if none. A parameter qualifies when its type names a user-defined class (or a list<UserDTO> collection of them).

The userClassName is the class the framework injects the authenticated user into; a parameter of that exact type is not a body parameter (it's the user-injection slot). Pass "" when the app has no auth configured to keep the old behaviour.

Throws BadRequestError at registration time if a single handler has two body-shaped parameters: the framework can only bind one request body and silently choosing the first hides bugs.

Function coerceQueryValue

func coerceQueryValue(string raw, string declaredType): any

Coerces a query-string value into the declared parameter type. Conversion failures are wrapped in BadRequestError so the client receives a 400 rather than a 500.

Function bindArguments

func bindArguments(any handler, dict<string, any> request, list<string> pathParamNames, any user, string userClassName): list<any>

Function bindArgumentsWithParams

func bindArgumentsWithParams(list<dict<string, any>> params, dict<string, any> request, list<string> pathParamNames, any user, string userClassName): list<any>

As bindArguments, over precomputed parameter metadata (RouteMeta).

Function makeRouteAdapter

func makeRouteAdapter(any handler, list<string> pathParamNames, validation.AssertionRegistry assertions): callable

Builds the raw-dict adapter that stdlib/web's router calls. The adapter binds arguments, runs @Assert validation on any body argument that resolved to a user class, invokes the handler, catches HttpException and converts to a Problem Details response, and serializes the return value to a JSON response dict. The assertions registry is the app's; passing it through lets every controller in an app share one set of registered validators.

Kept for back-compat; new code should use makeRouteAdapterWithAuth, which threads the auth config through (this delegates to it with a null auth, so @Auth is a no-op).

Function makeRouteAdapterWithAuth

func makeRouteAdapterWithAuth(any handler, ?any controllerClass, list<string> pathParamNames, validation.AssertionRegistry assertions, callable authLookup): callable

As makeRouteAdapter but also threads the controller-class value and the app's optional AuthConfig. When the handler or its controller class carries @Auth / @RequiresRole, the adapter runs the authenticator first; failures map to 401 / 403 and short-circuit before argument binding. When auth succeeds, the resolved user is injected into any handler parameter whose type matches the registered user class.

Function routeMeta

func routeMeta(any handler, ?any controllerClass): dict<string, any>

Route-static facts computed once at registration so the per-request path does no reflection: decorator scans (cache / websocket / sse / auth requirements), handler parameter metadata, and the raw-handler shape. The auth-dependent body index is memoised on first use (the auth config is wired lazily, after app construction).

Function makeRouteAdapterFull

func makeRouteAdapterFull(any handler, ?any controllerClass, list<string> pathParamNames, validation.AssertionRegistry assertions, callable authLookup, callable cacheLookup, callable idempotencyLookup, callable formRehydration, callable canEnforcer): callable

Full-fat adapter that also threads the app's optional CacheConfig. Pure handler-level inputs (auth, validation, binding) are unchanged from makeRouteAdapterWithAuth; this variant additionally consults the registered cache store before binding when the handler (or its controller class) carries @Cache, and writes the response back on a miss.

gebweb.broadcast

Source: gebweb/src/broadcast.gb

Class Subscription

class Subscription

Goroutine-safe broadcast hub for WebSocket fan-out. A mutex guards the subscriber set so concurrent connection handlers can join, leave, and broadcast at once; sends happen outside the lock (on a snapshot) so a slow connection cannot block membership changes. The engine serialises writes to a single connection via a per-handle mutex, so a publisher in one connection's handler can safely call sendText() on another.

class ChatController { broadcast.Hub hub; func ChatController(broadcast.Hub hub) { this.hub = hub; }

@Get("/ws/chat") @WebSocket func chat(ws.Connection conn): void { let sub = this.hub.join(conn); try { while (true) { let msg = conn.readText(); if (msg == "") { break; } this.hub.broadcast(msg); } } catch (Error e) { } this.hub.leave(sub); conn.close(); } }

Field id

int id

Field conn

any conn

Method Subscription

func Subscription(int id, any conn)

Class Hub

class Hub

Field nextId

int nextId

Field subscribers

list<Subscription> subscribers

Field _lock

sync.Mutex _lock

Method Hub

func Hub()

Method join

func join(any conn): Subscription

Method leave

func leave(Subscription sub): void

Method broadcast

func broadcast(string msg): int

Send msg to every current subscriber. Returns the number of connections that received the message. Sends that fail silently drop the subscriber. Membership is snapshotted under the lock and sends run unlocked, so a slow send never blocks join/leave.

Method broadcastExcept

func broadcastExcept(string msg, Subscription except): int

Same as broadcast() but excludes the supplied subscription.

Method size

func size(): int

Current number of active subscribers.

Method _snapshot

func _snapshot(): list<Subscription>

Method _prune

func _prune(list<int> deadIds): void

Function newHub

func newHub(): Hub

Convenience constructor for use inside gebweb.register(...).

gebweb.cache

Source: gebweb/src/cache.gb

Class CacheConfig

class CacheConfig

Holds the cache store plus the tag state. When the store provides cross-process tags (supportsTags()), generations and the key index live in the shared store and invalidation is distributed; otherwise they live in a thread-safe per-app index (process-local).

Field store

any store

Field tagIndex

storemod.Store tagIndex

Field sharedTags

bool sharedTags

Method CacheConfig

func CacheConfig(any store)

Function findCacheDecorator

func findCacheDecorator(?any controllerClass, any handler): ?dict<string, any>

Returns the @Cache decorator dict on the handler (or its controller class) or null when the route is not cached. A handler-level decorator wins over a class-level one.

Function ttlFromDecorator

func ttlFromDecorator(dict<string, any> decorator): int

Returns the per-route TTL in seconds. Reads @Cache(ttl: N) or @Cache(N) positional. Returns 0 when no TTL is set, meaning "let the store's own TTL apply".

Function varyFromDecorator

func varyFromDecorator(dict<string, any> decorator): list<string>

Returns the Vary header names declared on the decorator. Reads the vary named arg as either a single string or a list of strings. Empty list means the response varies only by method+path.

Function tagsFromDecorator

func tagsFromDecorator(dict<string, any> decorator): list<string>

Builds a cache key from the request method+path and the values of the listed Vary headers. Vary keys are sorted for determinism regardless of decorator argument order. tags named arg of @Cache as a list (single string accepted).

Function resolveTags

func resolveTags(list<string> tags, dict<string, any> request): list<string>

Substitute {name} placeholders from the request's path params: user:{id} on /users/42 resolves to user:42.

Function indexTags

func indexTags(CacheConfig cfg, list<string> tags, string key): void

Record key under each tag's index entry so invalidation can find every response cached with that tag.

Function invalidateTag

func invalidateTag(CacheConfig cfg, string tag): int

Delete every cached response recorded under tag, then the index.

Function cacheKey

func cacheKey(dict<string, any> request, list<string> varyHeaders): string

Function envelope

func envelope(dict<string, any> response, int ttl, dict<string, any> tagGens = {...}): dict<string, any>

Wraps a response in a TTL envelope so per-route TTLs can be shorter than the store's own TTL. The envelope encodes the absolute Unix-epoch expiry; the store's lower-level TTL governs eventual eviction.

Function captureTagGenerations

func captureTagGenerations(CacheConfig cfg, list<string> tags): dict<string, any>

Function openEnvelope

func openEnvelope(any raw, ?CacheConfig cfg = null): ?dict<string, any>

Unwraps the envelope. Returns the cached response, or null when the envelope is expired or malformed.

gebweb.cli

Source: gebweb/src/cli.gb

Function resolveConfig

func resolveConfig(list<string> args, dict<string, any> opts): dict<string, any>

Resolves the effective server configuration from flags, environment, and option defaults. Pure given its inputs, so it is directly testable. Returns: {help, host, httpPort, tlsPort, domain, selfSigned, noTls, acmeEmail, acmeCache, httpMode, certOut, server, errors}.

Function redirectResponse

func redirectResponse(dict<string, any> request, string domain, string tlsPort): dict<string, any>

The 301 response a plain-HTTP sidecar listener answers when TLS is active. domain pins the target host (autocert); otherwise the request's own Host header is reused with the TLS port.

Function writeCertFile

func writeCertFile(int handle, string path): bool

Write the listener's certificate PEM (self-signed servers generate one at startup) to path so it can be added to a local trust store. Returns false when the server has no exportable certificate.

Function helpText

func helpText(string appName): string

Function serve

func serve(appmod.GebwebApp app, dict<string, any> opts = {...}): void

Serves app with the standard flag/env surface. opts provides the defaults (port, tlsPort, host, domain, selfSigned, noTls, acmeEmail, acmeCache, name, server) that flags and environment variables override. Blocks until the server stops or a termination signal arrives.

gebweb.config

Source: gebweb/src/config.gb

Function currentEnv

func currentEnv(): string

Active environment name. Reads GEBWEB_ENV; falls back to "prod" when unset or blank so production deployments do not accidentally pick up dev overlays.

Function loadConfigDict

func loadConfigDict(string configPath = "config/services.yaml"): dict<string, any>

Loads configPath, recursively pulls in any imports:, then merges the sibling overlay <stem>_${GEBWEB_ENV}.<ext> on top if present. Returns the combined dict; the caller decides what to do with the parameters / services / bindings sections.

gebweb.controller

Source: gebweb/src/controller.gb

Class Controller

class Controller

Field __app

?any __app

Method Controller

func Controller()

Method bindApp

func bindApp(any app): void

Framework hook: called by gebweb.app(...) after construction.

Method json

func json(any data, int status = 200): http.Response

2xx JSON response. status defaults to 200.

Method html

func html(any body, int status = 200, ?dict<string, any> headers = null): http.Response

HTML response. Body is sent verbatim.

Method text

func text(string body, int status = 200): http.Response

text/plain response.

Method created

func created(any data, string location): http.Response

201 Created with a Location header pointing at the resource.

Method accepted

func accepted(?any data = null): http.Response

202 Accepted. Use for async / queued work; body is optional.

Method noContent

func noContent(): http.Response

204 No Content - empty body.

Method stream

func stream(callable handler, ?dict<string, any> opts = null): dict<string, any>

Streamed response.

Method problem

func problem(int status, string title, string detail, ?dict<string, any> extras = null): http.Response

Arbitrary RFC 9457 Problem Details response.

Method redirect

func redirect(string location, int status = 302): http.Response

3xx redirect. Default 302 Found.

Method badRequest

func badRequest(string detail): void

Throws BadRequestError (400). Framework renders as Problem Details.

Method unauthorized

func unauthorized(string detail): void

Throws UnauthorizedError (401).

Method forbidden

func forbidden(string detail): void

Throws ForbiddenError (403).

Method notFound

func notFound(string detail): void

Throws NotFoundError (404).

Method conflict

func conflict(string detail): void

Throws ConflictError (409).

Method unprocessable

func unprocessable(string detail, list<dict<string, any>> errs): void

Throws UnprocessableEntityError (422) with field-level errors.

Method view

func view(any request, string name, dict<string, any> context = {...}, int status = 200): http.Response

Render the named template against context and return a 200 HTML response. Threads request through the view-context injectors so csrf, flashes, errors, oldInput, cspNonce, asset map, etc. are auto-injected. User keys in context win over injectors when names collide.

Method partial

func partial(any request, string name, dict<string, any> context = {...}): http.Response

Render name and return an HTML fragment - identical to view but the response sets Vary: HX-Request and the template author is expected to skip the layout. Use for HTMX / Turbo-Frame partials. The route can branch on the HX-Request header to choose between view() and partial().

Method back

func back(any request, string fallback = "/"): http.Response

303 redirect to the request's Referer header, or fallback.

Method flash

func flash(any request, dict<string, any> response, string category, string message): dict<string, any>

Attach a flash message to response, persisted in the session for the next request. Requires gebweb.useSession(app, store).

Method redirectWithFlash

func redirectWithFlash(any request, string location, string category, string message): dict<string, any>

303 redirect to location with a flash message attached.

Method renderTemplate

func renderTemplate(any request, string name, dict<string, any> context, string method): string

Method requireApp

func requireApp(string what): void

gebweb/src/csrf.gb

Class CsrfConfig

class CsrfConfig

Per-app CSRF configuration. Set via gebweb.useCsrf(app, opts). Holds the signing secret and cookie metadata used by the per- route wrapper at request time.

Field secret

string secret

Field cookieName

string cookieName

Field cookieOptions

dict<string, any> cookieOptions

Method CsrfConfig

func CsrfConfig(string secret, string cookieName = "geb_csrf", dict<string, any> cookieOptions = {...})

Function newConfig

func newConfig(string secret, dict<string, any> opts = {...}): CsrfConfig

Function wrapRouteCsrf

func wrapRouteCsrf(callable adapter, callable lookup): callable

Wrap a route adapter with CSRF token handling. The wrapper:

  • On every request, ensures a token cookie exists (mints one if absent) and threads the current token into request as _csrfToken for view helpers.
  • On unsafe methods (POST/PUT/PATCH/DELETE), validates the submitted token (X-CSRF-Token header or _csrf form field) against the cookie value. Mismatch returns 403.
  • Calls the inner adapter on success and forwards its response.

Routes carrying @CsrfExempt are not wrapped (the per-route binding skips this call entirely).

lookup() returns the active CsrfConfig or null. When CSRF is not enabled on the app, the wrapper is a transparent passthrough.

gebweb.decorators

Source: gebweb/src/decorators.gb

Function bareDecoratorName

func bareDecoratorName(string name): string

Strips a module qualifier so @gebweb.Get / aliased @gw.Get match the same as the bare @Get.

Function decoratorsOf

func decoratorsOf(any target): list<dict<string, any>>

reflect.decorators with qualified names normalised to their bare suffix, so every Gebweb scanner accepts both forms.

Function isRouteDecorator

func isRouteDecorator(dict<string, any> decorator): bool

True when the decorator names a Gebweb route on a method.

Function routeMethod

func routeMethod(dict<string, any> decorator): string

Returns the HTTP method (uppercase) implied by a route decorator.

Function routePath

func routePath(dict<string, any> decorator): string

Returns the path template implied by a route decorator.

Function controllerPrefix

func controllerPrefix(any controllerClass): string

Returns the controller-level path prefix from @Controller("/api"), or "".

Function apiVersionFor

func apiVersionFor(any controllerClass, any method): string

Returns the API version label from @ApiVersion("v2"), or "". A method-level @ApiVersion overrides the controller's. Used to prefix routes with /<version> and group them in OpenAPI.

Function isDeprecated

func isDeprecated(any controllerClass, any method): bool

True when the method or its controller carries @Deprecated.

Function deprecationSunset

func deprecationSunset(any controllerClass, any method): string

Returns the sunset date string from @Deprecated("<date>") (method preferred over controller), or "" when none is given. The value is an HTTP-date / RFC 3339 string passed through to the Sunset header.

Function decoratorString

func decoratorString(any target, string decoratorName): string

Reads the first positional argument of the named decorator on target, or "".

Function decoratorInt

func decoratorInt(any target, string decoratorName, int defaultValue): int

Returns the first positional int argument of the named decorator on target, or defaultValue when the decorator is absent or its first arg is not an int. Used by @RateLimit(perSecond, burst?) and similar.

Function decoratorIntAt

func decoratorIntAt(any target, string decoratorName, int index, int defaultValue): int

Returns the Nth positional int argument of the named decorator on target, or defaultValue when missing / not an int.

Function decoratorDict

func decoratorDict(any target, string decoratorName): ?dict<string, any>

Returns the first dict positional argument of the named decorator, or null when absent. Used by @Cors({...}), @Cache({...}), and similar.

Function hasDecorator

func hasDecorator(any target, string decoratorName): bool

True when a method carries the given decorator.

Function tagFor

func tagFor(any controllerClass, any method, string className): string

Returns the @Tag for a method, falling back to controller class and class name.

Function apiResponses

func apiResponses(any target): list<dict<string, any>>

Collects every @ApiResponse decorator's data as a list of dicts.

Function pathParameterNames

func pathParameterNames(string path): list<string>

Extracts the {name} segments from a route path template, in order.

gebweb.di

Source: gebweb/src/di.gb

Class Container

class Container

Container holds the bindings (factory callables) and the singleton cache. The resolving list tracks the in-progress dependency stack so cycles surface as a clear error rather than as stack exhaustion.

factories and cache are keyed by class value - class refs are hashable in Geblang and equal-by-identity, so two literal Foo references in different files all hit the same slot.

Field factories

dict<any, callable> factories

Field cache

dict<any, any> cache

Field _lock

sync.Mutex _lock

Field resolvingByGid

dict<int, any> resolvingByGid

Field perRequestFactories

dict<any, callable> perRequestFactories

Field scopeActiveByGid

dict<int, bool> scopeActiveByGid

Field scopeCacheByGid

dict<int, any> scopeCacheByGid

Field interfaceInstances

dict<string, any> interfaceInstances

Field serviceIds

dict<string, any> serviceIds

Field serviceFactories

dict<string, callable> serviceFactories

Field serviceTags

dict<string, list<string>> serviceTags

Field serviceShared

dict<string, bool> serviceShared

Field aliases

dict<string, string> aliases

Field interfaceBindings

dict<string, string> interfaceBindings

Method Container

func Container()

Function newContainer

func newContainer(): Container

Build a new empty container.

Function register

func register(Container c, any classRef, callable factory): Container

Register a factory for a class. When the container is asked to resolve classRef, it calls factory() (a no-arg callable that returns a value of the right type) once, caches the result, and hands the same value back on every subsequent resolve.

Use a factory when the construction has side effects, depends on runtime configuration, or produces a value that can't be assembled by reflection (e.g. opening a database connection).

Function registerPerRequest

func registerPerRequest(Container c, any classRef, callable factory): Container

Register a per-request factory. While a request is in flight, the framework's request handler wraps resolution in a request scope; resolves for this class share one instance across the request and are discarded afterwards. Outside a request scope (e.g. during startup or in tests not using TestClient), each resolve calls the factory fresh and does not cache.

Useful for per-request state holders: a RequestContext that holds the current user + tenant + correlation id, a TransactionManager scoped to a single HTTP request, etc.

Function hasPerRequestBindings

func hasPerRequestBindings(Container c): bool

Run fn() inside a request scope and return whatever fn produced. Per-request classes resolved during fn are cached for the scope's lifetime and discarded when fn returns. Called by the framework's request handler; user code shouldn't need to invoke this directly.

The return is typed any rather than generic because Geblang doesn't bind a free generic on the function from a callable's return type alone (and the explicit call-site binding doesn't thread through to the as T cast cleanly). Callers cast the result at the boundary. True when the container has any registerPerRequest bindings. The dispatcher skips request-scope setup entirely when false.

Function withRequestScope

func withRequestScope(Container c, callable fn): any

Function registerInstance

func registerInstance(Container c, any classRef, any instance): Container

Register an explicit instance as the container's value for a class. Useful for stubbing in tests:

di.registerInstance(c, DbConn, fakeConn);

Function registerInterfaceInstance

func registerInterfaceInstance(Container c, string ifaceTypeName, any instance): Container

Register an instance to satisfy constructor parameters typed with an interface. ifaceTypeName is the interface's declared name as it appears in source (module-qualified for cross- module interfaces, e.g. "llm.Client"). The lookup is exact- string match, so the registered name must match the parameter type annotation verbatim.

Use this for any interface-typed dependency the framework wires up; constructor walks during resolve / resolveWith consult interfaceInstances before falling through to class-based resolution.

Function registerService

func registerService(Container c, string id, any classRef): Container

Register a class under a string id. Used by the @Service discovery sweep and the YAML services loader. Throws if id is already bound to a different class so duplicate ids surface at warm-up rather than as silent shadowing at first resolve.

Function resolveService

func resolveService(Container c, string id, callable parameterResolver): any

Resolve a service by its registered string id (from @Service or a YAML services entry). Throws if no service is registered under that id. Resolution otherwise follows the normal autowire path.

Function hasService

func hasService(Container c, string id): bool

True when an id is registered, following aliases.

Function serviceIds

func serviceIds(Container c): list<string>

Lists all registered service ids in insertion order. Aliases are not included; use aliases(c) for those.

Function registerServiceFactory

func registerServiceFactory(Container c, string id, any classRef, callable factory, list<string> tags, bool shared): Container

Register a custom factory for a service id, with optional tags and shared flag. Used by the YAML services-section loader when the entry supplies constructor arg overrides. Pass a no-arg factory callable that returns the built instance.

Function tagService

func tagService(Container c, string id, string tag): Container

Attach a tag to an already-registered service id.

Function tagsForService

func tagsForService(Container c, string id): list<string>

Tags attached to a service id, in insertion order.

Function taggedServiceIds

func taggedServiceIds(Container c, string tag): list<string>

Service ids carrying tag, in service-registration order.

Function registerAlias

func registerAlias(Container c, string alias, string target): Container

Register an alias mapping. Resolving the alias id goes through the normal resolveService path under the target id. Throws if alias is already registered as a real service or as a different alias.

Function aliases

func aliases(Container c): dict<string, string>

All registered aliases as {alias: target}.

Function canonicalServiceId

func canonicalServiceId(Container c, string id): string

Function resolve

func resolve(Container c, any classRef): any

Resolve a class: return the cached instance if present; otherwise call the registered factory if one is registered; otherwise build the instance via constructor autowiring by recursively resolving each constructor parameter's declared type.

Classes with no explicit constructor (data classes) are instantiated via the bare classRef() call. Cycles raise a RuntimeError. An unresolvable parameter type (no factory, no class found, can't be auto-built) raises a RuntimeError naming the offending parameter so the user can register the missing binding.

Function resolveWith

func resolveWith(Container c, any classRef, callable parameterResolver): any

Like resolve but lets the caller plug in a resolver for parameters annotated with @Param("key"). The framework wires this up so primitive config (db URLs, secrets, feature flags registered via gebweb.parameter) can be injected into controllers and services alongside class dependencies.

parameterResolver is called as parameterResolver(key) for each @Param(key) constructor parameter and should return the value to inject (typically a string / int / bool).

Function resolveDependency

func resolveDependency(Container c, dict<string, any> param, callable parameterResolver, string parentName = ""): any

Resolve a single constructor parameter by its declared type: @Param("key") -> parameterResolver(key); interface match -> registered instance; otherwise reflect.class + fallback to findRegisteredByTypeName, then recursively resolveWith. parentName is folded into the error message so the user sees which class's autowire failed.

Function bindInterface

func bindInterface(Container c, string ifaceName, string serviceId): Container

Bind an interface name to a registered service id. resolveDependency uses the binding to resolve constructor params typed with the interface. Throws if the interface is already bound to a different id (idempotent for the same target).

Function interfaceBindings

func interfaceBindings(Container c): dict<string, string>

All registered interface bindings as {interface: service-id}.

Function detectInterfaceConflicts

func detectInterfaceConflicts(Container c): void

Walk every registered service and throw when an interface has multiple implementations and no explicit binding (or eager instance). Single-impl auto-binding is deferred to first resolve so the binding reflects the final service set, not the partial picture seen at the time detect runs. Idempotent.

Function collectInheritedInterfaces

func collectInheritedInterfaces(any classRef): list<string>

gebweb.discovery

Source: gebweb/src/discovery.gb

Class DiscoveryReport

class DiscoveryReport

Walks every user class via reflect.classes() and routes those carrying gebweb markers into the right registry:

@Controller -> addControllers(app, [cls]) @Service -> marker only; container auto-wires on first resolve via ctor-param walking @Tag("event.subscriber") / @Tag("job.handler") / @Tag("message.handler") / @Tag("scheduled") -> instance is built via the container and passed to the matching gebweb registration helper.

Classes without any marker are skipped, so stdlib classes do not get auto-registered.

Field controllers

list<string> controllers

Field services

list<string> services

Field policies

list<string> policies

Field taggedByTag

dict<string, list<string>> taggedByTag

Method DiscoveryReport

func DiscoveryReport()

Function discover

func discover(appmod.GebwebApp app, callable eventSubscriberRegistrar, callable jobHandlerRegistrar, callable messageHandlerRegistrar, callable scheduledTaskRegistrar, callable policyRegistrar, bool mountControllers): DiscoveryReport

Function discoverCached

func discoverCached(appmod.GebwebApp app, callable eventReg, callable jobReg, callable msgReg, callable schedReg, callable policyReg, bool mountControllers, string cachePath): DiscoveryReport

Function isFrameworkReservedTag

func isFrameworkReservedTag(string tag): bool

gebweb.errors

Source: gebweb/src/errors.gb

Class HttpException

class HttpException extends RuntimeError

HTTP-shaped exceptions for Gebweb handlers. Throwing one of these from a handler short-circuits the response with the configured status code and a Problem Details body (RFC 9457). A handler can also return a Response directly for more control. Base class for HTTP errors raised by handlers.

Field status

int status

Field detail

string detail

Field typeUri

string typeUri

Field title

string title

Method HttpException

func HttpException(int status, string detail, string title)

Class BadRequestError

class BadRequestError extends HttpException

Method BadRequestError

func BadRequestError(string detail)

Class UnauthorizedError

class UnauthorizedError extends HttpException

Method UnauthorizedError

func UnauthorizedError(string detail)

Class ForbiddenError

class ForbiddenError extends HttpException

Method ForbiddenError

func ForbiddenError(string detail)

Class NotFoundError

class NotFoundError extends HttpException

Method NotFoundError

func NotFoundError(string detail)

Class ConflictError

class ConflictError extends HttpException

Method ConflictError

func ConflictError(string detail)

Class UnprocessableEntityError

class UnprocessableEntityError extends HttpException

Field validationErrors

list<dict<string, any>> validationErrors

Method UnprocessableEntityError

func UnprocessableEntityError(string detail, list<dict<string, any>> errs)

Class PayloadTooLargeError

class PayloadTooLargeError extends HttpException

Method PayloadTooLargeError

func PayloadTooLargeError(string detail)

Class InternalServerError

class InternalServerError extends HttpException

Method InternalServerError

func InternalServerError(string detail)

Function problemResponse

func problemResponse(HttpException err): dict<string, any>

Renders an HttpException as a Problem Details response dictionary suitable for returning from the web.router handler chain.

etag

Source: gebweb/src/etag.gb

Class EtagConfig

class EtagConfig

Configuration for useEtag. minBytes skips bodies below the threshold (default 0). maxBytes skips bodies above it (default 1 MiB) to avoid hashing large streams.

Field minBytes

int minBytes

Field maxBytes

int maxBytes

Field weak

bool weak

Method EtagConfig

func EtagConfig(dict<string, any> opts)

Function newConfig

func newConfig(dict<string, any> opts = {...}): EtagConfig

Function etagMiddleware

func etagMiddleware(EtagConfig cfg): callable

Returns the response-phase middleware. Hashes the body of any eligible 2xx response, sets the ETag header, and rewrites to 304 with an empty body when the request's If-None-Match matches. Skips streaming bodies (any value not coercible to string / bytes), non-2xx, and bodies outside the size window.

gebweb.events

Source: gebweb/src/events.gb

Class EventConfig

class EventConfig

Per-app event bus configuration: the subscriber registry keyed by event name. Each entry is a dict {"instance": any, "method": callable, "subscriberName": string}.

Field subscribers

dict<string, list<dict<string, any>>> subscribers

Method EventConfig

func EventConfig()

Class Event

class Event

Context handed to every subscriber. Carries the event name, payload, and the app reference (so subscribers can resolve DI bindings or enqueue follow-on jobs).

Field name

string name

Field payload

dict<string, any> payload

Field app

any app

Method Event

func Event(string name, dict<string, any> payload, any app)

Function newConfig

func newConfig(): EventConfig

Function registerSubscribers

func registerSubscribers(EventConfig config, list<any> instances): void

Walk each instance, find every method decorated with @On("event-name"), and register it. A single method may subscribe to multiple events by stacking decorators.

Function publish

func publish(EventConfig config, any app, string name, dict<string, any> payload): void

Synchronously fire name to every registered subscriber. Returns once each subscriber has run (or thrown). Subscriber exceptions are accumulated and re-thrown as a single aggregated error after the full dispatch, so one buggy subscriber can't silently break the chain.

Function subscriberCount

func subscriberCount(EventConfig config, string name): int

Number of subscribers registered for name (mostly for tests and diagnostics).

gebweb/src/flash.gb

Function flash

func flash(any sessionStore, dict<string, any> response, dict<string, any> request, string category, string message, dict<string, any> options = {...}): dict<string, any>

Append a flash message and return the updated response. The session store registered via gebweb.useSession (or useSessionAuth) persists the message on the outbound cookie.

Function currentFlashes

func currentFlashes(any sessionStore, dict<string, any> request): dict<string, list<string>>

Read all flashes from the current request, grouped by category. The flash view-context injector calls this for every render that threads a request; handler code rarely needs it directly. The injector also clears the messages so they vanish on next render.

Function consume

func consume(any sessionStore, dict<string, any> response, dict<string, any> request, dict<string, any> options = {...}): dict<string, any>

Drop the flash queue from the session. Used after the injector has handed the messages to the template, so a subsequent render sees an empty dict.

gebweb/src/forms.gb

Function preserveInput

func preserveInput(any sessionStore, dict<string, any> response, dict<string, any> request): dict<string, any>

Persist the submitted body under _oldInput in the session. Used by the rehydration hook and by handlers that want to keep input around for manual re-render flows.

Function withErrors

func withErrors(any sessionStore, dict<string, any> response, dict<string, any> request, dict<string, list<string>> errors): dict<string, any>

Persist a field -> [message] error map under _errors in the session. The map is consumed on the next view render.

Function currentOldInput

func currentOldInput(any sessionStore, dict<string, any> request): dict<string, any>

Read the queued old-input dict from the current session. Returns an empty dict when nothing is queued.

Function currentErrors

func currentErrors(any sessionStore, dict<string, any> request): dict<string, list<string>>

Read the queued errors dict from the current session.

Function consume

func consume(any sessionStore, dict<string, any> response, dict<string, any> request): dict<string, any>

Clear both queued maps from the session and return the updated response. Called from the after-middleware after the injector has handed the values to the template.

Function formRehydration

func formRehydration(callable sessionLookup): callable

Build the formRehydration callable wired into the route adapter. Inspects the request's Accept header on validation failure: HTML clients get a 303 redirect with old-input + errors in session; JSON clients return null so the adapter falls back to the standard 422 Problem-Details response.

sessionLookup is a closure returning the live session store (null when not configured). Lookup-style so apps can register the session after route binding.

gebweb

Source: gebweb/src/gebweb.gb

Type Request

type Request = requestmod.Request

Type Response

type Response = http.Response

Type GebwebApp

type GebwebApp = appmod.GebwebApp

Type UploadedFile

type UploadedFile = uploadsmod.UploadedFile

Type Page

type Page = repomod.Page

Type Cursor

type Cursor = repomod.Cursor

Type CursorPage

type CursorPage = repomod.CursorPage

Type OidcProvider

type OidcProvider = oidcmod.OidcProvider

Class Plugin

class Plugin extends pluginmod.Plugin

Re-export the Plugin base class so users only need import gebweb; to subclass it.

Method Plugin

func Plugin(string name)

Interface PluginContract

interface PluginContract extends pluginmod.PluginContract

Re-export the PluginContract interface so user code can type plugin parameters precisely without reaching into the internal gebweb.plugin module.

Class Controller

class Controller extends controllermod.Controller

Optional base class for controllers. Extending it gives helper methods (this.json(...), this.notFound(...), this.created(...), etc.). Plain classes with @Get / @Post decorators still work without subclassing - this is convenience, not a contract.

class HelloController extends gebweb.Controller { @Get("/hello/{name}") func hello(string name): dict<string, any> { return this.json({"message": "Hello, " + name}); }

@Get("/items/{id}") func read(string id): dict<string, any> { if (lookup(id) == null) { this.notFound("no item " + id); } return this.json(lookup(id)); } }

Method groups: response builders (json, html, created, noContent, redirect) and error throwers (badRequest, unauthorized, forbidden, notFound, conflict, unprocessable, problem). Error throwers raise an HttpException which the framework catches and renders as RFC 9457 Problem Details.

Method Controller

func Controller()

Class Hub

class Hub extends broadcastmod.Hub

Method Hub

func Hub()

Function newHub

func newHub(): broadcastmod.Hub

Function app

func app(list<any> controllers = [], ?dict<string, any> opts = null): appmod.GebwebApp

Builds a Gebweb app from optional controller entries. With an empty list, decorated controllers are discovered when the app first handles requests. If config/services.yaml exists in the working directory it is loaded before controllers are registered, so YAML-defined parameters / services are visible during DI autowiring.

Function loadConfig

func loadConfig(appmod.GebwebApp app, string path = "config/services.yaml"): appmod.GebwebApp

Explicitly load YAML configuration into the app. Use when the config file lives at a non-default path or when you need to load additional files on top of the auto-loaded one.

Function currentEnv

func currentEnv(): string

Active environment name (GEBWEB_ENV, defaulting to "prod").

Function discover

func discover(appmod.GebwebApp app): discoverymod.DiscoveryReport

Walk every user class via reflect.classes() and auto-register those carrying gebweb markers: @Controller -> mounted as a controller @Policy method -> registered as an authorization policy @Service -> registered in the DI container @Tag("event.subscriber") -> registered as an event subscriber @Tag("job.handler") -> registered as a job handler @Tag("message.handler") -> registered as a message handler @Tag("scheduled") -> registered as a scheduled task

This runs automatically (once) the first time the app starts handling requests via serve / listen / TestClient / dispatcher, so calling it is optional. Classes without any marker are skipped. @Controller classes are auto-mounted only when app() was given no explicit controller list; an explicit list is the complete set. Returns a DiscoveryReport listing what was found.

Function discoverCached

func discoverCached(appmod.GebwebApp app, string cachePath): discoverymod.DiscoveryReport

Like discover, but persists the sweep result to cachePath and reloads it on the next run when the loaded-class set is unchanged (matched by a fingerprint), skipping the scan. serve / listen use this with a default cache path; delete the file to force a rebuild after a decorator-only change.

Function parameter

func parameter(appmod.GebwebApp app, string key, any value): appmod.GebwebApp

Register a primitive config value in the app's parameter store.

Function getParameter

func getParameter(appmod.GebwebApp app, string key): any

Read a value from the parameter store, throwing if not registered.

Function hasParameter

func hasParameter(appmod.GebwebApp app, string key): bool

True when the parameter store has a value for key.

Function addControllers

func addControllers(appmod.GebwebApp app, list<any> controllers): appmod.GebwebApp

Register additional controllers after the app has been created. Useful when DI bindings (gebweb.register / gebweb.registerInstance) are added between app() and the controllers that depend on them.

Function setInfo

func setInfo(appmod.GebwebApp app, dict<string, any> info): appmod.GebwebApp

Set the OpenAPI info object (title, version, description, ...).

Function cli

func cli(appmod.GebwebApp app, dict<string, any> opts = {...}): void

Block and serve the app on the given address.

opts is forwarded to http.serve. Common options:

  • {"reactor": true} use the high-throughput reactor backend
  • {"maxConns": N} cap the goroutine pool
  • {"overload": "drop"|"reject"|"queue"} reactor-mode backpressure Standard server entrypoint: serves the app with the shared flag/env operational surface (--port, --tls-port, --domain, --self-signed, --no-tls, --help; GEBWEB_* environment fallbacks), prints a listening banner, and shuts down cleanly on SIGINT / SIGTERM. opts supplies the defaults the flags override.

Function serve

func serve(appmod.GebwebApp app, string address, ?dict<string, any> opts = null): void

Function listen

func listen(appmod.GebwebApp app, string address, ?dict<string, any> opts = null): int

Background-serve the app; returns an http listen handle. Accepts the same opts shape as serve.

Function useDocsAuth

func useDocsAuth(appmod.GebwebApp app, callable guard): appmod.GebwebApp

Register a guard that runs before /openapi.json and /docs.

Function basicAuthGuard

func basicAuthGuard(string user, string password): callable

HTTP Basic-Auth guard for docs routes.

Function bearerTokenGuard

func bearerTokenGuard(string expected): callable

Hard-coded Bearer-token guard for docs routes.

Function requireAppAuth

func requireAppAuth(appmod.GebwebApp app, list<string> requiredRoles = []): callable

Guard that reuses the app's existing authenticator (whatever useAuthenticator / useJWT / useSessionAuth registered). Optional requiredRoles denies users that lack ANY of the listed roles (intersection match).

Function dispatcher

func dispatcher(appmod.GebwebApp app): callable

Returns the in-process dispatcher closure: callable(request): response.

Function routes

func routes(appmod.GebwebApp app): list<dict<string, any>>

Returns the route table for introspection / debugging.

Function formatRouteTable

func formatRouteTable(list<dict<string, any>> rts): string

Render routes (method, path, controller.handler) as aligned text.

Function TestClient

func TestClient(appmod.GebwebApp app): testclientmod.TestClient

Build an in-process TestClient for the given Gebweb app.

Function register

func register(appmod.GebwebApp app, any classRef, callable factory): appmod.GebwebApp

Register a factory for a service class with the app's DI container. The factory is a no-arg callable that returns the service value; the container calls it at most once and caches the result.

gebweb.register(app, DbConn, func(): DbConn { return DbConn(url); });

Function registerInstance

func registerInstance(appmod.GebwebApp app, any classRef, any instance): appmod.GebwebApp

Register an explicit instance for a service class - useful for stubbing in tests.

Function registerPerRequest

func registerPerRequest(appmod.GebwebApp app, any classRef, callable factory): appmod.GebwebApp

Register a per-request factory. The framework creates a DI request scope around each incoming HTTP request; per-request bindings share one instance across the request and are discarded afterwards. Outside a request scope (in setup code or in tests that bypass the dispatcher) each resolve produces a fresh instance.

gebweb.registerPerRequest(app, RequestContext, func(): RequestContext { return RequestContext(); });

Function resolve

func resolve(appmod.GebwebApp app, any classRef): any

Resolve a class through the app's DI container.

Class Where

class Where extends querymod.Where

Build a Page value with offset/limit defaults. Use this to construct a Page from app code without importing the repository sub-module directly:

let page = gebweb.page(0, 50, "createdAt", "desc");

Method Where

func Where(string sql, list<any> params)

Class OrderBy

class OrderBy extends querymod.OrderBy

Method OrderBy

func OrderBy(list<dict<string, string>> entries)

Class Query

class Query extends querymod.Query

Method Query

func Query(string table)

Function eq

func eq(string field, any value): querymod.Where

Function neq

func neq(string field, any value): querymod.Where

Function gt

func gt(string field, any value): querymod.Where

Function ge

func ge(string field, any value): querymod.Where

Function lt

func lt(string field, any value): querymod.Where

Function le

func le(string field, any value): querymod.Where

Function like

func like(string field, string pattern): querymod.Where

Function in_

func in_(string field, list<any> values): querymod.Where

Function isNull

func isNull(string field): querymod.Where

Function notNull

func notNull(string field): querymod.Where

Function asc

func asc(string field): querymod.OrderBy

Function desc

func desc(string field): querymod.OrderBy

Function page

func page(int offset, int size, string sort, string direction): repomod.Page

Function registerAssertion

func registerAssertion(appmod.GebwebApp app, string name, callable validator): appmod.GebwebApp

Register a custom @Assert.<name> validator on the app. The validator takes (value, positional args, named args) and returns null on success or an error-message string on failure:

gebweb.registerAssertion(app, "strongPassword", func(any v, list args, dict<string, any> named): ?string { if ((v as string).length() < 12) { return "must be 12+ chars"; } return null; });

The rule registers under @Assert.strongPassword and runs in the same pass as the built-in validators.

Function use

func use(appmod.GebwebApp app, callable middleware): appmod.GebwebApp

Register a response-phase middleware. The callable takes (request, response) and returns the (possibly transformed) response. Common usage:

import gebweb.middleware as mw; gebweb.use(app, mw.securityHeaders({})); gebweb.use(app, mw.cors({"origin": "https://example.com"}));

Function before

func before(appmod.GebwebApp app, callable middleware): appmod.GebwebApp

Register a request-phase middleware. The callable takes the raw request dict and returns either null (continue to the handler) or a response dict (short-circuit). Use for auth gates and other request-time rejection logic.

Function after

func after(appmod.GebwebApp app, callable middleware): appmod.GebwebApp

Alias of use for readability.

Function plugin

func plugin(appmod.GebwebApp app, pluginmod.PluginContract pluginInstance): appmod.GebwebApp

Register a plugin on the app. A plugin is a value implementing PluginContract - typically a subclass of gebweb.Plugin. install is invoked immediately and the plugin is appended to app.plugins for later lookup via findPlugin.

Function findPlugin

func findPlugin(appmod.GebwebApp app, string name): ?pluginmod.PluginContract

Find a registered plugin by name. Returns null when absent.

Function useApiKeyAuth

func useApiKeyAuth(appmod.GebwebApp app, any userClass, callable resolveByKey): appmod.GebwebApp

Wire an API-key authenticator. The framework reads the key from X-API-Key (preferred) or Authorization: Bearer <key>. The resolver maps a key to the user instance (or null when the key is unrecognised). OpenAPI is set to the apiKey security scheme.

Function usePermissions

func usePermissions(appmod.GebwebApp app, callable extractor): appmod.GebwebApp

Override the permission extractor used by @RequiresPermission. The callable takes the authenticated user and returns the list<string> of permissions they hold. Defaults to reading user.permissions.

Function useViews

func useViews(appmod.GebwebApp app, string dir = "templates"): appmod.GebwebApp

Attach a view engine to the app, rooted at dir (default "templates/"). Subsequent calls to gebweb.view(app, name, ctx) resolve templates relative to that directory.

Function preloadViews

func preloadViews(appmod.GebwebApp app, list<string> names): appmod.GebwebApp

Compile named templates during production startup. Development remains lazy and keeps its modification-time reload behavior.

Function registerViewContext

func registerViewContext(appmod.GebwebApp app, string name, callable fn): appmod.GebwebApp

Register a view-context injector. The 4-arg form of gebweb.view (and gebweb.htmlView) merges each injector's return value into the rendered context under its name. The injector callable receives the rich Request (1.7.1+). Used internally by the framework's csrf / flashes / errors / oldInput / cspNonce / asset helpers; user code can register additional injectors here.

Function useCsrf

func useCsrf(appmod.GebwebApp app, dict<string, any> opts = {...}): appmod.GebwebApp

Enable CSRF protection. opts.secret is required. After this call, every POST/PUT/PATCH/DELETE requires a valid token (from the geb_csrf cookie, echoed in the X-CSRF-Token header or _csrf form field) unless the route declares @CsrfExempt. The current token is auto-injected into view contexts under csrf. Idiomatic usage in templates:

For fetch / ajax, set the X-CSRF-Token header to {{ csrf }}.

Function useI18n

func useI18n(appmod.GebwebApp app, dict<string, any> opts = {...}): appmod.GebwebApp

Mount the locale negotiator. Resolves the active locale from URL prefix (/<locale>/...), the sticky cookie, and the Accept-Language header in that order; falls back to default. The resolved Locale lives on request["_locale"] and is injected into handlers that declare an i18n.Locale parameter.

Common opts: locales, default, sources, cookieName, urlPrefix, urlStrip, defaultZone.

Class Locale

class Locale extends i18nmod.Locale

Class Translator

class Translator extends i18nmod.Translator

Function parseLocale

func parseLocale(string tag): ?i18nmod.Locale

Function t

func t(appmod.GebwebApp app, any locale, string key, dict<string, any> args = {...}): string

Translate key for locale (a tag like "en" or a Locale) with {name} placeholder substitution from args. Falls back to the configured default locale, then to the key itself when no catalog entry is found.

Function useTenant

func useTenant(appmod.GebwebApp app, callable resolver, dict<string, any> opts = {...}): appmod.GebwebApp

Mount the tenant resolver. resolver(request) returns a Tenant (or null). The resolved tenant is published on request["_tenant"] and injected into handlers that declare a Tenant parameter. Pass {required: false} to allow null resolutions to pass through (no 400).

Class Tenant

class Tenant extends tenancymod.Tenant

Method Tenant

func Tenant(string id, string name = "", dict<string, any> attributes = {...})

Function currentTenant

func currentTenant(dict<string, any> request): ?tenancymod.Tenant

Function currentTenantId

func currentTenantId(dict<string, any> request): string

Function stampTenant

func stampTenant(any entity, tenancymod.Tenant tenant): any

Function tenantOwns

func tenantOwns(any entity, tenancymod.Tenant tenant): bool

Function scopedQuery

func scopedQuery(querymod.Query q, tenancymod.Tenant tenant): querymod.Query

Function useHealth

func useHealth(appmod.GebwebApp app, list<any> instances, dict<string, any> opts = {...}): appmod.GebwebApp

Mount /healthz (liveness) and /readyz (readiness) endpoints. Each instance in instances is scanned for @HealthCheck methods; probes run on each hit. Pass {livenessPath, readinessPath} to override the URLs.

Function useMetrics

func useMetrics(appmod.GebwebApp app, dict<string, any> opts = {...}): appmod.GebwebApp

Mount a Prometheus /metrics endpoint fed by per-route request counters, latency totals, and an in-flight gauge.

Function useOps

func useOps(appmod.GebwebApp app, list<any> instances = [], dict<string, any> opts = {...}): appmod.GebwebApp

The production endpoint bundle: liveness + readiness probes and the Prometheus metrics endpoint in one call.

gebweb.useOps(app, [DbProbe(conn)]);

Function shutdown

func shutdown(appmod.GebwebApp app, dict<string, any> opts = {...}): void

Gracefully drain and stop the app's server: readiness flips to 503, in-flight requests finish within opts.timeoutMs (default 10000), then the listener closes and gebweb.serve returns. Safe to call from a signal handler.

Function isDraining

func isDraining(appmod.GebwebApp app): bool

True once gebweb.shutdown has started; long-running loops should exit when this flips.

Function useOidc

func useOidc(appmod.GebwebApp app, dict<string, any> opts): appmod.GebwebApp

Mount OIDC / OAuth2 providers. opts.providers is a list of oidc.OidcProvider values (built via oidc.google, oidc.github, or oidc.generic); opts.userResolver(claims, provider) returns the session-stored user dict; opts.stateSecret signs the cookie that carries PKCE state between redirect and callback. The framework mounts /auth/<provider>/callback automatically.

Function oidcLoginUrl

func oidcLoginUrl(appmod.GebwebApp app, string providerName, dict<string, any> request): dict<string, any>

Function oidcGoogle

func oidcGoogle(string clientId, string clientSecret, dict<string, any> opts = {...}): oidcmod.OidcProvider

Function oidcGithub

func oidcGithub(string clientId, string clientSecret, dict<string, any> opts = {...}): oidcmod.OidcProvider

Function oidcGeneric

func oidcGeneric(dict<string, any> opts): oidcmod.OidcProvider

Function useWebhooks

func useWebhooks(appmod.GebwebApp app, dict<string, any> opts = {...}): appmod.GebwebApp

Mount the outbound webhook dispatcher. Requires useJobs(...). Pass opts.deadLetter(event, payload, lastError) to handle permanent failures, opts.signer(body, secret) to override the default HMAC-SHA256 signer, and opts.signatureHeader to change the header name (X-Gebweb-Signature by default).

Function subscribeWebhook

func subscribeWebhook(appmod.GebwebApp app, string event, string url, string secret = ""): webhooksmod.WebhookSubscription

Function unsubscribeWebhook

func unsubscribeWebhook(appmod.GebwebApp app, string event, string url): bool

Function dispatchWebhook

func dispatchWebhook(appmod.GebwebApp app, string event, dict<string, any> payload): int

Function verifyWebhookSignature

func verifyWebhookSignature(string body, string secret, string headerValue): bool

Function markDeleted

func markDeleted(any entity): any

Function restore

func restore(any entity): any

Function isDeleted

func isDeleted(any entity): bool

Function excludeDeleted

func excludeDeleted(querymod.Query q): querymod.Query

Function withTrashed

func withTrashed(querymod.Query q): querymod.Query

Function onlyTrashed

func onlyTrashed(querymod.Query q): querymod.Query

Function useEtag

func useEtag(appmod.GebwebApp app, dict<string, any> opts = {...}): appmod.GebwebApp

Mount the ETag middleware: weak SHA-256 ETag on 2xx responses, 304 on If-None-Match match.

Function useServerTiming

func useServerTiming(appmod.GebwebApp app): appmod.GebwebApp

Function useProfilerBar

func useProfilerBar(appmod.GebwebApp app, dict<string, any> opts = {...}): appmod.GebwebApp

Mount the dev profiler bar. Enabled in non-prod (or via opts.enabled); injects a toolbar into HTML responses.

Function recordTiming

func recordTiming(dict<string, any> request, string label, int durationMs): void

Function measureTiming

func measureTiming(dict<string, any> request, string label, callable fn): any

Class ProbeResult

class ProbeResult extends healthmod.ProbeResult

Method ProbeResult

func ProbeResult(bool ok, string message = "", dict<string, any> details = {...})

Function passing

func passing(string message = ""): healthmod.ProbeResult

Function failing

func failing(string message): healthmod.ProbeResult

Function useSession

func useSession(appmod.GebwebApp app, any store): appmod.GebwebApp

Register a session store. Required for flash messages and form-state rehydration. Any value with load(request) and save(response, data, opts) methods works (the stdlib provides FileSessionStore / RedisSessionStore / DatabaseSessionStore). useSessionAuth calls this internally so registering twice isn't required.

Function useAdmissionControl

func useAdmissionControl(appmod.GebwebApp app, dict<string, any> opts): appmod.GebwebApp

Bound concurrent in-flight requests; excess requests get a 503 before any handler runs (opts.maxConcurrent, optional opts.onOverload). Use a value measured against per-request memory under load.

Function useStaticAssets

func useStaticAssets(appmod.GebwebApp app, string dir, dict<string, any> opts = {...}): appmod.GebwebApp

Mount a directory of static assets with content-hash fingerprinting.

gebweb.useStaticAssets(app, "public", { "urlPrefix": "/assets", "cacheControl": "public, max-age=31536000, immutable", "dev": false });

Templates render fingerprinted URLs via the auto-injected helper:

<link rel="stylesheet" href="{{ asset('app.css') }}">

Function useSecurity

func useSecurity(appmod.GebwebApp app, dict<string, any> opts = {...}): appmod.GebwebApp

Mount browser-security response headers (CSP with per-request nonce expansion, HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy). The per-request CSP nonce is auto-published to templates as {{ cspNonce }}.

gebweb.useSecurity(app, { "csp": { "defaultSrc": ["'self'"], "scriptSrc": ["'self'", "'nonce'"] }, "hsts": {"maxAge": 31536000, "includeSubdomains": true} });

The literal 'nonce' in any directive expands to 'nonce-<value>' with a fresh value minted per request.

Function flash

func flash(appmod.GebwebApp app, dict<string, any> request, dict<string, any> response, string category, string message, dict<string, any> options = {...}): dict<string, any>

Append a flash message to the session. Survives exactly one render: the next request that touches a template via gebweb.htmlView consumes the queue. Categories are arbitrary; common conventions are "success", "error", "info".

return gebweb.flash(app, request, response, "success", "Saved!");

Requires a session store via gebweb.useSession(app, store).

Function view

func view(appmod.GebwebApp app, string name, dict<string, any> context = {...}, ?dict<string, any> request = null): string

Render the named template with context and return the HTML string. When request is supplied, every registered view-context injector (csrf token, flashes, errors, oldInput, cspNonce, asset map, etc.) runs against the request and its return value is merged into the rendered context under its registered name. User-supplied keys in context win over injectors when they collide. The 3-arg form (no request) is unchanged.

For server-rendered HTML responses, gebweb.htmlView(app, request, name, ctx) returns a complete response dict in one call.

Function htmlView

func htmlView(appmod.GebwebApp app, dict<string, any> request, string name, dict<string, any> context = {...}, int status = 200, ?dict<string, any> headers = null): dict<string, any>

Render name against context with the request threaded through for view-context injection, and wrap the result in a 200 HTML response. The most common idiom for server-rendered handlers:

return gebweb.htmlView(app, request, "page.html", {"user": user});

Optional status + headers mirror gebweb.html.

Function useJobs

func useJobs(appmod.GebwebApp app, db.Connection conn, dict<string, any> opts = {...}): appmod.GebwebApp

Attach a background-job queue to the app, backed by conn. See gebweb.docs.background-jobs for the full options dict.

Function registerJobHandlers

func registerJobHandlers(appmod.GebwebApp app, list<any> instances): appmod.GebwebApp

Register a set of @Job handler instances.

Function enqueue

func enqueue(appmod.GebwebApp app, string name, dict<string, any> payload, dict<string, any> opts = {...}): string

Enqueue a job by name. Returns the new job id.

Function runWorker

func runWorker(appmod.GebwebApp app, dict<string, any> opts = {...}): void

Run the worker loop. Blocks the calling process until killed (or until opts.maxJobs jobs have been processed). The gebweb worker CLI subcommand calls this after setting GEBWEB_RUN=worker in the environment - branch on that in your main.gb if you want a single binary for HTTP + worker.

When a scheduler is also configured via gebweb.useScheduler, the worker calls the scheduler's tick function between job polls so cron-style tasks fire on the same process.

Function registerPolicies

func registerPolicies(appmod.GebwebApp app, list<any> instances): appmod.GebwebApp

Register policy classes. Each method tagged @Policy("TypeName") becomes the policy for that action (the method name) on that subject type. Discovered by reflection, like job and message handlers.

Function authorize

func authorize(appmod.GebwebApp app, any request, string action, any subject): any

Authorize action on subject for the authenticated user, throwing a 403 HttpException when the registered policy denies it (or no policy covers it). Returns the user on success. Use in a handler after loading the subject.

Function can

func can(appmod.GebwebApp app, any request, string action, any subject): bool

True when the policy for action on subject grants it; never throws.

Class Job

class Job extends jobsmod.Job

Method Job

func Job(string id, string name, dict<string, any> payload, int attempts, any app)

Function useScheduler

func useScheduler(appmod.GebwebApp app, dict<string, any> opts = {...}): appmod.GebwebApp

Attach the scheduler to the app. Uses the connection from the job queue (so call useJobs first) unless opts.conn is set.

Function registerScheduledTasks

func registerScheduledTasks(appmod.GebwebApp app, list<any> instances): appmod.GebwebApp

Register a set of @Scheduled task handler instances.

Function tickScheduler

func tickScheduler(appmod.GebwebApp app): void

Run one scheduler tick directly. Mostly used by tests; the worker loop calls this automatically.

Function useEvents

func useEvents(appmod.GebwebApp app): appmod.GebwebApp

Attach the in-process event bus to the app.

Function registerEventSubscribers

func registerEventSubscribers(appmod.GebwebApp app, list<any> instances): appmod.GebwebApp

Register a set of @On subscriber instances.

Function publish

func publish(appmod.GebwebApp app, string name, dict<string, any> payload): void

Publish a synchronous event to every subscriber. Returns when all subscribers have run; aggregates and re-throws any subscriber exceptions.

Class Event

class Event extends eventsmod.Event

Method Event

func Event(string name, dict<string, any> payload, any app)

Function useMessageQueue

func useMessageQueue(appmod.GebwebApp app, string name, any handle): appmod.GebwebApp

Register a named queue handle on the app. handle is the return value of messaging.connect({...}). Once registered, methods carrying @OnMessage("name") are routed to that handle's consume loop by runMessageWorker.

import messaging; let q = messaging.connect({"driver": "rabbitmq", ...}); gebweb.useMessageQueue(app, "orders", q);

Function useMessageTopic

func useMessageTopic(appmod.GebwebApp app, string name, any handle): appmod.GebwebApp

Register a named topic handle on the app. handle is the return value of messaging.topic({...}). Once registered, methods carrying @OnMessage("name") are routed to that topic's subscribe loop by runMessageWorker.

Function registerMessageHandlers

func registerMessageHandlers(appmod.GebwebApp app, list<any> instances): appmod.GebwebApp

Register a set of @OnMessage handler instances.

Function runMessageWorker

func runMessageWorker(appmod.GebwebApp app, dict<string, any> opts = {...}): void

Run the messaging worker loop. For each registered handle that has at least one @OnMessage handler, drives consume() (queues) or subscribe() (topics) in sequence. Most deployments have a single broker handle per worker process; pass opts.handle to pin the worker to that handle, or wrap the call in an async.scope to run multiple handle loops concurrently.

Class Mailable

class Mailable extends mailingmod.Mailable

Method Mailable

func Mailable()

Interface MailerContract

interface MailerContract extends mailingmod.MailerContract

Function useMailer

func useMailer(appmod.GebwebApp app, mailingmod.MailerContract transport): appmod.GebwebApp

Attach a mailer transport.

Function smtpMailer

func smtpMailer(dict<string, any> opts): mailingmod.SmtpMailer

Build an SMTP mailer from a {host, port, username, password, from, startTLS?, tls?} dict.

Function memoryMailer

func memoryMailer(): mailingmod.MemoryMailer

In-memory mailer for tests; capture and inspect via .sent.

Function logMailer

func logMailer(): mailingmod.LogMailer

Mailer that writes each delivery to stdout (dev).

Function llmClient

func llmClient(dict<string, any> opts): llmmod.Client

Build an LLM client (llm.Client) from a provider-agnostic options dict; pick the backend with opts.provider ("openai" / "anthropic" / "bedrock"). Equivalent to llm.client(opts) from the stdlib; surfaced on the gebweb facade so import gebweb; is enough.

Function useLlm

func useLlm(appmod.GebwebApp app, llmmod.Client client): appmod.GebwebApp

Register an LLM client with the app. Stores it on the app and also registers it in the DI container so handler constructors with an llm.Client-typed parameter resolve to this instance automatically.

Interface SecretsProvider

interface SecretsProvider extends secretsmod.SecretsProvider

Re-export the SecretsProvider interface so user implementations can implements gebweb.SecretsProvider without reaching into the internal module.

Function useSecrets

func useSecrets(appmod.GebwebApp app, secretsmod.SecretsProvider provider): appmod.GebwebApp

Wires a secrets provider onto the app. %secret(name)% markers in YAML parameters call provider.getSecret(name) on read.

Function service

func service(appmod.GebwebApp app, string id): any

Resolves a service by its registered id (set via @Service("id") or @Service-defaulted to the class name; or via a YAML services entry once that lands in step 5).

Function hasService

func hasService(appmod.GebwebApp app, string id): bool

True when a service with this id is registered.

Function serviceIds

func serviceIds(appmod.GebwebApp app): list<string>

All currently registered service ids.

Function interfaceBindings

func interfaceBindings(appmod.GebwebApp app): dict<string, string>

All registered interface->service-id bindings.

Function taggedServices

func taggedServices(appmod.GebwebApp app, string tag): list<any>

Resolves every service carrying tag, in registration order. Each instance is built through service(app, id) so per-service shared/transient policy still holds.

Function taggedServiceIds

func taggedServiceIds(appmod.GebwebApp app, string tag): list<string>

Service ids carrying tag, without resolving instances.

Function tagsForService

func tagsForService(appmod.GebwebApp app, string id): list<string>

Tags attached to a service id, in insertion order.

Function secrets

func secrets(appmod.GebwebApp app): ?secretsmod.SecretsProvider

Returns the registered secrets provider or null.

Function encryptedFileSecrets

func encryptedFileSecrets(string filePath = "config/secrets.enc"): secretsmod.EncryptedFileSecretsProvider

Built-in secrets provider backed by an encrypted PEM-style file (default config/secrets.enc). Key is read from GEBWEB_SECRETS_KEY if set, else from config/secrets.key.

Function encryptSecrets

func encryptSecrets(dict<string, any> secrets, bytes key): string

Encrypts a {name: value} dict into the PEM-style body the EncryptedFileSecretsProvider expects. Used by gebweb secrets CLI tooling and exposed for custom workflows.

Function llm

func llm(appmod.GebwebApp app): ?llmmod.Client

Returns the registered LLM client or null. Use this from handler code when you only have the app value and want the configured client without going through DI.

Function sesMailer

func sesMailer(dict<string, any> opts): mailingmod.SesMailer

Build an AWS SES v2 mailer from a {region, accessKey, secretKey, from, endpoint?} dict. Endpoint defaults to the regional AWS host; override for VPC endpoints or local stacks.

Function send

func send(appmod.GebwebApp app, mailingmod.Mailable mail): void

Render mailable (subject + view template) and dispatch through the registered mailer. If a job queue is registered, the delivery is enqueued as a _gebweb_mailer_deliver job and retried by the worker on failure. Otherwise, delivery is synchronous on the calling thread.

Interface StorageContract

interface StorageContract extends storagemod.StorageContract

Function useStorage

func useStorage(appmod.GebwebApp app, storagemod.StorageContract backend): appmod.GebwebApp

Attach a storage backend (memory, local disk, or custom).

Function memoryStorage

func memoryStorage(): storagemod.MemoryStorage

In-memory storage. Survives the app's lifetime; ideal for tests.

Function localStorage

func localStorage(string dir): storagemod.LocalStorage

Local filesystem storage rooted at dir.

Function s3Storage

func s3Storage(dict<string, any> opts): storagemod.S3Storage

AWS S3 (or S3-compatible) backend. Required opts: bucket, region, accessKey, secretKey. Optional: endpoint (default https://s3.<region>.amazonaws.com; set for MinIO, R2, B2, etc.).

Function put

func put(appmod.GebwebApp app, string name, any content): void

Write content (string or bytes) under name.

Function get

func get(appmod.GebwebApp app, string name): ?bytes

Read name; returns null when missing.

Function storageExists

func storageExists(appmod.GebwebApp app, string name): bool

Check whether name exists.

Function storageDelete

func storageDelete(appmod.GebwebApp app, string name): void

Delete name (no-op if it doesn't exist).

Function storageUrl

func storageUrl(appmod.GebwebApp app, string name): string

Public URL for name. The shape depends on the backend (file:// for LocalStorage without a urlPrefix, memory:// for MemoryStorage, etc.).

Function viewsFilter

func viewsFilter(appmod.GebwebApp app, string name, callable filter): appmod.GebwebApp

Register a custom filter on the app's view engine.

Class ViewEngine

class ViewEngine extends viewsmod.ViewEngine

Method ViewEngine

func ViewEngine(string dir)

Class View

class View extends viewsmod.View

Method View

func View(string name, list<dict<string, any>> nodes, ?dict<string, any> extendsExpr, dict<string, any> blocks)

Function cors

func cors(dict<string, any> opts): callable

Function securityHeaders

func securityHeaders(dict<string, any> opts): callable

Function etag

func etag(dict<string, any> opts = {...}): callable

Conditional-GET middleware: weak ETag on 200 GET/HEAD responses and empty 304 replies to matching If-None-Match revalidations.

gebweb.use(app, gebweb.etag());

Function requestId

func requestId(): callable

Function requestLog

func requestLog(dict<string, any> opts): callable

Function compress

func compress(dict<string, any> opts): callable

Gzip-compress response bodies when the client accepts it. See gebweb.middleware.compress for options.

Function rateLimit

func rateLimit(dict<string, any> opts): callable

Token-bucket rate limit by client key (default: remote address). See gebweb.middleware.rateLimit for options.

Function abuseGuard

func abuseGuard(dict<string, any> opts): callable

Auto-ban credential-scanner / exploit bots by client IP. Register with gebweb.before. See gebweb.middleware.abuseGuard for options.

Function waf

func waf(dict<string, any> opts): callable

Web Application Firewall request-phase middleware. Register with gebweb.before.

Function jwtIssue

func jwtIssue(string secret, dict<string, any> claims, int ttlSeconds): string

Issue an HS256 JWT signed with secret. The claims dict carries any JSON-serializable values; an iat claim is added automatically, and exp is added when ttlSeconds > 0.

let token = gebweb.jwtIssue("secret", {"sub": "user-42"}, 3600);

Function jwtVerify

func jwtVerify(string secret, string token): ?dict<string, any>

Verify an HS256 JWT. Returns the claims dict on success or null when the signature mismatched, the token is malformed, or the exp claim is in the past.

Function useAuthenticator

func useAuthenticator(appmod.GebwebApp app, any userClass, callable authenticator): appmod.GebwebApp

Register an authenticator on the app. userClass is the class Gebweb injects into any handler parameter of that type when the route is gated by @Auth or @RequiresRole. The authenticator takes the raw request dict and returns the user value or null; a null result becomes a 401 Unauthorized response. Subsequent calls replace the previous registration.

gebweb.useAuthenticator(app, CurrentUser, func(dict<string, any> req): ?any { let header = ((req["headers"] as dict<string, any>)["Authorization"] ?? "") as string; if (!header.startsWith("Bearer ")) { return null; } let claims = gebweb.jwtVerify("secret", header.substring(7, header.length())); if (claims == null) { return null; } let c = claims as dict<string, any>; return CurrentUser(c["sub"] as string, (c["name"] ?? "") as string, (c["roles"] ?? []) as list); });

Function useSessionAuth

func useSessionAuth(appmod.GebwebApp app, any store, any userClass, callable fromSession): appmod.GebwebApp

Wire a session-backed authenticator on the app. store is one of web.session.{redisSessionStore, fileSessionStore, databaseSessionStore} (any value with a load(request) method). fromSession turns the loaded session dict into a user value or null. An empty session dict yields a 401 directly without calling fromSession. The OpenAPI security scheme is swapped from the JWT bearer default to a cookie-based cookieAuth (apiKey / cookie / geb_sid).

import web.session as session;

let store = session.fileSessionStore("/tmp/app-sessions", 3600); gebweb.useSessionAuth(app, store, CurrentUser, func(dict<string, any> data): ?CurrentUser { if (!data.contains("id")) { return null; } return CurrentUser(data["id"] as string, (data["name"] ?? "") as string, (data["roles"] ?? []) as list); });

Login and logout are still the user's responsibility - call store.save(response, data, options) and store.clear(response, request) from the respective handlers.

Function useMaxBodyBytes

func useMaxBodyBytes(appmod.GebwebApp app, int maxBytes): appmod.GebwebApp

Register a response cache store on the app. store is one of web.cache.{redisCacheStore, fileCacheStore, databaseCacheStore} or the pooled gebweb.redisCacheStore(opts) (any value with get(key) / set(key, value) methods). Handlers (or controller classes) carrying @Cache(ttl: N) opt in; cache hits return the stored response before binding + handler dispatch run. Use @Cache(ttl: N, vary: ["Authorization", "X-Tenant"]) to include header values in the cache key.

import web.cache as cachemod;

let store = cachemod.fileCacheStore("/tmp/app-cache", 3600); gebweb.useCacheStore(app, store); Set the app-wide request body cap in bytes (default 10 MB; 0 disables). Enforced at the HTTP server and the dispatcher with a 413 Problem response; @MaxBody(bytes) tightens it per route.

gebweb.useMaxBodyBytes(app, 1024 * 1024);

Function bindConfig

func bindConfig(appmod.GebwebApp app, any configClass, dict<string, any> opts = {...}): any

Wire the request-context convention: a correlation id per request (inbound X-Request-Id or generated), req.requestId(), the echoed response header, and gebweb.requestLogger(req) for structured logging that carries the id. Hydrate a config class from env vars (PREFIX_FIELD_NAME, prefix opt default "APP") and the parameter store, with type coercion and @Assert validation at boot:

class AppConfig { string dbHost; int port; ?string sentryDsn; } let cfg = gebweb.bindConfig(app, AppConfig) as AppConfig;

Function useJwks

func useJwks(appmod.GebwebApp app, any keys, dict<string, any> opts = {...}): appmod.GebwebApp

Mount the app's public signing keys as a JWKS document (default /.well-known/jwks.json), so token consumers can verify with crypt.jwtVerify(token, fetchedJwks):

gebweb.useJwks(app, [{"pem": crypt.publicKey(priv), "kid": "2026-06"}]);

Function useRequestContext

func useRequestContext(appmod.GebwebApp app): appmod.GebwebApp

Function cacheInvalidate

func cacheInvalidate(appmod.GebwebApp app, string tag): int

Drop every cached response recorded under tag:

@Cache(ttl: 300, tags: ["user:{id}"]) (on the route) gebweb.cacheInvalidate(app, "user:42"); (after a write)

Function requestLogger

func requestLogger(any request, any logger = null): mwmod.RequestLogger

A logger bound to the request's correlation id.

Function useCacheStore

func useCacheStore(appmod.GebwebApp app, any store): appmod.GebwebApp

Function useIdempotencyStore

func useIdempotencyStore(appmod.GebwebApp app, any store): appmod.GebwebApp

Function memoryIdempotencyStore

func memoryIdempotencyStore(): idemmod.MemoryIdempotencyStore

Function redisPool

func redisPool(dict<string, any> opts): any

Build a shared RedisPool to pass as pool opt to redisCacheStore/redisRateLimit.

Function redisCacheStore

func redisCacheStore(dict<string, any> opts): any

Redis-backed cache store for useCacheStore (see gebweb caching docs).

Function redisRateLimit

func redisRateLimit(dict<string, any> opts): callable

Distributed token-bucket rate limiter backed by Redis. Register with gebweb.before.

Function useRoleExtractor

func useRoleExtractor(appmod.GebwebApp app, callable extractor): appmod.GebwebApp

Override the default role extractor (user.roles read as list<string>). Useful when the user value stores roles under a different field or computes them on demand. Must be called after useAuthenticator.

Function useSecurityScheme

func useSecurityScheme(appmod.GebwebApp app, string name, dict<string, any> definition, bool setAsDefault): appmod.GebwebApp

Register an OpenAPI security scheme on the app. The default useAuthenticator call registers bearerAuth (HTTP / bearer / JWT) automatically. Use this to declare an alternate scheme - an API-key in a header, OAuth2 flows, HTTP basic auth - and pass setAsDefault: true to make it the scheme attached to every @Auth / @RequiresRole-gated operation in the generated spec. Must be called AFTER useAuthenticator.

gebweb.useSecurityScheme(app, "apiKey", { "type": "apiKey", "in": "header", "name": "X-API-Key", }, true);

Function html

func html(any body, int status = 200, ?dict<string, any> headers = null): dict<string, any>

Build an HTML response dict. Status defaults to 200; caller headers merge over the default text/html; charset=utf-8 Content-Type. See gebweb.response for the full set of helpers.

return gebweb.html("

Hi

"); return gebweb.html(rendered, 200, {"Cache-Control": "no-store"});

Function file

func file(string path, ?dict<string, any> opts = null): dict<string, any>

Build a response that serves the file at path. Content-Type is inferred from the extension; set opts.attachment = true to force a download. See gebweb.response.file for all options.

return gebweb.file("./public/logo.png"); return gebweb.file("./exports/report.pdf", {"attachment": true, "filename": "Q1.pdf"});

Function stream

func stream(callable handler, ?dict<string, any> opts = null): dict<string, any>

Build a streaming response. The handler is invoked by the HTTP server with a stream handle (int) usable with http.streamWrite, http.streamFlush, and http.streamClose. See gebweb.response.stream for all options.

import http;

return gebweb.stream(func(int h): void { http.streamWrite(h, "tick\n"); http.streamFlush(h); http.streamClose(h); });

Function badRequest

func badRequest(string detail): errorsmod.BadRequestError

Function unauthorized

func unauthorized(string detail): errorsmod.UnauthorizedError

Function forbidden

func forbidden(string detail): errorsmod.ForbiddenError

Function notFound

func notFound(string detail): errorsmod.NotFoundError

Function conflict

func conflict(string detail): errorsmod.ConflictError

Function unprocessableEntity

func unprocessableEntity(string detail, list<dict<string, any>> errs): errorsmod.UnprocessableEntityError

Function internalServerError

func internalServerError(string detail): errorsmod.InternalServerError

health

Source: gebweb/src/health.gb

Class ProbeResult

class ProbeResult

Result returned by a @HealthCheck method. ok is true on success; message is a short diagnostic; details carries any structured info the probe wants to surface (db version, queue depth, etc.).

Field ok

bool ok

Field message

string message

Field details

dict<string, any> details

Method ProbeResult

func ProbeResult(bool ok, string message = "", dict<string, any> details = {...})

Function passing

func passing(string message = ""): ProbeResult

Function failing

func failing(string message): ProbeResult

Class Probe

class Probe

Field name

string name

Field kind

string kind

Field timeoutMs

int timeoutMs

Field method

callable method

Method Probe

func Probe(string name, string kind, int timeoutMs, callable method)

Class HealthConfig

class HealthConfig

Field probes

list<Probe> probes

Field livenessPath

string livenessPath

Field readinessPath

string readinessPath

Method HealthConfig

func HealthConfig(string livenessPath = "/healthz", string readinessPath = "/readyz")

Function newConfig

func newConfig(dict<string, any> opts = {...}): HealthConfig

Function registerProbes

func registerProbes(HealthConfig config, list<any> instances): void

Walk each instance, find every method decorated with @HealthCheck(...), and append a Probe entry to the config. Methods without a name argument get the class+method name.

Function runProbes

func runProbes(HealthConfig config, string kind): dict<string, any>

Runs all probes for the given kind ("liveness" or "readiness"), aggregating each result with timing into the response body. Returns a {status, body} pair the request handler emits as JSON. A probe that throws or exceeds its timeout fails the overall check; aggregate status is 200 when every probe passes, 503 otherwise.

i18n

Source: gebweb/src/i18n.gb

Class Locale

class Locale

BCP-47 locale tag plus parsed components. The tag is the canonical form (e.g. "en-GB"); language is the primary language subtag ("en"); region is the upper-case region subtag ("GB") or "" if absent; zone is the IANA time- zone name ("Europe/London") or "" if absent.

Field tag

string tag

Field language

string language

Field region

string region

Field zone

string zone

Method Locale

func Locale(string tag, string language = "", string region = "", string zone = "")

Function parseLocale

func parseLocale(string tag): ?Locale

Parses a BCP-47 locale tag into a Locale. Accepts forms like "en", "en-GB", "zh-Hant-TW". Unknown subtags after the first two are ignored. Returns null on malformed input.

Class I18nConfig

class I18nConfig

Configuration for useI18n. locales is the list of supported tags; default is the fallback when negotiation yields nothing; sources is the ordered list of negotiation sources ("url", "cookie", "accept-language"); cookieName is the cookie carrying a sticky choice; urlPrefix controls whether the matched URL prefix is stripped before the router sees the path.

Field locales

list<string> locales

Field defaultTag

string defaultTag

Field sources

list<string> sources

Field cookieName

string cookieName

Field urlPrefix

bool urlPrefix

Field urlStrip

bool urlStrip

Field defaultZone

string defaultZone

Field messagesDir

string messagesDir

Field translator

?Translator translator

Method I18nConfig

func I18nConfig(dict<string, any> opts)

Function negotiate

func negotiate(any request, I18nConfig cfg): Locale

Picks the active locale for a request, applying the configured source order. Returns the resolved Locale (never null); when nothing matches, the default tag is used. When url is in sources and urlStrip is true, the matching prefix is removed from request["path"] so route matching is locale- agnostic.

Class Translator

class Translator

Holds loaded message catalogs and resolves keys with locale fallback. messages is keyed by locale tag, then by flat key. defaultTag is consulted when the requested locale is missing a key; when neither has it, the key itself is returned so the gap is visible without breaking the page.

Field messages

dict<string, dict<string, string>> messages

Field defaultTag

string defaultTag

Method Translator

func Translator(dict<string, dict<string, string>> messages, string defaultTag = "en")

Method translate

func translate(string locale, string key, dict<string, any> args = {...}): string

Method lookup

func lookup(string locale, string key): string

Function loadCatalogs

func loadCatalogs(string dir): dict<string, dict<string, string>>

Loads YAML message catalogs from a directory. Each file <dir>/<tag>.yaml becomes a catalog for that locale; nested keys flatten to dotted strings (auth.login.title). Returns an empty dict when the directory does not exist.

Function formatNumber

func formatNumber(any value, string locale): string

Format an integer or decimal as a string using the locale's thousands and decimal separators. Hand-coded conventions for en, de, fr, es, it, pt, ru, pl, ar, zh, ja; unknown locales fall back to the en-US "1,234.56" style.

Function numberSeparators

func numberSeparators(string locale): dict<string, string>

Returns {"thousands": ..., "decimal": ...} for the locale's preferred numeric separators.

Function formatDate

func formatDate(dict<string, any> parts, string locale, string style = "short"): string

Format a date parts dict ({year, month, day} as produced by datetime.now()) for the locale. style is "short" (numeric) or "long" (month name). Falls back to "short".

Function pluralForm

func pluralForm(string language, int count): string

Returns the CLDR plural category ("zero" | "one" | "two" | "few" | "many" | "other") for count in language. Hand- coded rules for en, de, fr, es, it, nl, pt, ru, pl, ar, zh, ja, ko; unknown languages get the English rule (1 = one, else other).

Function i18nBefore

func i18nBefore(I18nConfig cfg): callable

Returns a request-phase middleware that resolves the locale, sticks it on request["_locale"], and optionally strips the URL prefix so routes stay locale-agnostic.

gebweb.idempotency

Source: gebweb/src/idempotency.gb

Class MemoryIdempotencyStore

class MemoryIdempotencyStore

Field s

any s

Method MemoryIdempotencyStore

func MemoryIdempotencyStore()

Method putIfAbsent

func putIfAbsent(string key, any value, int ttl): bool

Method set

func set(string key, any value, int ttl): void

Method get

func get(string key): any

Method delete

func delete(string key): void

Function memoryIdempotencyStore

func memoryIdempotencyStore(): MemoryIdempotencyStore

Function findIdempotentDecorator

func findIdempotentDecorator(any handler): ?dict<string, any>

Returns the @Idempotent decorator dict on the handler, or null.

Function fingerprint

func fingerprint(dict<string, any> request): string

Function applyIdempotency

func applyIdempotency(any store, dict<string, any> dec, dict<string, any> request, callable runHandler): dict<string, any>

Apply idempotency logic for a handler decorated with @Idempotent. runHandler is a thunk that invokes the handler and returns the response dict. Returns the response dict (either from cache/short-circuit or from runHandler).

gebweb.jobs

Source: gebweb/src/jobs.gb

Class JobConfig

class JobConfig

Per-app jobs configuration: the DB connection, poll interval, retry policy, and the registry of name -> {handler, instance} pairs populated by registerJobHandlers.

Field conn

db.Connection conn

Field pollIntervalMs

int pollIntervalMs

Field maxAttempts

int maxAttempts

Field backoffMs

list<int> backoffMs

Field reclaimAfterMs

int reclaimAfterMs

Field handlers

dict<string, dict<string, any>> handlers

Method JobConfig

func JobConfig(db.Connection conn)

Class Job

class Job

A Job context passed to a handler. Carries the row's id, name, payload, the attempt count (1-based for the current attempt), and a back-reference to the GebwebApp so handlers can resolve DI bindings via gebweb.resolve(job.app, SomeService).

Field id

string id

Field name

string name

Field payload

dict<string, any> payload

Field attempts

int attempts

Field app

any app

Field queue

string queue

Method Job

func Job(string id, string name, dict<string, any> payload, int attempts, any app)

Function newConfig

func newConfig(db.Connection conn, dict<string, any> opts): JobConfig

Build a job queue config backed by conn. Auto-creates the gebweb_jobs table if it doesn't exist. Options:

  • pollIntervalMs (default 1000): worker sleep between polls
  • maxAttempts (default 5): retry ceiling per job
  • backoffMs (default [1s, 5s, 30s, 2m, 10m]): per-retry delay

Most users go through the facade helper gebweb.useJobs(app, conn, opts) which attaches the resulting config to the app.

Function registerHandlers

func registerHandlers(JobConfig config, list<any> instances): void

Walk each provided handler instance, find every method decorated with @Job("name"), and register it. Multiple classes may supply handlers - they are merged into a single registry.

Function enqueue

func enqueue(JobConfig config, string name, dict<string, any> payload, dict<string, any> opts): string

Insert a job row. runAt (optional unix seconds) lets the caller schedule the job for the future; default is "now". Returns the new job id.

Function runWorker

func runWorker(any app, JobConfig config, dict<string, any> opts): void

Run the worker loop. Blocks until the process is killed (or until opts.maxJobs jobs have been processed - useful for tests). Each iteration claims one pending job whose run_at <= now, executes its handler, and writes the outcome back.

Options:

  • maxJobs (default -1, run forever): stop after N completed/failed jobs
  • workerId (default ":"): tag for locked_by

Function get

func get(JobConfig config, string id): ?dict<string, any>

Returns the row for a given job id, or null.

Function stats

func stats(JobConfig config): dict<string, int>

Returns pending+completed+failed counts. Useful for dashboards.

gebweb.jwt

Source: gebweb/src/jwt.gb

Function issue

func issue(string secret, dict<string, any> claims, int ttlSeconds): string

Issue a signed token. claims is a dict of payload entries - any JSON-serializable values. ttlSeconds is added as the exp claim relative to the current time; pass 0 (or omit) to skip the expiry. The iat (issued-at) claim is always set.

Reserved JWT claim names (iss, sub, aud, exp, nbf, iat, jti) are accepted as-is - if you pass "iat" or "exp" in claims, it overrides the automatic value.

Function verify

func verify(string secret, string token): ?dict<string, any>

Verify a token. Returns the claims dict on success, or null when the signature mismatched, the token is malformed, or the exp claim is in the past. Use verifyAt(secret, token, now) with an explicit time for deterministic testing.

Function verifyAt

func verifyAt(string secret, string token, int nowSec): ?dict<string, any>

Verify a token against an explicit current-time seconds. Useful for deterministic tests where time.now() isn't fixed. Same return shape as verify.

Function decode

func decode(string token): ?dict<string, any>

Decode a token's claims WITHOUT verifying the signature. Useful for debugging or inspecting tokens at a trust boundary where verification is done separately. Returns null when the token is malformed.

gebweb.mailing

Source: gebweb/src/mailing.gb

Interface MailerContract

interface MailerContract

Anything that can dispatch a rendered message. Implementations see the rendered subject + HTML body, the recipient address, and an optional "from" override; they are NOT involved in template rendering.

Method deliver

func deliver(string to, string subject, string htmlBody, string fromOverride): void

Class Mailable

class Mailable

Base class for declarative email definitions. Subclass it, set to (and optionally fromOverride), and override subject(), template(), and context(). Reading instance fields from the template through context() is the easiest way to make per-message data available.

Field to

string to

Field fromOverride

string fromOverride

Method Mailable

func Mailable()

Method subject

func subject(): string

Subject line. Override in subclasses.

Method template

func template(): string

View template name (resolved via gebweb.view(app, name, ctx)). Override in subclasses.

Method context

func context(): dict<string, any>

Render context handed to the view. Override to expose whatever fields the template needs.

Class MemoryMailer

class MemoryMailer implements MailerContract

In-memory mailer that captures every send to a list. Use in tests to assert what the application would have sent.

Field sent

list<dict<string, any>> sent

Field _lock

sync.Mutex _lock

Method MemoryMailer

func MemoryMailer()

Method deliver

func deliver(string to, string subject, string htmlBody, string fromOverride): void

Method clear

func clear(): void

Class LogMailer

class LogMailer implements MailerContract

Logging mailer that prints each delivery to stdout. Use in dev when you don't want to spin up an SMTP server but still want to see what the templating produced.

Method deliver

func deliver(string to, string subject, string htmlBody, string fromOverride): void

Class SmtpMailer

class SmtpMailer implements MailerContract

SMTP-backed mailer wrapping the stdlib mailer.Mailer / mailer.smtpTransport. Built via gebweb.smtpMailer(opts) so users don't have to import the stdlib mailer module.

Field inner

stdmailer.Mailer inner

Field defaultFrom

string defaultFrom

Method SmtpMailer

func SmtpMailer(stdmailer.Mailer inner, string defaultFrom)

Method deliver

func deliver(string to, string subject, string htmlBody, string fromOverride): void

Function smtpMailer

func smtpMailer(dict<string, any> opts): SmtpMailer

Build an SmtpMailer from a plain dict of {host, port, username, password, from, startTLS?, tls?}.

Class SesMailer

class SesMailer implements MailerContract

AWS SES v2 mailer. Speaks the SendEmail JSON API at https://email.<region>.amazonaws.com/v2/email/outbound-emails signed with AWS Signature V4. No long-lived connection: each delivery is one HTTPS request.

Field region

string region

Field accessKey

string accessKey

Field secretKey

string secretKey

Field defaultFrom

string defaultFrom

Field endpoint

string endpoint

Method SesMailer

func SesMailer(string region, string accessKey, string secretKey, string defaultFrom, string endpoint)

Method deliver

func deliver(string to, string subject, string htmlBody, string fromOverride): void

Method request

func request(string method, string path, string body): http.Response

Function sesMailer

func sesMailer(dict<string, any> opts): SesMailer

Build an SesMailer from a plain dict of {region, accessKey, secretKey, from, endpoint?}. endpoint defaults to the regional AWS endpoint; override for local stack / VPC endpoints.

Function deliverNow

func deliverNow(MailerContract mailer, string to, string subject, string body, string fromOverride): void

Render the mailable and dispatch through the mailer. Called from gebweb.send (sync path) and from the _gebweb_mailer_deliver job handler (async path).

Function renderPayload

func renderPayload(any app, Mailable mail, callable renderView): dict<string, any>

Build the {to, subject, body, from} payload that flows through the queue when send() defers to the worker. Centralised so the job-handler payload shape stays in lockstep with what send() produces.

Class MailerJobHandler

class MailerJobHandler

Built-in @Job handler used when a jobs queue is active. The facade wires this in via registerJobHandlers. Looks up the mailer from job.app.mailer and delivers.

Method deliver

func deliver(any job): void

Decorators: Job("_gebweb_mailer_deliver")

gebweb.messaging

Source: gebweb/src/messaging.gb

Class MessagingConfig

class MessagingConfig

Per-app messaging configuration: a registry of named broker handles plus the @OnMessage handler registry.

Field handles

dict<string, dict<string, any>> handles

Field handlers

dict<string, list<dict<string, any>>> handlers

Method MessagingConfig

func MessagingConfig()

Function newConfig

func newConfig(): MessagingConfig

Function useQueue

func useQueue(MessagingConfig config, string name, any handle): void

Register a named queue handle. The name is what @OnMessage decorators refer to; handle is the return value of messaging.connect({...}) (a MessageQueue).

Function useTopic

func useTopic(MessagingConfig config, string name, any handle): void

Register a named topic handle. The name is what @OnMessage decorators refer to; handle is the return value of messaging.topic({...}) (a MessageTopic).

Function registerHandlers

func registerHandlers(MessagingConfig config, list<any> instances): void

Walk each instance, find every method decorated with @OnMessage("handle-name"), and register it under that handle's name. A single method may handle multiple handles by stacking decorators.

Function runWorker

func runWorker(any app, MessagingConfig config, dict<string, any> opts): void

Run the messaging worker loop. For each registered handle that has at least one @OnMessage handler, the worker drives one consume / subscribe loop on the calling thread. To consume multiple handles concurrently, call this from inside an async.scope or spawn the worker per handle.

Options:

  • handle (string, optional): only run the loop for this one handle. Useful when a process is dedicated to a single queue / topic.
  • handles (list, optional): only run the loop for the handles in this list. Use when one process owns a subset of handles (e.g. a worker server pinned to orders and audit).

Function runHandleLoop

func runHandleLoop(any app, MessagingConfig config, string handleName): void

Run the consume / subscribe loop for a single handle name. Blocks until the broker handle is closed or the loop throws. Exposed so callers can spawn one task per handle for concurrent consumption.

Function handlerCount

func handlerCount(MessagingConfig config, string handleName): int

Number of @OnMessage handlers registered for handleName.

Function handle

func handle(MessagingConfig config, string name): any

Returns the registered handle (queue or topic) under name, or null when no such handle exists.

gebweb.metrics

Source: gebweb/src/metrics.gb

Class MetricsConfig

class MetricsConfig

Field counters

store.Store counters

Field path

string path

Method MetricsConfig

func MetricsConfig(string path)

Function newConfig

func newConfig(dict<string, any> opts = {...}): MetricsConfig

Function wrapRouteMetrics

func wrapRouteMetrics(callable adapter, callable configLookup, string method, string route): callable

Wraps a route adapter so every request records count, duration, and in-flight gauge under the route's template label. The config resolves lazily so useMetrics can be wired after app(); routes record nothing until it is.

Function renderPrometheus

func renderPrometheus(MetricsConfig config): string

Renders the counters as Prometheus text format (version 0.0.4).

gebweb.middleware

Source: gebweb/src/middleware.gb

Function cors

func cors(dict<string, any> opts): callable

CORS middleware. opts:

  • "origin" (string): allowed origin. Defaults to "*".
  • "methods" (string or list): comma-joined list. Defaults to "GET,POST,PUT,PATCH,DELETE,OPTIONS".
  • "headers" (string or list): comma-joined list. Defaults to "Content-Type,Authorization".
  • "credentials" (bool): include Access-Control-Allow-Credentials: true. Defaults false.

Function securityHeaders

func securityHeaders(dict<string, any> opts): callable

A conservative set of browser security headers (X-Content-Type- Options, X-Frame-Options, Referrer-Policy). opts accepts an extra dict of additional headers to merge in:

gebweb.use(app, mw.securityHeaders({ "extra": {"Strict-Transport-Security": "max-age=31536000"} }));

Function requestId

func requestId(): callable

Request-ID propagation: sets X-Request-ID on outgoing responses (or copies it from the request when present).

Function requestContext

func requestContext(): callable

Request-phase half of the request-context convention: ensures every request carries a correlation id (inbound X-Request-Id or a fresh one) readable as req.requestId(). Wired by gebweb.useRequestContext(app) together with the response header.

Function requestContextHeader

func requestContextHeader(): callable

Response-phase half: echo the correlation id on the response.

Class RequestLogger

class RequestLogger

A logger bound to one request's correlation id: every entry carries requestId alongside the call's own fields.

Field logger

any logger

Field requestId

string requestId

Method RequestLogger

func RequestLogger(any logger, string requestId)

Method withId

func withId(dict<string, any> fields): dict<string, any>

Method info

func info(string message, dict<string, any> fields = {...}): void

Method warn

func warn(string message, dict<string, any> fields = {...}): void

Method error

func error(string message, dict<string, any> fields = {...}): void

Method debug

func debug(string message, dict<string, any> fields = {...}): void

Function requestLogger

func requestLogger(any request, any logger = null): RequestLogger

Build a RequestLogger for the given request (see useRequestContext).

Function requestLog

func requestLog(dict<string, any> opts): callable

Request access log: logs method + path + status after each response. Pass {"logger": <handle>} to use a custom log handle, otherwise stdout.

Function etag

func etag(dict<string, any> opts = {...}): callable

Gzip response middleware. When the request's Accept-Encoding header includes gzip, the response body is compressed and a Content-Encoding: gzip header is added. Bodies whose Content-Type is already a compressed format (image/, audio/, video/*, application/zip, etc.) or smaller than the configured minBytes threshold are passed through unchanged.

Options:

  • "minBytes" (int): skip compression for bodies smaller than this size in bytes. Defaults to 1024.
  • "skipContentTypes" (list): additional Content-Type prefixes to skip. The built-in skips image/, audio/, video/, application/zip, application/gzip, application/octet-stream. Conditional-GET middleware: tags 200 GET/HEAD responses with a weak ETag (content hash) and answers If-None-Match revalidations with an empty 304, cutting repeat-view bandwidth. Register response-phase: gebweb.use(app, gebweb.etag()).

Function compress

func compress(dict<string, any> opts): callable

Function rateLimit

func rateLimit(dict<string, any> opts): callable

Token-bucket rate limiter middleware. Tracks one bucket per client key (default: remote address). When the bucket is exhausted the middleware short-circuits with a 429 Too Many Requests response.

Options:

  • "perSecond" (int): tokens added per second. Defaults to 10.
  • "burst" (int): bucket capacity. Defaults to perSecond * 2.
  • "keyFn" (callable): receives the request, returns the string key. Defaults to the engine-resolved client IP, which only honours X-Forwarded-For from peers listed in the server's trustedProxies option - a direct client cannot spoof its key.
  • "message" (string): response body for rejected requests. Defaults to "rate limit exceeded".

Buckets live in process memory, so this is single-instance; production deployments behind a load balancer should use an external limiter (Redis bucket, gateway feature). The implementation deliberately stays in pure Geblang to keep the framework portable.

Function wrapRouteMaxBody

func wrapRouteMaxBody(callable adapter, int maxBytes): callable

Wraps a route adapter with a per-route body cap (@MaxBody(bytes)). Oversize bodies answer 413 Problem Details without invoking the handler. The app-level cap still applies; a route cap can only tighten it.

Function sweepStaleBuckets

func sweepStaleBuckets(store.Store buckets, int now, int staleAfterMs): void

Drops token buckets idle past staleAfterMs. A bucket that idle has fully refilled, so removing it is lossless; this bounds limiter memory under client-key churn.

Function abuseGuard

func abuseGuard(dict<string, any> opts): callable

Automatic abuse / bot guard. Detects credential-scanner and exploit probes - requests for paths like /root/.aws/credentials, .git-credentials, /wp-admin - and bans the offending client IP for a TTL, short-circuiting all further requests from it with 403 before they reach routing. Register with gebweb.before so banned traffic costs almost nothing.

opts:

  • "banSeconds" (int, default 3600): how long a banned IP stays blocked.
  • "threshold" (int, default 1): probes from an IP before it is banned.
  • "badPaths" (list): extra case-insensitive path substrings treated as probes, merged with the built-in credential/exploit list.
  • "allowIps" (list): keys (IPs) that are never banned.
  • "message" (string): the 403 detail text.
  • "onBan" (callable): called with the key string when a ban is applied.
  • "keyFn" (callable): receives the request, returns the identity key to ban on; default is the client IP. An empty key is never banned.

The client IP honours the server's trustedProxies setting, same as rateLimit, so a direct client cannot spoof it.

Function wrapRouteRateLimit

func wrapRouteRateLimit(callable adapter, int perSecond, int burst): callable

Wraps a route adapter with route-scoped rate limiting. Used by the framework when a handler carries @RateLimit(perSecond, burst?). The state lives in the closure so all requests to the route share one bucket per client key.

Function wrapRouteRateLimitWithClock

func wrapRouteRateLimitWithClock(callable adapter, int perSecond, int burst, callable clock): callable

Function wrapRouteCors

func wrapRouteCors(callable adapter, dict<string, any> opts): callable

Wraps a route adapter with route-scoped CORS. Used by the framework when a handler carries @Cors({...}). Adds the standard Access-Control headers to the response and short- circuits preflight OPTIONS requests with 204.

The options dict matches the app-level cors() middleware: origin, methods, headers, credentials.

Function wrapRouteDeprecation

func wrapRouteDeprecation(callable adapter, string sunset): callable

Wraps a route adapter to mark it deprecated: every response carries a Deprecation: true header (RFC 8594), plus a Sunset: <sunset> header when a sunset date is given. Used by the framework for routes (or controllers) carrying @Deprecated.

gebweb.negotiation

Source: gebweb/src/negotiation.gb

Function findProducesDecorator

func findProducesDecorator(any handler): ?dict<string, any>

Function declaredMimes

func declaredMimes(dict<string, any> decorator): list<string>

Function parseAccept

func parseAccept(string header): list<dict<string, any>>

Function negotiate

func negotiate(string accept, list<string> declared): ?string

Function dataToXmlElement

func dataToXmlElement(any data): dict<string, any>

Function negotiateResponse

func negotiateResponse(dict<string, any> decorator, dict<string, any> request, any data, any handler): dict<string, any>

oidc

Source: gebweb/src/oidc.gb

Class OidcProvider

class OidcProvider

Configuration for one OIDC / OAuth2 provider. flavor is "oidc" when the provider issues a signed ID token at the token endpoint, or "github" when the provider returns only an access token and the user profile must be fetched separately.

Field name

string name

Field flavor

string flavor

Field authEndpoint

string authEndpoint

Field tokenEndpoint

string tokenEndpoint

Field userinfoEndpoint

string userinfoEndpoint

Field clientId

string clientId

Field clientSecret

string clientSecret

Field scopes

list<string> scopes

Field issuer

string issuer

Method OidcProvider

func OidcProvider(dict<string, any> opts)

Function google

func google(string clientId, string clientSecret, dict<string, any> opts = {...}): OidcProvider

Function github

func github(string clientId, string clientSecret, dict<string, any> opts = {...}): OidcProvider

Function generic

func generic(dict<string, any> opts): OidcProvider

Class OidcConfig

class OidcConfig

Field providers

list<OidcProvider> providers

Field callbackPathPrefix

string callbackPathPrefix

Field successRedirect

string successRedirect

Field failureRedirect

string failureRedirect

Field userResolver

callable userResolver

Field stateSecret

string stateSecret

Method OidcConfig

func OidcConfig(dict<string, any> opts)

Function loginUrl

func loginUrl(OidcProvider provider, string redirectUri, string stateSecret): dict<string, any>

Build the authorisation URL for provider. Generates a PKCE verifier + challenge and an HMAC-signed state value that the callback verifies. Returns {url, stateCookie}: redirect the browser to url and set stateCookie on the response so the callback can recover the PKCE verifier.

Function verifyState

func verifyState(string stateCookie, string returnedState, string secret): string

Validate the state cookie planted by loginUrl and recover the PKCE verifier. Returns the verifier on success, empty string on failure.

Function exchangeCode

func exchangeCode(OidcProvider provider, string code, string redirectUri, string verifier): dict<string, any>

Exchange the authorization code for tokens. Posts to the provider's token endpoint with the PKCE verifier; returns the parsed token response (access_token, id_token, etc.). The GitHub variant returns only access_token.

Function resolveClaims

func resolveClaims(OidcProvider provider, dict<string, any> tokens): dict<string, any>

Returns the validated claims dict for the authenticated user. For OIDC providers, decodes the ID token and validates iss, aud, and exp. For GitHub, fetches the /user endpoint and synthesises a claims dict with sub, name, email.

gebweb.openapi

Source: gebweb/src/openapi.gb

Function schemaFor

func schemaFor(string t): dict<string, any>

Returns the OpenAPI schema for a single declared type name.

Function build

func build(dict<string, any> info, list<dict<string, any>> routes, ?authmod.AuthConfig auth): dict<string, any>

Build the full OpenAPI 3.1 dict from the app info and the registered route metadata. auth is the app's optional auth config (or null). When present, the spec gains a components.securitySchemes section and every operation whose handler or controller class carries @Auth / @RequiresRole gets a matching security requirement. A handler parameter typed as the registered user class is also omitted from the spec's path/query/body parameter list.

gebweb.plugin

Source: gebweb/src/plugin.gb

Interface PluginContract

interface PluginContract

PluginContract is the interface a Gebweb plugin honours. Any value satisfying this shape can be registered via gebweb.plugin(app, instance); the framework calls install once and tracks the instance on app.plugins for later lookup by name().

The app parameter on install is typed as any here to keep gebweb.plugin and gebweb.app modules acyclic; in practice implementations cast to GebwebApp (or the framework calls install with a GebwebApp, which satisfies any).

Method name

func name(): string

Method install

func install(any app): void

Class Plugin

class Plugin implements PluginContract

Plugin is the convenience base class implementing PluginContract. Subclass it and override install:

class MyPlugin extends gebweb.Plugin { dict<string, any> config;

func MyPlugin(dict<string, any> config) { parent("my-plugin"); this.config = config; }

func install(any app): void { gebweb.use(app, this.middleware()); // register routes, services, etc. }

func middleware(): callable { return func(any req, any res): any { return res; }; } }

gebweb.plugin(app, MyPlugin({"key": "value"}));

Plugins are the standard extension point for sibling Geblang packages: they register middleware, mount routes, configure authenticators, and so on through the existing public app API.

Field _name

string _name

Method Plugin

func Plugin(string name)

Method name

func name(): string

Method install

func install(any app): void

Override in a subclass to wire the plugin's behaviour into the app at registration time.

gebweb.profilerbar

Source: gebweb/src/profilerbar.gb

Function mount

func mount(any app, dict<string, any> opts): any

gebweb.query

Source: gebweb/src/query.gb

Class Where

class Where

Where carries one or more predicates as a compiled SQL fragment plus its parameter list. Construct via the module factories (eq, gt, ...) then compose with .and(other) / .or(other) / .not(). Calling code never instantiates Where directly.

Field sql

string sql

Field params

list<any> params

Method Where

func Where(string sql, list<any> params)

Method and

func and(Where other): Where

Method or

func or(Where other): Where

Method not

func not(): Where

Function eq

func eq(string field, any value): Where

field = ?

Function neq

func neq(string field, any value): Where

field <> ?

Function gt

func gt(string field, any value): Where

field > ?

Function ge

func ge(string field, any value): Where

field >= ?

Function lt

func lt(string field, any value): Where

field < ?

Function le

func le(string field, any value): Where

field <= ?

Function like

func like(string field, string pattern): Where

field LIKE ? - caller supplies the wildcards.

Function in_

func in_(string field, list<any> values): Where

field IN (?, ?, ?) for a non-empty list. Empty list compiles to a false predicate so the row count is zero.

Function isNull

func isNull(string field): Where

field IS NULL

Function notNull

func notNull(string field): Where

field IS NOT NULL

Function raw

func raw(string sql, list<any> params): Where

Escape hatch: caller-supplied SQL fragment and parameters. Use for predicates the DSL doesn't model yet (e.g. function calls). Always parameterise user input via the params list - never splice values into the SQL string.

Class OrderBy

class OrderBy

Ordering chain. Build with asc(field) / desc(field) then extend with .then(asc/desc(...)). Compiles to a comma-separated ORDER BY clause body (no leading keyword).

Field entries

list<dict<string, string>> entries

Method OrderBy

func OrderBy(list<dict<string, string>> entries)

Method then

func then(OrderBy other): OrderBy

Function asc

func asc(string field): OrderBy

Ascending ordering on a single field.

Function desc

func desc(string field): OrderBy

Descending ordering on a single field.

Class Query

class Query

Query builds a SELECT / COUNT / DELETE statement over a single table. Chained .where / .orderBy / .limit / .offset calls mutate the builder; the terminal .select(cols), .count(), or .delete() returns a {text: string, params: list<any>} dict ready for conn.query(text, params) / conn.exec(text, params).

Field table

string table

Field filter

?Where filter

Field ordering

?OrderBy ordering

Field limit_

int limit_

Field offset_

int offset_

Method Query

func Query(string table)

Method where

func where(Where w): Query

Method orderBy

func orderBy(OrderBy o): Query

Method limit

func limit(int n): Query

Method offset

func offset(int n): Query

Method select

func select(list<string> columns): dict<string, any>

Compile to SELECT cols FROM table [WHERE ...] [ORDER BY ...] [LIMIT n] [OFFSET m]. Pass an empty columns list (or omit) to fall back to *.

Method count

func count(): dict<string, any>

SELECT COUNT(*) AS count FROM table [WHERE ...].

Method delete

func delete(): dict<string, any>

DELETE FROM table [WHERE ...]. ORDER BY / LIMIT / OFFSET are silently dropped - they are not portable across SQLite, Postgres, and MySQL for DELETE.

Method compileSelect

func compileSelect(string colsClause): dict<string, any>

gebweb.redisbackend

Source: gebweb/src/redisbackend.gb

Class RedisPool

class RedisPool

Field free

any free

Field address

string address

Field password

any password

Field db

int db

Method RedisPool

func RedisPool(dict<string, any> opts)

Method connectOne

func connectOne(): any

Method withClient

func withClient(callable fn): any

Class RedisCacheStore

class RedisCacheStore

Field pool

RedisPool pool

Field ttl

int ttl

Field logger

any logger

Method RedisCacheStore

func RedisCacheStore(dict<string, any> opts)

Method get

func get(string key): any

Method set

func set(string key, any value): void

Method set

func set(string key, any value, int ttl): void

Method delete

func delete(string key): void

Method putIfAbsent

func putIfAbsent(string key, any value, int ttl): bool

Method warn

func warn(string op, any e): void

Function redisCacheStore

func redisCacheStore(dict<string, any> opts): RedisCacheStore

Build a RedisCacheStore. Opts: address, ttl (default 300), poolSize (default 8), optional password/db/pool.

Function redisRateLimit

func redisRateLimit(dict<string, any> opts): callable

Distributed token-bucket rate limiter middleware backed by Redis. Opts: address, poolSize, password, db (or pool for a shared RedisPool), perSecond (10), burst (perSecond*2), keyFn (default clientIp), message, failOpen (default true), prefix ("rl:"), logger.

gebweb.repository

Source: gebweb/src/repository.gb

Class Page

class Page

The repository pattern as Gebweb expects it. A repository is the thin layer between a domain class and its persistence backend (database, file, in-memory map, ...). @ApiResource scans the resource class for a static func repository(): Repo method, looks the repo up, and dispatches the CRUD operations through the methods declared on Repository<T>.

The interface is intentionally small: find, list, save, delete. Implementations may add count and findBy to opt into pagination metadata and filtered queries; those are NOT on the base interface so a tiny in-memory store can implement the minimum without ceremony.

Quick example:

class UserRepo implements repository.Repository { db.Connection conn;

func UserRepo(db.Connection conn) { this.conn = conn; }

func find(string id): ?User { ... } func list(repository.Page page): list { ... } func save(User u): User { ... } func delete(string id): void { ... } } Pagination value passed into Repository.list. offset is zero-based; size defaults to 25 for unparameterized requests. sort and direction are optional and may be empty strings when the caller doesn't specify a sort.

Offset/limit pagination uses this Page value; cursor-based pagination is available as the sibling CursorPage value when key-set semantics are needed.

Field offset

int offset

Field size

int size

Field sort

string sort

Field direction

string direction

Method Page

func Page()

Function makePage

func makePage(int offset, int size, string sort, string direction): Page

Convenience constructor with all four fields set explicitly.

Function pageFromQuery

func pageFromQuery(dict<string, string> query): Page

Builds a Page from the decoded query parameters of an HTTP request. Recognised keys: offset (int), limit (int), sort (string), direction ("asc" | "desc"). Missing keys fall back to the Page defaults. Non-int offset/limit values raise the framework's BadRequestError so the client sees a 400.

Interface Repository

interface Repository<T>

The base repository contract. A class implements Repository<MyEntity> to be eligible for @ApiResource auto-CRUD.

  • find(id) - return the entity for the given id, or null if no such entity exists. Implementations choose the id type (string is the most common; int works too).

  • list(page) - return one page of entities. The page argument carries the requested offset, size, and (optionally) sort. Implementations are responsible for honouring whichever fields make sense for the backend.

  • save(entity) - persist the entity (insert or update) and return the stored value. Implementations typically populate any server-generated fields (id, timestamps) on the returned value.

  • delete(id) - remove the entity. Idempotent: deleting a missing entity is not an error.

Optional capabilities not on the base interface (the framework detects them via reflection):

  • count(): int - total count, used for pagination metadata.
  • findBy(dict<string, string>): list<T> - simple filter lookup. The framework wires this to ?filter=field:value query parameters when present.

Generic parameter T is the domain class. Implementations declare the concrete bindings: class UserRepo implements Repository<User>.

Method find

func find(string id): ?T

Method list

func list(Page page): list<T>

Method save

func save(T entity): T

Method delete

func delete(string id): void

Class Cursor

class Cursor

Cursor-based pagination input. Use when the table is large enough that offset-based pagination becomes expensive, or when results change between page fetches and you want a stable view.

after is an opaque cursor returned by a previous listCursor call (base64-encoded). Empty means "start from the beginning". size is the page size; 25 by default.

sort carries the field used to keyset across pages. Implementations choose a sortable, indexed column (typically the primary key for stable iteration).

Field after

string after

Field size

int size

Field sort

string sort

Method Cursor

func Cursor()

Function makeCursor

func makeCursor(string after, int size, string sort): Cursor

Convenience constructor.

Function cursorFromQuery

func cursorFromQuery(dict<string, string> query): Cursor

Builds a Cursor from query parameters. Recognised keys: after (opaque string), limit (int), sort (string). Missing keys fall back to defaults.

Class CursorPage

class CursorPage<T>

Output value for cursor-paginated queries. items is the page; nextCursor is the opaque base64-encoded token to pass back into the next Cursor.after, or null when there are no further items.

Generic over the item type so callers get typed lists back: CursorPage<User> etc.

Field items

list<T> items

Field nextCursor

?string nextCursor

Method CursorPage

func CursorPage(list<T> items, ?string nextCursor)

Function encodeCursor

func encodeCursor(string keysetValue): string

Encode a keyset value as the opaque nextCursor string. Repositories that use the helper can stay agnostic about the cursor format; the base64 wrapper hides the underlying key from clients so it can change between releases without breaking pagination links.

Function decodeCursor

func decodeCursor(string cursor): string

Decode an opaque cursor back to its keyset value. Returns the empty string when the input is empty (i.e. first page). Throws on a malformed cursor so the caller can return 400.

gebweb.request

Source: gebweb/src/request.gb

Class Request

class Request

Field data

dict<string, any> data

Method Request

func Request(dict<string, any> data)

Method __index

func __index(any key): any

Method __setIndex

func __setIndex(any key, any value): void

Method __contains

func __contains(any key): bool

Method contains

func contains(string key): bool

Method set

func set(string key, any value): void

Method toDict

func toDict(): dict<string, any>

Method method

func method(): string

Method path

func path(): string

Method isMethod

func isMethod(string name): bool

Method scheme

func scheme(): string

Method isSecure

func isSecure(): bool

Method host

func host(): string

Method clientIp

func clientIp(): string

Method clientCert

func clientCert(): ?dict<string, any>

Method requestId

func requestId(): string

Method header

func header(string name): ?string

Method isJson

func isJson(): bool
func cookie(string name): ?string

Method query

func query(string name): ?string

Method queryInt

func queryInt(string name): ?int

Method queryBool

func queryBool(string name): ?bool

Method queryAll

func queryAll(string name): list<string>

Method text

func text(): string

Method json

func json(): any

Method routeParam

func routeParam(string name): ?string

Method routeParams

func routeParams(): dict<string, any>

Method locale

func locale(): ?any

Method tenant

func tenant(): ?any

Method user

func user(): ?any

Method csrfToken

func csrfToken(): ?string

Method cspNonce

func cspNonce(): ?string

Method rawQuery

func rawQuery(): string

gebweb.resource

Source: gebweb/src/resource.gb

Class ResourceInfo

class ResourceInfo

Metadata extracted from a resource class's @ApiResource decorator.

Field path

string path

Field entityClass

any entityClass

Field repoClass

any repoClass

Field entityName

string entityName

Field operations

list<string> operations

Field readGroupsConfig

list<string> readGroupsConfig

Field writeGroupsConfig

list<string> writeGroupsConfig

Function scan

func scan(any classRef): ?ResourceInfo

Returns a ResourceInfo when the given class carries an @ApiResource decorator and a static repositoryClass() method; returns null otherwise. The caller (typically gebweb.app(...)) uses the null/non-null distinction to decide whether to treat the entry as a resource or as a regular controller.

Function buildRoutes

func buildRoutes(any app, ResourceInfo info, callable repoLookup, validation.AssertionRegistry assertions, list<dict<string, any>> existing): list<dict<string, any>>

gebweb.response

Source: gebweb/src/response.gb

Function html

func html(any body, int status = 200, ?dict<string, any> headers = null): dict<string, any>

Build an HTML response dict. Status defaults to 200; any caller headers merge over the default Content-Type. Pass null for headers to keep the default Content-Type only.

return gebweb.html("<!doctype html>..."); return gebweb.html("<!doctype html>...", 201); return gebweb.html(rendered, 200, {"Cache-Control": "no-store"});

Function file

func file(string path, ?dict<string, any> opts = null): dict<string, any>

Build a response that serves the file at path. The engine streams the file with HTTP conditional-request semantics (HEAD, Range, If-None-Match/ETag, If-Modified-Since) and sets Content-Length; the file is not read into memory. Content-Type is inferred from the file extension via a small built-in map; application/octet-stream is the fallback for unknown extensions.

Options (all optional):

  • contentType string - explicit Content-Type, overrides ext lookup.
  • attachment bool - when true, add Content-Disposition: attachment.
  • filename string - suggested name; defaults to the base name of path.
  • status int - response status, defaults to 200.
  • headers dict - extra response headers (merged on top).

A missing file yields 404.

Function stream

func stream(callable handler, ?dict<string, any> opts = null): dict<string, any>

Build a streaming response. The handler is invoked by the underlying HTTP server with a stream handle (int) usable with http.streamWrite(handle, chunk), http.streamFlush(handle), and http.streamClose(handle). The handler runs after the status line + headers have been flushed.

Options (all optional):

  • contentType string - default text/plain; charset=utf-8.
  • status int - response status, defaults to 200.
  • headers dict - extra response headers (merged on top).

Note: the in-process TestClient cannot drive the stream handler; use a real gebweb.serve / gebweb.listen to exercise streaming end-to-end.

Function isServeFileMarker

func isServeFileMarker(any value): bool

gebweb.scheduler

Source: gebweb/src/scheduler.gb

Class ScheduleConfig

class ScheduleConfig

Per-app scheduler configuration: the DB connection (used for the leader-election table only), per-tick interval, leader lease duration, the worker id used in leader rows, and the registered tasks list.

Field conn

any conn

Field tickIntervalMs

int tickIntervalMs

Field leaseSec

int leaseSec

Field workerId

string workerId

Field tasks

list<dict<string, any>> tasks

Method ScheduleConfig

func ScheduleConfig(any conn)

Class CronExpr

class CronExpr

Parsed cron expression: each field is the sorted list of allowed values for that position.

Field minute

list<int> minute

Field hour

list<int> hour

Field dom

list<int> dom

Field month

list<int> month

Field dow

list<int> dow

Field text

string text

Method CronExpr

func CronExpr(list<int> minute, list<int> hour, list<int> dom, list<int> month, list<int> dow, string text)

Function newConfig

func newConfig(any conn, dict<string, any> opts): ScheduleConfig

Build a scheduler config bound to conn. The conn drives the leader-election table - typically the same connection used by the jobs queue but it doesn't have to be.

Function registerTasks

func registerTasks(ScheduleConfig config, list<any> instances): void

Walk each instance, find every method decorated with @Scheduled("cron expr"), parse the cron and register the binding. Tasks are keyed by <ClassName>.<methodName>.

Function tick

func tick(ScheduleConfig config): void

Run one scheduler tick. Tries to acquire leadership; if this worker isn't the leader, returns without doing anything. If it is, walks the task list and fires any task whose current-minute timestamp matches the cron and hasn't already been fired this minute by this worker.

The worker loop in gebweb.jobs.runWorker calls this between job polls when a scheduler is configured.

Function parseCron

func parseCron(string expr): CronExpr

Parse a five-field cron expression into a CronExpr. Throws a RuntimeError on malformed input. Whitespace between fields is any run of spaces / tabs.

gebweb.secretstore

Source: gebweb/src/secretstore.gb

Interface SecretsProvider

interface SecretsProvider

Contract a secrets provider must implement. getSecret returns the value or throws RuntimeError if the name is unknown. hasSecret is a non-throwing existence probe.

Method getSecret

func getSecret(string name): string

Method hasSecret

func hasSecret(string name): bool

Class EncryptedFileSecretsProvider

class EncryptedFileSecretsProvider implements SecretsProvider

Built-in provider that decrypts a single PEM-style file on first use. Wire format: AES-256-GCM over the JSON-encoded {name: value} dict, output as nonce || ciphertext, base64-encoded, chunked at 80 chars, wrapped in -----BEGIN GEBWEB SECRETS----- / END marker. The key is 32 raw bytes (typically base64-decoded from config/secrets.key or the GEBWEB_SECRETS_KEY env var).

Field filePath

string filePath

Field key

bytes key

Field cache

?dict<string, any> cache

Method EncryptedFileSecretsProvider

func EncryptedFileSecretsProvider(string filePath, bytes key)

Method getSecret

func getSecret(string name): string

Method hasSecret

func hasSecret(string name): bool

Method loadIfNeeded

func loadIfNeeded(): dict<string, any>

Function encryptedFileSecrets

func encryptedFileSecrets(string filePath = "config/secrets.enc"): EncryptedFileSecretsProvider

Convenience factory. Reads the key via loadKey(): GEBWEB_SECRETS_KEY env var always wins when set; otherwise the default key path. Throws if neither source is available.

Function loadKey

func loadKey(string keyPath = ""): bytes

Resolves the AES-256 key. Precedence: GEBWEB_SECRETS_KEY env var (base64) wins when set, even if keyPath is supplied; this lets prod deployments override file-shipped defaults. Falls back to keyPath (or config/secrets.key) read as base64. Pass "" for keyPath to use the default.

Function encryptSecrets

func encryptSecrets(dict<string, any> values, bytes key): string

Encrypts the JSON dict of secrets into the PEM-style file body the runtime provider expects. Called by gebweb secrets edit / gebweb secrets set.

gebweb.security

Source: gebweb/src/security.gb

Class SecurityConfig

class SecurityConfig

Configuration object built from the user-supplied opts dict.

Field csp

?dict<string, any> csp

Field cspReportOnly

bool cspReportOnly

Field hsts

?dict<string, any> hsts

Field frameOptions

string frameOptions

Field referrerPolicy

string referrerPolicy

Field contentTypeOptions

bool contentTypeOptions

Field needsNonce

bool needsNonce

Function newConfig

func newConfig(dict<string, any> opts): SecurityConfig

Parse the user-supplied opts dict into a SecurityConfig. Defaults are conservative: nosniff + DENY framing + strict-origin-when-cross -origin Referrer-Policy on. CSP and HSTS are off unless asked.

Function mintNonce

func mintNonce(): string

Generate a 16-byte URL-safe base64 nonce.

Function nonceBefore

func nonceBefore(SecurityConfig cfg): callable

Build the request-phase middleware that mints the per-request nonce.

Function headersAfter

func headersAfter(SecurityConfig cfg): callable

Build the response-phase middleware that applies the headers.

gebweb.serialization

Source: gebweb/src/serialization.gb

Function fieldVisible

func fieldVisible(dict<string, any> field, list<string> active): bool

Returns true when a field belongs to the active group set. A field with no @Groups decorator is always included; a field with one is included iff at least one tag matches an active group. Active = empty list means no filter (every field passes).

Function serialize

func serialize(any instance, list<string> active): dict<string, any>

Serialize an instance to a dict, including only fields whose @Groups membership overlaps with at least one of active. An empty active list means no filter (every field serialized).

Function applyInput

func applyInput(any instance, dict<string, any> source, list<string> active): any

Apply a source dict to an instance, but only for fields that are part of the active groups. Mutates the instance in place and returns it for chaining. Fields with @Groups that exclude all active groups are silently dropped from the input - this is the security boundary against clients smuggling protected fields through write endpoints (e.g. passwordHash tagged @Groups("admin") won't update from a public-facing POST).

Function handlerGroups

func handlerGroups(any target): list<string>

Returns the @Groups arguments on a function / class target, or the empty list when no @Groups decorator is present.

servertiming

Source: gebweb/src/servertiming.gb

Function record

func record(any request, string label, int durationMs): void

Function measure

func measure(any request, string label, callable fn): any

Times the callable fn, appends the duration under label, and returns the callable's result. Use to wrap a single operation (DB query, external call) so it surfaces on the response.

Function beforeMiddleware

func beforeMiddleware(): callable

Function afterMiddleware

func afterMiddleware(): callable

softdelete

Source: gebweb/src/softdelete.gb

Function markDeleted

func markDeleted(any entity): any

Stamps entity.deleted_at with the current Unix time. Repos call this in their delete(id) implementation instead of a physical DELETE so the row survives for audit and restore.

Function restore

func restore(any entity): any

Function isDeleted

func isDeleted(any entity): bool

Function excludeDeleted

func excludeDeleted(querymod.Query q): querymod.Query

Adds deleted_at IS NULL to a query so soft-deleted rows are excluded. Use this in repository read methods (find, list, count) by default.

Function withTrashed

func withTrashed(querymod.Query q): querymod.Query

No-op pass-through. Marks a call site as deliberately including trashed rows for callers (admin views, restore screens).

Function onlyTrashed

func onlyTrashed(querymod.Query q): querymod.Query

Adds deleted_at IS NOT NULL so a query returns only the trashed rows. Useful for admin "Recycle bin" views.

gebweb.storage

Source: gebweb/src/storage.gb

Interface StorageContract

interface StorageContract

Backend interface. A concrete backend handles four operations plus a URL helper for serving content to clients.

Method put

func put(string name, any content): void

Method get

func get(string name): ?bytes

Method exists

func exists(string name): bool

Method delete_

func delete_(string name): void

Method url

func url(string name): string

Class MemoryStorage

class MemoryStorage implements StorageContract

Backs storage with an in-process dict. Survives only as long as the GebwebApp does; ideal for unit tests.

Field items

store.Store items

Method MemoryStorage

func MemoryStorage()

Method put

func put(string name, any content): void

Method get

func get(string name): ?bytes

Method exists

func exists(string name): bool

Method delete_

func delete_(string name): void

Method url

func url(string name): string

Method keys

func keys(): list<string>

Returns every stored name. Useful for tests asserting what was written.

Class LocalStorage

class LocalStorage implements StorageContract

Backs storage with a directory on the local filesystem. Names are joined onto the root and rejected if they try to escape via ... Sub-directories are created on demand.

Field root

string root

Field urlPrefix

string urlPrefix

Method LocalStorage

func LocalStorage(string root)

Method withUrlPrefix

func withUrlPrefix(string prefix): LocalStorage

Set the URL prefix that url(name) prepends. Default is empty; set this when the directory is served via a static- file handler at a known path (e.g. "/uploads").

Method put

func put(string name, any content): void

Method get

func get(string name): ?bytes

Method exists

func exists(string name): bool

Method delete_

func delete_(string name): void

Method url

func url(string name): string

Class S3Storage

class S3Storage implements StorageContract

Field bucket

string bucket

Field region

string region

Field accessKey

string accessKey

Field secretKey

string secretKey

Field endpoint

string endpoint

Method S3Storage

func S3Storage(string bucket, string region, string accessKey, string secretKey, string endpoint)

Method put

func put(string name, any content): void

Method get

func get(string name): ?bytes

Method exists

func exists(string name): bool

Method delete_

func delete_(string name): void

Method url

func url(string name): string

Method request

func request(string method, string name, bytes body): http.Response

Build and dispatch a sigv4-signed request.

Function s3Storage

func s3Storage(dict<string, any> opts): S3Storage

Convenience constructor that accepts a dict of options matching the documented S3 storage shape: bucket, region, accessKey, secretKey, optional endpoint.

Function signingKey

func signingKey(string secretKey, string dateStamp, string region, string service): bytes

The HMAC-chain that derives the signing key for a given date, region, and service. Built on crypt.hmacSha256Bytes so each step's raw bytes feed the next HMAC's key without going through hex.

Function canonicalRequest

func canonicalRequest(string method, string canonicalUri, string canonicalQuery, dict<string, string> headers, string payloadHash): string

Build the canonical request string per the sigv4 spec.

Function stringToSignForSigv4

func stringToSignForSigv4(string amzDate, string dateStamp, string region, string service, string canonical): string

Build the string-to-sign blob, given a canonical request and the date / scope.

gebweb.streaming

Source: gebweb/src/streaming.gb

Function isWebSocketRoute

func isWebSocketRoute(any handler): bool

True when the handler carries @WebSocket.

Function isSseRoute

func isSseRoute(any handler): bool

True when the handler carries @Sse.

Function upgradeRoute

func upgradeRoute(callable handler): dict<string, any>

Build a WebSocket upgrade response that calls handler with a live web.websocket.Connection once the client completes the upgrade handshake. The handler should run its own read/write loop and close the connection when done.

Function sseRoute

func sseRoute(list<any> frames): dict<string, any>

Build a buffered text/event-stream response from a list of pre-formatted SSE frames. Each entry must be a string built via web.sse.data / web.sse.event / web.sse.named. Use gebweb.stream(handler) directly when you want push-as-you-go SSE rather than the buffered "produce-all-frames" shape.

gebweb.swaggerui

Source: gebweb/src/swaggerui.gb

Function assetNames

func assetNames(): list<string>

Asset files vendored and served when bundled.

Function serveAsset

func serveAsset(string bundleDir, string name): dict<string, any>

Serve one embedded asset from the bundle extract dir.

Function htmlPage

func htmlPage(string specUrl, string title, bool embedded): string

Returns the HTML for the docs page mounted at /docs. With embedded true the asset URLs point at the local routes serving the bundled copies; otherwise they point at the pinned CDN distribution.

tenancy

Source: gebweb/src/tenancy.gb

Class Tenant

class Tenant

Tenant identifies a single customer account in a multi-tenant application. id is the stable internal key (UUID, slug, numeric); name is a human-readable label; attributes carries any extra fields the resolver chose to attach (plan tier, feature flags). The resolver is free to construct any subclass.

Field id

string id

Field name

string name

Field attributes

dict<string, any> attributes

Method Tenant

func Tenant(string id, string name = "", dict<string, any> attributes = {...})

Class TenantConfig

class TenantConfig

Configuration for useTenant. resolver(request) returns the Tenant (or null when no tenant could be determined). When required is true (the default) a null resolution short- circuits the request with a 400 response; when false the request continues with no tenant bound.

Field resolver

callable resolver

Field required

bool required

Method TenantConfig

func TenantConfig(callable resolver, bool required = true)

Function tenantBefore

func tenantBefore(TenantConfig cfg): callable

Returns the request-phase middleware that resolves the tenant and stashes it on request["_tenant"]. When the resolver returns null and required is true, the middleware short- circuits with a 400 problem-detail response.

Function currentTenant

func currentTenant(dict<string, any> request): ?Tenant

Returns the resolved Tenant for the current request, or null if no tenant is bound. Use this from services that do not receive the request directly.

Function currentTenantId

func currentTenantId(dict<string, any> request): string

Returns the current tenant's id, or "" when no tenant is bound. Convenient for repository queries that take a string tenant_id.

Function stampTenant

func stampTenant(any entity, Tenant tenant): any

Stamps entity.tenant_id with the tenant's id. Idempotent. Returns the entity for chaining.

Function tenantOwns

func tenantOwns(any entity, Tenant tenant): bool

True when entity.tenant_id equals the tenant's id. Use as a guard before returning an entity fetched by id, so a request cannot see another tenant's row.

Function scopedQuery

func scopedQuery(querymod.Query q, Tenant tenant): querymod.Query

Returns a query with tenant_id = ? added to the WHERE clause. Use in repository methods that read or count rows under a tenant scope.

gebweb.testclient

Source: gebweb/src/testclient.gb

Class TestResponse

class TestResponse

Field status

int status

Field headers

dict<string, any> headers

Field body

any body

Method TestResponse

func TestResponse(int status, dict<string, any> headers, any body)

Method json

func json(): any

Returns the body parsed as JSON if it's a string, or as-is when the framework already produced a dict / list.

Method text

func text(): string

Returns the body as a string (json.stringify when not already string).

Method assertStatus

func assertStatus(int want): void

Throws a RuntimeError when the status doesn't match.

Class TestClient

class TestClient

Field app

appmod.GebwebApp app

Field dispatch

callable dispatch

Method TestClient

func TestClient(appmod.GebwebApp app)

Method get

func get(string path): TestResponse

Method post

func post(string path, any body): TestResponse

Method put

func put(string path, any body): TestResponse

Method patch

func patch(string path, any body): TestResponse

Method delete

func delete(string path): TestResponse

Method request

func request(string method, string path, any body, dict<string, any> headers): TestResponse

Send a request with custom headers.

Method multipart

func multipart(string path, dict<string, any> parts, dict<string, any> extraHeaders): TestResponse

POST a multipart/form-data request. parts maps each form field to either a string (rendered as a plain text field) or a dict {"filename": string, "contentType": string, "content": string|bytes} for file parts. Additional headers (e.g. auth) merge in via extraHeaders.

Method send

func send(string method, string path, any body, dict<string, any> headers): TestResponse

gebweb.typedconfig

Source: gebweb/src/typedconfig.gb

Function bind

func bind(any configClass, dict<string, any> parameters, dict<string, any> opts = {...}): any

Resolution order per field dbHost: env PREFIX_DB_HOST (prefix from opts, default "APP"), then the parameter store under dbHost, then the field stays absent. Optional (?T) fields may be absent; required fields that resolve nothing throw, naming the environment variable to set.

Function screamingSnake

func screamingSnake(string name): string

gebweb.types

Source: gebweb/src/types.gb

Function baseTypeName

func baseTypeName(string t): string

Returns the unqualified type name with any leading ? stripped.

Function isPrimitiveType

func isPrimitiveType(string t): bool

True if t (with optional leading ?) names a primitive.

Function isRawRequestType

func isRawRequestType(string t): bool

True if t is one of the names the framework uses for the raw-request escape hatch: a handler with a single parameter of this type receives the request dict unchanged instead of being bound from path / query / body. Only the bare opaque container types qualify - dict<string, MyDTO> would still be auto-bound.

Function isContainerType

func isContainerType(string t): bool

True if t names a generic collection or container with no element info worth schema-referencing (list, set, dict, the same with generic args). Used by the OpenAPI builder to skip emitting $ref schemas for these.

Function isUploadsMapType

func isUploadsMapType(string t): bool

True if t is a dict<string, UploadedFile>-shaped parameter (matching dict<string, UploadedFile>, dict<string, gebweb.UploadedFile>, or dict<string, uploads.UploadedFile>). The framework recognises this as a request signal to parse multipart/form-data and bind the file map.

Function isBodyType

func isBodyType(string t): bool

True if t names a type that should map to a request body when appearing as a non-path handler parameter. Custom user classes qualify, and so does list<UserDTO> / set<UserDTO> (a body-as- array). Primitives, bare containers, and the raw-request escape hatch do not qualify.

gebweb.uploads

Source: gebweb/src/uploads.gb

Class UploadedFile

class UploadedFile

Holds one file part decoded out of a multipart request. The framework constructs instances; user code reads them.

Field filename

string filename

Field contentType

string contentType

Field data

bytes data

Method UploadedFile

func UploadedFile(string filename, string contentType, bytes data)

Method bytes

func bytes(): bytes

The raw payload as bytes.

Method size

func size(): int

The payload length in bytes.

Method saveTo

func saveTo(string path): void

Write the payload to path (overwrites any existing file).

Method saveToStorage

func saveToStorage(any app, string name): void

Write the payload to the app's configured storage backend under name. Convenience for the common pattern:

class UploadController { @Post("/avatar") func upload(dict<string, gebweb.UploadedFile> files): dict<string, any> { let avatar = files["avatar"]; avatar.saveToStorage(app, "avatars/" + currentUser.id + ".jpg"); return {"ok": true}; } }

Requires gebweb.useStorage(app, ...) to have been called.

Function fromParseResult

func fromParseResult(dict<string, any> files): dict<string, UploadedFile>

Wraps a raw multipart-parse result into a dict keyed by form field name with UploadedFile instances. The argument is the dict returned by the native web.parseMultipart(request) (or its files sub-dict).

gebweb.validation

Source: gebweb/src/validation.gb

Class ValidationError

class ValidationError

One assertion failure. The framework throws UnprocessableEntityError(detail, [list of these]) and the error renderer surfaces them as the errors array of the RFC 9457 problem document.

Field field

string field

Field code

string code

Field message

string message

Field params

dict<string, any> params

Method ValidationError

func ValidationError(string field, string code, string message, dict<string, any> params = {...})

Class AssertionRegistry

class AssertionRegistry

The registry of assertion handlers. Built-ins are seeded by builtinAssertions(); user code adds to it via gebweb.registerAssertion. The key is the unqualified rule name (e.g. "email" for @Assert.email).

Field assertions

dict<string, callable> assertions

Method AssertionRegistry

func AssertionRegistry()

Function newRegistry

func newRegistry(): AssertionRegistry

Returns a fresh registry seeded with the built-in assertions.

Function register

func register(AssertionRegistry registry, string name, callable validator): AssertionRegistry

Register a custom assertion under @Assert.<name>.

Function builtinAssertions

func builtinAssertions(): dict<string, callable>

Build the default assertion registry. Each validator takes (value, positional args, named args) and returns null on success or an error-message string on failure.

Function validate

func validate(AssertionRegistry registry, any instance): list<ValidationError>

Walk the instance's class fields, run any @Assert.* decorators against the corresponding field value, and return the list of failures. A field marked @Valid cascades into its nested value (a DTO, a list<DTO>, or a dict<string, DTO>); nested failures carry a dotted / indexed / keyed field path. An empty list means the instance passed validation.

Class UnknownAssertionError

class UnknownAssertionError extends RuntimeError

Raised for an @Assert.<name> that is neither built in nor registered.

Method UnknownAssertionError

func UnknownAssertionError(string message)

Function checkAssertionNames

func checkAssertionNames(AssertionRegistry registry, list<any> classes): void

Throws if a field of the given DTO classes, or of nested @Valid field types, has an unknown @Assert.<name>.

Function classForTypeName

func classForTypeName(string declared): ?any

The class named by a declared type, unwrapping ?, list<T>, set<T> and dict<K, V>; null for non-classes.

Function localize

func localize(any translator, string locale, list<ValidationError> failures): list<ValidationError>

Localise validation failures using a translator. Looks up validation.<code> in the catalog; on hit, interpolates the field name and the failure's params into the result. On miss, the original (English) message is preserved.

gebweb.views

Source: gebweb/src/views.gb

Class View

class View

A compiled template. nodes is the rendered AST; parent is the extends target (or null); blocks is the dict of block-name -> AST that overrides the parent.

Field name

string name

Field nodes

list<dict<string, any>> nodes

Field extendsExpr

?dict<string, any> extendsExpr

Field blocks

dict<string, any> blocks

Method View

func View(string name, list<dict<string, any>> nodes, ?dict<string, any> extendsExpr, dict<string, any> blocks)

Class ViewEngine

class ViewEngine

Compile + cache + render templates. Construct via ViewEngine(dir) or the framework helper gebweb.useViews(app, dir). Filters can be registered at any time with addFilter.

Field dir

string dir

Field _dev

bool _dev

Field cache

dict<string, View> cache

Field _mtimes

dict<string, int> _mtimes

Field filters

dict<string, callable> filters

Field _compiledFilters

list<callable> _compiledFilters

Field _cacheLock

sync.RWMutex _cacheLock

Method ViewEngine

func ViewEngine(string dir)

Method load

func load(string name): View

Load and compile a template; in dev a changed source recompiles, in a built binary the cache is permanent.

Method preload

func preload(list<string> names): ViewEngine

Compile named templates before production traffic starts. Development stays lazy so missing and edited templates follow the normal reload path.

Method fileMtime

func fileMtime(string path): int

Source mtime (Unix nanos) for dev change detection.

Method render

func render(string name, dict<string, any> context): string

Render a template by name with the given context.

Method renderView

func renderView(View view, dict<string, any> context): string

Method addFilter

func addFilter(string name, callable filter): ViewEngine

Register a filter callable. The callable receives the input value as the first argument and any tail args after it.

Method applyCompiledFilter

func applyCompiledFilter(int filterId, string name, any value, list<any> args): any

Method applyFilter

func applyFilter(string name, any value, list<any> args): any

Function bundledPath

func bundledPath(string base, string dir): string

A relative directory resolved inside the bundle extract dir; absolute paths are used as given.

gebweb.waf

Source: gebweb/src/waf.gb

Function ipInCidr

func ipInCidr(string ip, string cidr): bool

Function ipMatchesAny

func ipMatchesAny(string ip, list<string> patterns): bool

Function waf

func waf(dict<string, any> opts): callable

webhooks

Source: gebweb/src/webhooks.gb

Class WebhookSubscription

class WebhookSubscription

Field event

string event

Field url

string url

Field secret

string secret

Field createdAt

int createdAt

Method WebhookSubscription

func WebhookSubscription(string event, string url, string secret = "")

Class WebhookConfig

class WebhookConfig

Per-app webhook delivery config. Stores subscriptions in memory (use opts.store to back with a database) and routes dispatch through the job queue. signatureHeader is the outgoing HMAC header; supply opts.signer(body, secret) to replace the default HMAC-SHA256 signer entirely.

Field subscriptions

list<WebhookSubscription> subscriptions

Field signatureHeader

string signatureHeader

Field timestampHeader

string timestampHeader

Field timestampSkewSeconds

int timestampSkewSeconds

Field signer

?callable signer

Field deadLetter

?callable deadLetter

Field maxAttempts

int maxAttempts

Method WebhookConfig

func WebhookConfig(dict<string, any> opts)

Function newConfig

func newConfig(dict<string, any> opts = {...}): WebhookConfig

Function subscribe

func subscribe(WebhookConfig cfg, string event, string url, string secret = ""): WebhookSubscription

Function unsubscribe

func unsubscribe(WebhookConfig cfg, string event, string url): bool

Function subscriptionsFor

func subscriptionsFor(WebhookConfig cfg, string event): list<WebhookSubscription>

Function defaultSign

func defaultSign(string body, string secret): string

Computes the default HMAC-SHA256 signature for body using secret. Returns sha256=<hex> in the Stripe/GitHub shape.

Function verifySignature

func verifySignature(string body, string secret, string headerValue): bool

Verifies a signature header against the body. Constant-time compare to avoid timing oracles.

Class WebhookJobHandler

class WebhookJobHandler

Built-in @Job handler that delivers a single webhook attempt. Registered automatically by useWebhooks; users do not need to mention it.

Field config

WebhookConfig config

Method WebhookJobHandler

func WebhookJobHandler(WebhookConfig config)

Method send

func send(jobsmod.Job job): void

Decorators: Job("gebweb.webhook.send")

Function deliverNow

func deliverNow(WebhookConfig cfg, WebhookSubscription sub, string event, dict<string, any> payload): dict<string, any>

Posts the payload to sub.url immediately. Throws on non-2xx response. Used internally by the job handler; expose for tests that want a synchronous path.