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, rewriterequest["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 ascspNoncein the view context.cspReportOnly- bool. Switches to the report-only header.hsts- dict withmaxAge,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. EmitsX-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 staticrepositoryClass()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.
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
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
_csrfTokenfor view helpers. - On unsafe methods (POST/PUT/PATCH/DELETE), validates the
submitted token (X-CSRF-Token header or
_csrfform 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.optssupplies 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
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 ordersandaudit).
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
func UserRepo(db.Connection conn) { this.conn = conn; }
func find(string id): ?User { ... }
func list(repository.Page page): listRepository.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:valuequery 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
Method cookie
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):
contentTypestring - explicit Content-Type, overrides ext lookup.attachmentbool - when true, addContent-Disposition: attachment.filenamestring - suggested name; defaults to the base name ofpath.statusint - response status, defaults to 200.headersdict - 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):
contentTypestring - defaulttext/plain; charset=utf-8.statusint - response status, defaults to 200.headersdict - 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.