API Reference

Public vs extension API. using Mongoose gives the application-facing surface (servers, requests, responses, middleware builders, helpers). The extension protocols below (router protocol, pipeline seam, format encoding, string utilities) are exported by Mongoose.Kernel and are reachable as Mongoose.<name> or via import Mongoose: <name> — both work without being re-exported at the top level, keeping the user namespace clean.

App

Mongoose.App — Type
App — Mongoose.jl web application.

Use `workers=0` for sync (default) or `workers=N` for async worker pool.

# Constructors
```julia
app = App()                          # sync, dynamic router
app = App(workers=4)                 # async, 4 workers
app = App(workers=4, queue_size=2048) # async with larger queue
app = App(router=my_router)          # bring-your-own router
```

# Configuration keyword arguments
| Keyword                | Default            | Description                            |
|------------------------|--------------------|----------------------------------------|
| `workers`              | `0`                | Worker threads (0 = sync)              |
| `queue_size`           | `1024`             | Max pending requests (async only)      |
| `poll_timeout_ms`      | `1`                | Mongoose poll interval                 |
| `max_body_bytes`       | `MAX_BODY_BYTES`   | Max request body size                  |
| `drain_timeout_ms`     | `DRAIN_TIMEOUT_MS` | Graceful shutdown drain                |
| `request_timeout_ms`   | `0`                | Per-request timeout (0 = disabled)     |
| `ws_max_frame_bytes`   | `MAX_BODY_BYTES`   | Max WebSocket frame size               |
| `ws_idle_timeout_ms`   | `0`                | WS idle timeout (0 = disabled)         |
| `header_timeout_ms`    | `0`                | Close conns without complete headers   |
| `body_timeout_ms`      | `0`                | Max time to receive a request body     |
| `max_header_bytes`     | `64 KiB`           | Max request header size (0 = unlimited)|
| `send_buffer_bytes`    | `1 MiB`            | Unsent bytes per conn (streams + WS)   |
| `max_bg_tasks`         | `4×workers`        | Runaway timed-out tasks before 503     |
| `max_connections`      | `0`                | Max open connections (0 = unlimited)   |
| `router`               | `Router()`         | Custom router instance                 |
| `tls`                  | `nothing`          | `TLSConfig` for HTTPS                  |

# Structure (DESIGN G4)
- `app.config` — immutable `ServerConfig`.
- `app.runtime` — mutable `RunState` (connections, manager, loop, TLS…).
- `app.router`, `app.middlewares`, `app.errors`, `app.services`, … —
  build-phase state; registration after `start!` throws `ServerError`.
- `app.executor` — `SyncExecutor` or `AsyncExecutor` (the worker pool).
source
Mongoose.AbstractServer — Type
AbstractServer — the server protocol.

`App` is the built-in implementation; custom server types implement the
same surface (or subtype `App`). Registration helpers (`route!`, `ws!`,
`use!`, `serve!`, `onerror!`, `onstart!`, `onstop!`) and the read-side
router protocol (`freeze!`, `isfrozen`, `matchroute`, `hasroute`,
`haswsroutes`, `getwsendpoint`, `length`) all work without reaching
through `server.router`.
source
Mongoose.Kernel.start! — Function
start!(app; host, port, blocking, tls)

Start the HTTP server. Initializes manager, binds listener, spawns workers (if async), runs event loop.

When blocking=true (default), the caller blocks until shutdown, and a delivered InterruptException (Ctrl+C) triggers graceful shutdown (drain + onstop! hooks) before start! returns. Graceful shutdown depends on Julia delivering SIGINT as an exception to the waiting task; process managers that only send SIGTERM bypass it.

Example

app = App(workers=4)
get!(app, "/") do req; json(Dict("ok" => true)) end
start!(app; port=8080)
source
Mongoose.shutdown! — Function
shutdown!(server)

Gracefully stop the server: drain requests, stop workers, free resources. In-flight requests and tracked background tasks (see background!, and over-budget handlers from request_timeout_ms) get one shared grace period of drain_timeout_ms ms before teardown; tasks still running after it are left alone, completed ones are dropped.

source
Mongoose.isrunning — Function
isrunning(server) → Bool

Whether the server's event loop is currently running (started and not yet shut down).

source
Mongoose.url — Function
url(server) → Union{Nothing,String}

The bound base URL (e.g. "http://127.0.0.1:8080") while running, nothing otherwise.

source

Routing

Mongoose.Kernel.Router — Type
Router — default `AbstractRouter` implementation.

Supports: static paths, typed parameters (`:id::Int`), string parameters
(`:slug`), and a catch-all wildcard (`*path`, must be the last segment).
`freeze!` closes the route table (registration throws afterwards) and
compiles the closed table into a `CompiledDispatch` — the contract that
makes the router amenable to AOT/`--trim=safe` builds.
source
Mongoose.Kernel.route! — Function
route!(router, method, path, handler; middleware=nothing, metadata=nothing) → router

Register an HTTP route. Supports:

  • Static: /health
  • Typed params: /users/:id::Int
  • String params: /posts/:slug
  • Wildcard: /*path (must be last segment)

middleware is scoped to this route (composed with app-global middleware at dispatch time); it accepts nothing, a single middleware/callable, or a vector/tuple of them. metadata is opaque and available for future OpenAPI-style tooling.

Overlapping parametric routes resolve first-registered-first at dispatch; static routes always take precedence over parametric ones.

source
route!(group, method, path, handler)

Add a route to a group. Path is relative to the group's prefix.

source
Mongoose.Kernel.ws! — Function
ws!(group, path; kwargs...)
ws!(group, path, handler; kwargs...)

Add a WebSocket route to a group. The handler may be positional (shorthand for on_message=handler) or passed as the on_message keyword.

source
Mongoose.Kernel.freeze! — Function
freeze!(server) → server

Close and compile the server's route table: later route!/ws! throw RouteError. See freeze! on routers for the compiled-dispatch details.

source
freeze!(router) → router

Close the route table: any later route!/ws! throws RouteError. Dispatch keeps working. This is the closed-route contract required by AOT/--trim=safe profiles (a static route table can be compiled once and pruned).

Freezing also compiles the closed table into a CompiledDispatch (see compiled.jl): each fixed route and parametric route gets a pre-baked terminal (handler + scoped middleware fused, with the handler's concrete type captured), and parametric matching runs through a statically-typed chain with no per-request path splitting. The pipeline uses the compiled path via getterminal when compiled !== nothing; matchroute keeps its generic (correct) implementation.

source
Mongoose.Kernel.isfrozen — Function
isfrozen(server) → Bool

Whether the server's route table has been closed by freeze!.

source
isfrozen(router) → Bool

Whether freeze! has been called on this router (registration closed; the table compiled). Custom AbstractRouters default to false.

source
Mongoose.Kernel.group — Function
group(prefix; middleware=[]) → RouteGroup

Create a new route group with the given path prefix.

Example

api = group("/api/v1", middleware=[bearer(validate_token)]) do g
    route!(g, :get, "/users", list_users)
    route!(g, :post, "/users", create_user)

    group!(g, "/admin", middleware=[require_role("admin")]) do admin
        route!(admin, :delete, "/users/:id::Int", delete_user)
    end
end
source
Mongoose.Kernel.mount! — Function
mount!(router_or_app, group)

Mount a RouteGroup into a router or app, registering all its routes with the group's prefix applied and its middleware attached as scoped route metadata. The runtime composes scoped middleware with app-global middleware at dispatch time — no per-route closures are created.

Example

api = group("/api/v1") do g
    get!(g, "/users", list_users)
    post!(g, "/users", create_user)
end
mount!(app, api)
source
Mongoose.Kernel.matchroute — Function
matchroute(server, method, path) → RouteResult

Resolve a request against the server's router, without running handlers. See matchroute.

source
matchroute(router, method, path) → RouteResult

Resolve a request to its exhaustive outcome: Matched(endpoint, handlers, params) when the route serves the method, NoMatch when the path matches nothing, or MethodMismatch{allowed} carrying the route's method bitmask. Exact (static) matches win; parametric routes are scanned in registration order; the "*" catch-all is the final fallback. HEAD is served only by an explicit head! route — there is no auto-HEAD fallback.

source
Mongoose.Kernel.hasroute — Function
hasroute(server, path) → Bool

Whether the server's router owns path (catch-all excluded). See hasroute.

source
hasroute(router, path) → Bool

true when a concrete (non-catch-all) route owns the path, regardless of method — used by static file serving to avoid shadowing registered routes (the previous match_route_exact semantic).

source
Mongoose.Kernel.getendpoint — Function
getendpoint(mm, method) → Union{Nothing, Endpoint}

The endpoint registered for method, or nothing; throws RouteError for a method outside the seven supported HTTP methods.

source
Mongoose.Kernel.haswsroutes — Function
haswsroutes(server) → Bool

Whether the server serves any WebSocket endpoints. See haswsroutes.

source
haswsroutes(router) → Bool

Whether the router serves any WebSocket endpoints. Defaults to false; the default Router answers true once a ws! route is registered.

source
Mongoose.Kernel.getwsendpoint — Function
getwsendpoint(server, uri) → Union{Nothing,WSEndpoint}

Resolve the WebSocket endpoint for uri, or nothing. See getwsendpoint.

source
getwsendpoint(router, uri) → Union{Nothing,WSEndpoint}

Resolve the WebSocket endpoint registered for uri, or nothing when the router serves no matching WS route. Defaults to nothing.

source
Mongoose.Kernel.Matched — Type
Matched{endpoint,handlers,params} <: RouteResult

A successful route match. endpoint is the Endpoint for the requested method, handlers carries the route's method information (a MethodMap, or SingleEndpoint for routers with one handler), and params is the typed parameter tuple.

source
Mongoose.Kernel.MethodMismatch — Type
MethodMismatch{allowed::UInt8} <: RouteResult

The path matched but the method isn't registered; allowed is a bitmask of served methods (HEAD is implied by GET). Serialize with allow_from_bitmask for the RFC 9110 §15.5.6 Allow header.

source
Mongoose.Kernel.RouteResult — Type
RouteResult — outcome of `matchroute`: `Matched`, `NoMatch`, or
`MethodMismatch{allowed}` (the last carries the route's method bitmask,
so 405 `Allow` needs no secondary lookup).
source

get!, put!, and delete! are Base methods that Mongoose extends (the other verbs are Mongoose exports). All accept (server_or_router, path, handler) and the do-block form get!(server, path) do req … end.

Request Processing

Mongoose.Kernel.process — Function
process(ctx::RequestContext, request) → Response

Run the full pipeline: attach services to the request context, dispatch the request through any middleware then the router, apply custom error responses for 4xx/5xx results, and map thrown exceptions (typed onerror! handlers first, then the built-in HTTPError/ValidationError mapping).

Arguments

  • ctx::RequestContext — router, middleware stack, error pages, DI services, and typed exception handlers (see RequestContext).
  • request::Request — the transport-agnostic request.

Middleware is composed with the matched route's scoped Endpoint middleware (global → group/route → handler), and it wraps every terminal — including the 404/405 producers — so interception middleware (CORS, health, metrics) observes all requests.

source
Mongoose.Kernel.RequestContext — Type
RequestContext{R,M,E,S,H} — the app-level request-processing bundle.

Collapses the config that `process` needs into one object so the
pipeline seam has a single argument: the router, the app-global middleware
stack, the status→error-page map, the DI services, and the typed exception
handlers.

The global middleware stack is stored as a **baked tuple snapshot** (built
once by `App`/`use!` and immutable afterward), so the per-request pipeline
never re-grows or re-walks a mutable vector and needs no
`[global; scoped]` concatenation.

Standalone use (no server):
```julia
ctx = RequestContext(router; errors=errs, services=(db=pool,))
resp = process(ctx, Request(:get, "/", Dict{String,String}(), Pair{String,String}[], ""))
```
source
Mongoose.Kernel.getterminal — Function
getterminal(router, request) → Union{Nothing,Function}

Optional compiled-dispatch capability. A frozen Router that compiled its route table returns a pre-built terminal (req) → Response for the request (scoped middleware already fused, handler call statically typed); nothing means "fall back to the generic dispatch path".

This is the contract-by-fallback seam that lets the pipeline skip the per-request closure/concat allocation when the router is compiled, without forcing every router implementation to understand compilation.

source
Mongoose.Kernel.invokeendpoint — Function
invokeendpoint(endpoint, request, params) → Response

Call the matched endpoint's handler with the route parameters. The built-in Endpoint dispatches handler(req, params...) (or handler(req) when there are none) — that method lives in process.jl, after Endpoint is defined.

Custom routers that carry their own endpoint type implement this method (and scopedmiddleware) instead of forcing their endpoints into Mongoose.Endpoint.

source
Mongoose.Kernel.scopedmiddleware — Function
scopedmiddleware(endpoint) → Tuple

Scoped middleware owned by a matched endpoint (empty tuple for custom endpoint types). Paired with invokeendpoint for custom routers; the built-in Endpoint stores a captured tuple.

source
Mongoose.Kernel.errorresponse — Function
errorresponse(errors, status) → Response

Look up a custom error response, falling back to module defaults. errors maps HTTP status codes to a static Response or Function(req).

source
Mongoose.Kernel.runpipeline — Function
runpipeline(middlewares, request, handler) → Response
runpipeline(globals, scoped, request, handler) → Response

Run the middleware onion around handler: each middleware receives (request, next); next advances to the following middleware and finally the handler. Middleware may short-circuit by returning without calling next.

The tuple form (the compiled/production path, where route-scoped middleware is already fused into the terminal) walks the baked stack with an immutable callable continuation — Next is a Function, so the (req, next) contract is unchanged, but no closure or cursor is allocated per request.

The four-argument form (generic/dev path) walks the baked app-global stack and the route-scoped stack with one cursor over their virtual concatenation — no [global; scoped] array built per request.

handler may be any 0-arity callable (Function or functor) — the compiled dispatch path passes pre-baked terminal functors.

source
Mongoose.Kernel.asmiddleware — Function
asmiddleware(mw) → AbstractMiddleware

Normalize any middleware into an AbstractMiddleware: AbstractMiddleware instances pass through; any other callable f(req, next) is wrapped in a FunctionMiddleware. This is the single admission point used by use!, by route!/group middleware= metadata, and by Endpoints.

source
Mongoose.Kernel.asmiddlewares — Function
asmiddlewares(input) → Vector{AbstractMiddleware}

Normalize middleware input into a Vector{AbstractMiddleware}: nothing → empty, a single middleware (or plain callable) → one entry, a vector/tuple → one entry per element. Each element goes through asmiddleware.

source
Mongoose.Kernel.attach! — Function
attach!(middleware, server) → middleware

Optional lifecycle hook: use! calls it when middleware is registered, so middleware that needs server state (metrics gauges, readiness checks) can capture a reference. Default is a no-op.

source
Mongoose.Kernel.AbstractRequest — Type
AbstractRequest — protocol for transport-agnostic requests.

`Request` is the default implementation. Transport adapters construct
their own request objects (or reuse `Request`) and the protocol layer
never crosses into FFI types.
source

Request & Response

Mongoose.Kernel.Request — Type
Request — Full HTTP request with owned data.

`query` is parsed lazily: the transport stores the raw query string and
[`parsequery`](@ref) memoizes the parsed `Dict` on first access, so requests
that never read the query pay only the raw-string copy (nothing at all when
there is no query). `context` is allocated on first access the same way.

`services` is the app's DI NamedTuple, set by `process` before dispatch (no
dict allocation, no boxing); [`service`](@ref)/[`withservices`](@ref) read
it directly.

`remote_addr` is the transport-provided peer address (the client's IP as a
string, or `nothing` when the transport does not supply one — e.g. the
standalone pipeline or `FakeTransport`-constructed requests).
source
Mongoose.Kernel.Response — Type
Response — Immutable HTTP response with structured headers.

Headers are stored as a `Vector{Pair{String,String}}` and serialized
to wire format only when sent. Middleware can inspect and modify headers
before they reach the client.
source
Mongoose.Kernel.StreamResponse — Type
StreamResponse — Response whose body is produced incrementally.

The `producer` function receives a `StreamWriter` and writes chunks to it.
The producer runs on its own task, feeding a bounded channel that the
event loop drains — a slow producer never blocks the poll thread or other
connections. Works in both sync and async modes.

# Example
```julia
function sse_handler(req)
    StreamResponse(200, "text/event-stream") do writer
        for i in 1:10
            write(writer, "data: event $i\n\n")
            flush(writer)
            sleep(0.5)
        end
    end
end
```
source
Mongoose.Kernel.Headers — Type
Headers — lightweight wrapper around the parsed header pairs.

Ownership of the type by Mongoose allows defining `get`/`haskey`
without committing Base piracy on `Vector{Pair{String,String}}`.
source
Mongoose.Kernel.asheaders — Function
asheaders(input) → Headers

Normalize accepted header inputs into Headers: a Headers passes through, a single Pair or a vector/tuple of pairs is converted (string keys/values are Stringed; anything else throws ArgumentError).

source
Mongoose.Kernel.mergeheaders — Function
mergeheaders(headers::Headers, extra; prepend=false) → Headers
mergeheaders(response::Response, extra; prepend=false) → Response

Return a new headers list (or a new Response carrying it) with extra merged in; the original is left untouched. extra may be a single pair or a vector of pairs.

This is a concatenation, not a dictionary merge: existing pairs are preserved (including duplicates and order). extra is appended after them by default; prepend=true places extra first so get/haskey find those values before any same-named pair the original carried.

source

Response Helpers

Mongoose.Kernel.json — Function
json(data; status=200, headers=[]) → Response

Create a JSON response. Supports Dict, NamedTuple, Vector, and any JSON-serializable type.

Example

json(Dict("id" => 1, "name" => "Alice"))
json((id=1, name="Alice"))  # NamedTuple
json(Dict("error" => "Not Found"); status=404)
source
Mongoose.Kernel.redirect — Function
redirect(url; status=302, headers=[]) → Response

Return an HTTP redirect response.

Example

redirect("/login")
redirect("https://example.com"; status=301)
source

Request Helpers

Mongoose.Kernel.query — Function
query(req, key) → Union{String, Nothing}
query(req, key, default) → String
query(req, key, default::T) → T  (auto-parses to type of default)

Type-safe query parameter access with optional default and auto-parsing.

Examples

q = query(req, "q", "")           # String with default
page = query(req, "page", 1)      # Auto-parse to Int
limit = query(req, "limit", 20)   # Auto-parse to Int
flag = query(req, "debug", false) # Auto-parse to Bool
source
Mongoose.Kernel.parsejson — Function
parsejson(req) → Any

Parse the request body as JSON. Throws BadRequestError (400) on malformed JSON so the pipeline answers 400 instead of falling through to a 500.

source
Mongoose.Kernel.parsemultipart — Function
parsemultipart(req) → Dict{String, Union{String, MultipartFile}}

Parse a multipart/form-data request body. Returns a Dict where string fields map to their values and file fields map to MultipartFile objects.

Example

post!(app, "/upload") do req
    parts = parsemultipart(req)
    file = parts["avatar"]::MultipartFile
    text("Received $(file.filename) ($(length(file.data)) bytes)")
end
source
Mongoose.Kernel.context — Function
context(req) → Dict{Symbol,Any}

Return the request's per-request context dict, creating it lazily on first access.

Example

get!(app, "/") do req
    ctx = context(req)
    ctx[:user_id] = 42
    json(Dict("ok" => true))
end
source
Mongoose.service — Function
service(req, name) → Any
service(req, ::Val{name}) → T
service(req, name, T) → T

Retrieve a service by name from the request context.

  • service(req, :db) returns the raw value (values may be zero-arg callables, which are invoked).
  • service(req, Val(:db)) avoids re-parsing the name, but the lookup goes through the dynamic request context — the return type is inferred Any.
  • service(req, :db, DBPool) asserts the type and throws otherwise.

For type-stable access in hot paths use withservices, whose closure receives the concrete NamedTuple:

Example

app = App(services=(db=pool, cache=redis))
withservices(req) do svcs
    svcs.db            # concrete: DBPool
end
db = service(req, Val(:db))   # convenient, dynamically typed
source
Mongoose.services — Function
services(req) → NamedTuple

The request's DI services as a NamedTuple (empty when none were registered). Dynamically typed at this boundary; use withservices for type-stable access.

source
Mongoose.withservices — Function
withservices(f, req) → f(services(req))

Function-barrier access to DI services: the closure receives the concrete NamedTuple, so field access inside it specializes — unlike service(req, Val(:x)), which returns a dynamically typed value.

Example

withservices(req) do svcs
    svcs.db.query("select 1")
end
source

URI & String Utilities

Mongoose.Kernel.parsequery — Function
parsequery(query::AbstractString) → Dict{String,String}

Single-pass query string parser. Pre-sized for typical query parameter counts.

source
parsequery(req) → Dict{String,String}

The request's query parameters, parsed from the raw query on first access and memoized. Prefer query for typed lookups; use this when you need the whole dict. (The string method parsequery(str) is the underlying parser.)

source
Mongoose.Kernel.formatheaders — Function
formatheaders(headers) → String

Serialize headers into Mongoose C library format: "Key: Value\r\n".

source
formatheaders(io, headers)

Write the Mongoose header framing for headers into io — used to assemble a response header block in one buffer (no intermediate String).

source
Mongoose.Kernel.urldecode — Function
urldecode(bytes, start_i, end_i; plus=true) → String

Decode a URL-encoded byte range. Handles + → space (form semantics) and %XX hex escapes. Pass plus=false for path segments, where + is a literal character (RFC 3986 §2.3).

source
Mongoose.Kernel.asstrings — Function
asstrings(input) → Vector{String}

Normalize string-ish input into a Vector{String}: nothing → empty, a single AbstractString → one-element vector, a vector/tuple → Stringed entries. Used for paths=, allowed_origins=, and similar collection kwargs.

source

Middleware

Mongoose.use! — Function
use!(app, middleware; paths=[])

Add middleware to an app. middleware may be any callable (req, next) → Response or an AbstractMiddleware subtype; plain functions are wrapped automatically. When paths is non-empty, the middleware only applies to requests whose URI starts with one of the given prefixes.

Example

use!(app, cors())
use!(app, bearer(validate_token); paths=["/api"])
use!(app, (req, next) -> (req.headers ...; next()))
source
Mongoose.Kernel.cors — Function
cors(; origins, allow_methods, allow_headers, max_age_seconds, allow_credentials)

Create a CORS middleware. origins accepts "*", a single origin, or a Vector{String} of allowed origins.

Keyword Arguments

  • origins: Allowed origins (default "*"; a list enables per-origin echo).
  • allow_methods::String: Allowed HTTP methods (default "GET, POST, PUT, PATCH, DELETE, OPTIONS").
  • allow_headers::String: Allowed request headers (default "Content-Type, Authorization").
  • max_age_seconds::Int: Preflight cache duration in seconds (default 86400).
  • allow_credentials::Bool: Emit Access-Control-Allow-Credentials (default false).

Example

use!(app, cors(origins=["https://myapp.com", "https://admin.myapp.com"],
               allow_credentials=true, max_age_seconds=600))
source
Mongoose.Kernel.ratelimit — Function
ratelimit(; max_requests, window_seconds, trust_proxies, key_fn)

Create a rate-limiting middleware using a sharded fixed-window counter. Returns 429 Too Many Requests when the limit is exceeded.

Uses 16 independent shards internally to minimize lock contention.

Keyword Arguments

  • max_requests::Int: Maximum requests allowed per window (default: 100).
  • window_seconds::Int: Time window duration in seconds (default: 60).
  • trust_proxies::Bool: Trust X-Forwarded-For/X-Real-IP for the default bucket key (default: false). Enable only behind a proxy that overwrites these headers; otherwise clients can spoof their bucket. Without it the default key is the request's remote address (per-client host).
  • key_fn::Function: Custom bucket key (Request) -> String, overriding the default IP-based key (e.g. an API key extracted from the request).

Example

use!(server, ratelimit(max_requests=50, window_seconds=30))
use!(server, ratelimit(max_requests=100, key_fn=req -> apikey(req)))
source
Mongoose.Kernel.bearer — Function
bearer(validator)
bearer(secret::String)

Create a Bearer token authentication middleware. When called with a function, validator(token) must return true if valid. When called with a string, uses constant-time comparison to prevent timing attacks.

Example

use!(server, bearer("my-secret-token"))
use!(server, bearer(token -> token in valid_tokens))
source
Mongoose.Kernel.apikey — Function
apikey(keys; header_name="X-API-Key")
apikey(; header_name="X-API-Key", keys)

Create an API key authentication middleware. keys may be a single key string or a collection of keys (Set/Vector); it is normalized to a Set{String} at construction. The positional and keyword forms are equivalent.

Example

use!(server, apikey("key-123"))
use!(server, apikey(Set(["key-123", "key-456"])))
use!(server, apikey(["key-123"]); header_name="x-api-key")
source
Mongoose.Kernel.basicauth — Function
basicauth(user, password; realm="restricted")

Create an HTTP Basic authentication middleware with constant-time credential comparison.

Example

use!(server, basicauth("admin", ENV["ADMIN_PASSWORD"]))
source
Mongoose.Kernel.logger — Function
logger(; threshold_ms=0, output=stderr, structured=false)

Create a request-logging middleware.

Keyword Arguments

  • threshold_ms::Int: Only log requests slower than this (default: 0 = log all) in milliseconds.
  • output::IO: IO stream for log output (default: stderr).
  • structured::Bool: If true, emit one JSON object per line (default: false).

Example

use!(server, logger())                         # plain text, all requests
use!(server, logger(threshold_ms=100))         # only slow requests
use!(server, logger(structured=true))          # JSON structured logs
source
Mongoose.Kernel.health — Function
health(; health_check, ready_check, live_check)

Create a health check middleware for cloud-native deployments.

Keyword Arguments

  • health_check::Function: Function that returns true if the service is healthy (default: always true)
  • ready_check::Function: Function that returns true if the service is ready to accept traffic (default: always true)
  • live_check::Function: Function that returns true if the service is alive (default: always true)

Endpoints

  • GET /healthz: Overall health status (combines all checks)
  • GET /readyz: Readiness for traffic (load balancers)
  • GET /livez: Liveness check (process alive)

Example

use!(server, health(
    health_check = () -> check_database(),
    ready_check = () -> check_dependencies(),
    live_check = () -> true  # Process is always alive if running
))
source
Mongoose.Kernel.metrics — Function
metrics(; path="/metrics")

Create a Prometheus-compatible metrics middleware.

Exposes an HTTP endpoint (default /metrics) in Prometheus text exposition format v0.0.4. Uses 8 internal shards keyed by thread ID to minimize lock contention under concurrent load.

Keyword Arguments

  • path::String: Scrape endpoint path (default: "/metrics").

Metrics

MetricTypeLabels
http_requests_totalcountermethod, status
http_request_duration_secondshistogramle (11 buckets: 5ms–10s)
mongoose_connectionsgaugeopen connections
mongoose_ws_clientsgaugeopen WebSocket clients
mongoose_active_streamsgaugein-flight streaming responses
mongoose_executor_inflightgaugejobs currently executing
mongoose_executor_queue_depthgaugejobs waiting in the executor queue
mongoose_bg_tasksgaugeabandoned timed-out handler tasks
mongoose_ws_frames_droppedgaugeWebSocket pushes dropped (slow readers)

Gauges are emitted once the middleware is registered (use! attaches the server); before that only the counter and histogram are exposed.

Example

app = App(workers=4)
use!(app, health())
use!(app, metrics())   # exposes GET /metrics

start!(app; port=8080)

Prometheus scrape_configs:

- job_name: myapp
  static_configs:
    - targets: ['localhost:8080']
  metrics_path: /metrics
source
Mongoose.Kernel.security — Function
security(; hsts_max_age_seconds, frame_options, content_type_options, referrer_policy, csp)

Create a security headers middleware. All headers are pre-computed at construction time. Each optional header is disabled with nothing (uniform "off" convention); only content_type_options is a plain Bool.

Keyword Arguments

  • hsts_max_age_seconds::Union{Nothing,Int}: HSTS max-age in seconds (default: 31536000 = 1 year). nothing disables the header.
  • frame_options::Union{Nothing,String}: X-Frame-Options value (default: "DENY").
  • content_type_options::Bool: Add X-Content-Type-Options: nosniff (default: true).
  • referrer_policy::Union{Nothing,String}: Referrer-Policy value (default: "strict-origin-when-cross-origin").
  • csp::Union{Nothing,String}: Content-Security-Policy value (default: nothing = not added).
source
Mongoose.Kernel.compress — Function
compress(; min_size_bytes=1024) → Compress

Create a GZip compression middleware. Only compresses responses larger than min_size_bytes bytes when the client sends Accept-Encoding: gzip.

Keyword Arguments

  • min_size_bytes::Int: Minimum response body size to compress (default: 1024 bytes).

Example

use!(app, compress())
use!(app, compress(min_size_bytes=256))  # More aggressive compression
source
Mongoose.Kernel.etag — Function
etag() — add ETag + conditional request middleware (304/412).

# Example
```julia
use!(app, etag())                    # before compress, after cors
use!(app, compress(min_size_bytes=1024))
```
source
Mongoose.Kernel.AbstractMiddleware — Type
Middleware protocol — composable request/response pipeline.

Middleware is a callable `(req, next) → response` that wraps around the
handler ("onion" model). `req` is the `Request`, `next` advances to the
following middleware (and finally the handler); returning a `Response`
without calling `next` short-circuits.

# Implementing Middleware

Subtype `AbstractMiddleware` and implement the call operator:

```julia
struct MyMiddleware <: AbstractMiddleware end

function (mw::MyMiddleware)(req::Request, next::Function)
    # before logic
    response = next()  # call downstream
    # after logic
    return response
end
```

Plain closures/functions work too: `use!`/`route!` wrap them via
`asmiddleware` (see `FunctionMiddleware`). The tag type exists so the
pipeline can hold a typed stack (`Vector{AbstractMiddleware}`).
source
Mongoose.Kernel.FunctionMiddleware — Type
FunctionMiddleware{F} — adapter that lets any callable `f(req, next)` act
as a middleware without subtyping `AbstractMiddleware`.

User code rarely needs this directly: `use!` and `route!(; middleware=...)`
accept plain closures/functions and wrap them automatically.
source
Mongoose.Kernel.Health — Type
Health — Health check middleware for cloud-native deployments.
Intercepts `/healthz`, `/readyz`, and `/livez` before any other middleware.
source
Mongoose.Kernel.Metrics — Type
Metrics — Prometheus-compatible metrics middleware.

Intercepts every request, records latency and status, and exposes the
configured `/metrics` endpoint in Prometheus text exposition format.

Metrics exposed:
- `http_requests_total{method,status}` — counter
- `http_request_duration_seconds{le}` — histogram (11 finite buckets)
source
Mongoose.Kernel.Security — Type
Security — adds standard security headers to all responses.

Protects against common web vulnerabilities (XSS, clickjacking, MIME
sniffing).
source
Mongoose.Kernel.Etag — Type
Etag — middleware that computes strong ETags and handles conditional requests.

Adds an `ETag` header to generated buffered responses (deterministic
FNV-1a over the response body bytes — stable across restarts, no new
dependencies), and applies RFC 9110 §13 preconditions:

- `If-None-Match` match → `304 Not Modified` (GET/HEAD) or
  `412 Precondition Failed` (other methods); `"*"` matches any tag.
- `If-Match` mismatch → `412 Precondition Failed` (strong comparison).
- `If-None-Match` uses weak comparison (`W/` prefixes are stripped).

Streaming responses and raw (non-`Response`) handler returns are passed
through unchanged — they have no serialized body to hash. Register it
outside transformation middleware (e.g. before `compress`) so the ETag
validates the representation that is actually sent.
source
Mongoose.Kernel.Cors — Type
Cors — CORS (Cross-Origin Resource Sharing) middleware.

Handles preflight OPTIONS requests and attaches CORS headers to responses:

- origin allowlist: only listed origins get `Access-Control-Allow-Origin`,
  reflected verbatim (with `Vary: Origin`); `"*"` still means any origin.
- credentials: opt-in `Access-Control-Allow-Credentials: true`
  (`"*"` + credentials is not emitted, per the spec).
- preflight validation: requested method and request headers are checked
  against the allowlists; mismatches get a 403 instead of a blanket 204.
source
Mongoose.Kernel.Bearer — Type
Bearer — Bearer token authentication middleware.
Checks the `Authorization: Bearer <token>` header and delegates validation to a user-supplied function.
source
Mongoose.Kernel.ApiKey — Type
ApiKey — API key authentication middleware.
Reads a header by name and checks it against a set of valid keys.
source
Mongoose.Kernel.BasicAuth — Type
BasicAuth — HTTP Basic authentication middleware.
Validates `Authorization: Basic <base64(user:password)>` with
constant-time comparison.
source
Mongoose.Kernel.RateLimit — Type
RateLimit — fixed-window rate limiting middleware with sharded locks.

Tracks requests per bucket key with automatic cleanup, using N shards
(each with its own lock) to reduce contention under high concurrency.

Buckets are keyed by a user-supplied `key_fn(request) -> String`, or by a
default that keys on the request's transport-provided remote address;
`X-Forwarded-For`/`X-Real-IP` are only trusted when `trust_proxies=true`
(reading proxy headers directly is a spoofing vector when the app is
exposed to clients).
source
Mongoose.Kernel.Compress — Type
Compress — GZip compression middleware.

Compresses response bodies when the client supports it
(Accept-Encoding: gzip). Skips already-compressed, streaming, or small
responses.
source

Server-Sent Events

Mongoose.Kernel.SSEWriter — Type
SSEWriter — Writes Server-Sent Events to a connection.

Used within a `StreamResponse` producer:
```julia
function sse_handler(req)
    sse(req) do writer
        for i in 1:10
            emit(writer; data="tick $i", event="heartbeat", id=string(i))
            sleep(1.0)
        end
    end
end
```
source
Mongoose.Kernel.emit — Function
emit(sse; data, event="", id="", retry_ms=nothing)

Send a single SSE event to the client. Fields:

  • data::String — event payload (required). Multi-line data is handled correctly.
  • event::String — event type/name (optional).
  • id::String — event ID for reconnection (optional).
  • retry_ms::Union{Nothing,Int} — reconnection interval in ms (optional).
source
Mongoose.Kernel.sse — Function
sse([req,] producer; headers=[]) → StreamResponse

Convenience constructor for SSE responses with correct headers.

function stream_events(req)
    sse(req) do writer
        emit(writer; data="hello", event="greeting")
    end
end
source

WebSocket

Mongoose.Kernel.Message — Type
Message — one WebSocket frame.

`data` is either the UTF-8 text of a text frame or the raw bytes of a
binary frame. WebSocket handlers receive a `Message` and may return a
`Message` to reply (or `nothing` for no reply).
source
Mongoose.broadcastws — Function
broadcastws(server, path, data)

Server-initiated WebSocket push: enqueue a text frame for every open client of path (async executors only — the frame is routed through the same reply queue the worker pool uses, so it is sent on the poll/callback thread and is safe to call from any task). Idle/closed clients are skipped naturally: a stale conn id is dropped when drained.

source

Lifecycle

Mongoose.onerror! — Function
onerror!(app, status, handler)
onerror!(handler, app, status)

Register a custom error handler for a specific HTTP status code. handler may be a Response (static) or Function(req) → Response (dynamic). Both argument orders are accepted; the (handler, app, status) form exists so a do-block works.

Example

onerror!(app, 404) do req
    json(Dict("error" => "not found", "path" => req.uri); status=404)
end
source
onerror!(app, ::Type{E}, handler)

Register a typed exception handler: handler(req, e) returns the Response for any handler/middleware error that is a E (or subtype). Handlers are tried in registration order; unhandled exceptions fall through to the default 500 path.

Example

struct NoMatch <: Exception end
onerror!(app, NoMatch) do req, e
    json(Dict("error" => "not found"); status=404)
end
source
Mongoose.onstart! — Function
onstart!(app, f)
onstart!(f, app)

Register a callback to run after the server starts (before accepting connections). Both argument orders are accepted; the (f, app) form exists so onstart!(app) do … end works.

source
Mongoose.onstop! — Function
onstop!(app, f)
onstop!(f, app)

Register a callback to run during graceful shutdown. Both argument orders are accepted; the (f, app) form exists so onstop!(app) do … end works.

source
Mongoose.service! — Function
service!(app, name, value)

Register a service for dependency injection.

service!(app, :db, MyDB.connect())
service(req, :db)      # retrieve inside handler
source
Mongoose.background! — Function
background!(app, f)
background!(f, app)

Schedule a background task to be spawned when start! is called. f should be a zero-argument function. Both argument orders are accepted; the (f, app) form exists so background!(app) do … end works.

background!(app) do
    while true
        cleanup_expired_sessions!()
        sleep(60)
    end
end
source
Mongoose.serve! — Function
serve!(server, directory; uri_prefix="/")

Serve static files from directory under uri_prefix on the URL. The directory is the positional argument; the URL prefix is always the keyword (so the two can never be silently swapped).

Dotfiles (.env, .git, …) are not served; .well-known is allowed for ACME challenges and security.txt. Symlinks inside the directory are followed by the OS, so do not place links that escape the root.

source

Configuration

Mongoose.ServerConfig — Type
ServerConfig — Immutable tuning parameters for the server.

Separated from `App` runtime state to clearly distinguish what's
configuration (set once) vs what changes during execution.
source
Mongoose.TLSConfig — Type
TLSConfig(; cert, key, ca="", name="", skip_verification=false)

TLS options for HTTPS/WSS servers, passed to start!(app; tls=TLSConfig(...)). cert, key, and ca accept file paths, PEM strings, or raw bytes.

The Mongoose_jll build uses Mongoose's built-in TLS, which is TLS 1.3 only — clients pinned to TLS 1.2 (older runtimes, some corporate proxies) cannot connect; terminate at a reverse proxy or rebuild the JLL against OpenSSL if you need 1.2.

Setting ca enables mutual TLS: the server then requires a client certificate signed by that CA (a handshake without one fails). TLS handshakes have no C-level timeout, so configure header_timeout_ms (the accept-time sweep reclaims stalled handshakes) and max_connections on public TLS listeners.

source

Extensibility

Mongoose.Kernel.AbstractRouter — Type
AbstractRouter — pluggable routing protocol.

Any type `R <: AbstractRouter` can be supplied to `App(router=R())`.
The transport and dispatch layers talk to routers exclusively through
this protocol; they never inspect internal fields.

Required protocol for HTTP dispatch:
- `route!(r::R, method, path, handler; middleware=AbstractMiddleware[], metadata=nothing) → r`
  (register an HTTP route; the router stores the handler inside an
  `Endpoint` and never interprets it. The `App` layer normalizes
  `middleware` to a vector before delegating, so a router may assume an
  `AbstractVector`)
- `matchroute(r::R, method, path)`                → a `RouteResult`
  (`Matched` / `NoMatch` / `MethodMismatch{allowed}` — 404/405 and the
  `Allow` set are resolved by the router at match time)
- `hasroute(r::R, path)`                  → `Bool` (path owned, catch-all excluded)
  (no `"*"` fallback — route ownership check for static serving)
- `gethandler(match, method)` / `getendpoint(match, method)` — work on
  any `Matched`, including custom routers' matches and `SingleEndpoint`

Custom routers return a `RouteResult` from `matchroute`. Returning a
`Matched` directly is enough: wrap the endpoint with
`SingleEndpoint(ep, method)` as the match's `handlers` value.

Optional capabilities (safe defaults are provided):
- `haswsroutes(r::R) → Bool`                   (default: `false`)
- `ws!(r::R, path; ...)`                         (no default)
- `getwsendpoint(r::R, uri)`                    (default: `nothing`)
- `length(r::R)`                            (default: `0`)

The default implementation is `Router` in `router.jl`.

## Contract-by-fallback pattern

The `AbstractRouter` protocol is enforced by *fallback methods*: calling a
protocol function on an unimplemented router type throws a `MethodError`
naming the missing method, so a partially-implemented router fails loudly
instead of silently under-dispatching. Optional capabilities default to
"not supported" rather than throwing.
source
Mongoose.Kernel.SingleEndpoint — Type
SingleEndpoint — minimal "handlers" carrier for custom routers that don't
track per-method maps. `gethandler`/`getendpoint` answer for exactly the
one method the endpoint serves.
source
Mongoose.Kernel.Endpoint — Type
Endpoint{F} — what a route owns: handler, scoped middleware, and metadata.

The handler's concrete type is a type parameter, so the endpoint can be
invoked without a dynamic call when its type is known (custom routers,
compiled terminals); registration specializes on the handler type.

The router only stores and returns `Endpoint`s; it does not execute
middleware. `middleware` applies to this route (in addition to app-global
middleware); `metadata` is opaque and available for OpenAPI-style docs.
source
Mongoose.Kernel.AbstractExecutor — Type
AbstractExecutor — controls where and how middleware + handlers run.

The executor is the "where/how to run" half of the runtime. It owns the
concurrency policy (inline vs worker pool), backpressure, and lifecycle of
execution, so the transport and `App` never see `Channel`s or `Task`s.

Handler jobs are closures `() → Union{Nothing, <:Tagged}` producing the
reply to deliver (or `nothing` to drop). The executor only runs them and
ships replies; it never interprets `Request`/`Response`/`Intent`.

Reference implementations:
- `SyncExecutor` — runs each job inline on the calling thread.
- `AsyncExecutor` (server layer) — bounded worker pool + reply queue.

## Contract

- `submit!(executor, job)` — schedule a job. `SyncExecutor` runs it
  inline and returns its value; pool executors return nothing.
- `start!(executor, app)` / `stop!(executor)` — lifecycle.
- `haspending(executor)` — is work still in flight? (drain support)

Missing methods fail loudly via fallback methods below.
source
Mongoose.Kernel.SyncExecutor — Type
SyncExecutor — runs every job inline on the calling thread.

This is the transport-agnostic equivalent of `workers=0` sync mode.
source
Mongoose.AsyncExecutor — Type
AsyncExecutor — bounded worker pool with a reply queue.

Architecture:
- Transport submits closures (`() → Union{Nothing,Kernel.Tagged}`) via `submit!`.
- `workers` threads dequeue and run jobs, pushing replies onto `replies`.
- The event loop drains `replies` (see `dispatch_replies!`) and sends them
  through the transport's connections.
- `supervise_workers!` respawns dead workers on a timer.

The executor never interprets requests/responses; it only runs jobs and
ships the replies they produce. Timeout policy is applied by the transport
when it builds a job.
source
Mongoose.Kernel.stop! — Function
stop!(exec::AsyncExecutor; timeout=5.0)

Stop the worker pool. calls is closed first, then replies are drained while workers are joined so a full reply queue cannot deadlock the join. The join is bounded by timeout seconds: a handler that never returns is abandoned (its task keeps running, as before) instead of hanging shutdown forever.

source
Mongoose.Kernel.FakeExecutor — Type
FakeExecutor — deterministic, thread-free executor for tests.

Mirrors the `AsyncExecutor` contract (queued `submit!`, `haspending`,
`start!`/`stop!`) but never spawns workers: jobs are queued and only run
when the test calls `run!`, inline in submission order. This makes
reply-order/backpressure tests deterministic — no threads, no sleeps.

```julia
fe = FakeExecutor()
submit!(fe, () -> "first")
submit!(fe, () -> "second")
@assert haspending(fe)
@assert run!(fe) == ["first", "second"]
@assert !haspending(fe)
```
source
Mongoose.Kernel.run! — Function
run!(fe::FakeExecutor) → Vector{Any}

Run every queued job inline in submission order, clearing the queue and recording each result.

source
Mongoose.Kernel.AbstractTransport — Type
AbstractTransport — replaceable I/O transport.

The transport is the last FFI boundary: it converts external events into
`Kernel` objects and responses into bytes/frames, and the runtime
never sees `Ptr{Cvoid}`.

Today the transport is a **capability-tagged seam** rather than a callable
interface: implementations declare what they can do via the ability
traits (`canws`, `cantls`, `canstream`), and the server
drives the one C implementation
(`transport/mongoose`). A reference fake (`FakeTransport`, in
`testing.jl`) drives the whole pipeline with no FFI.

The C transport's concrete lifecycle entry points (used by `start!` /
`shutdown!`) are `init_server!`, `bind_server!`,
`spawn_event_loop!`/`stop_event_loop!`, and its send path is
`send_http_response!`/`send_ws_frame!`/`send_stream_response!` in
`transport/mongoose`. Extracting a full `init!/listen!/poll!/send!`
interface behind `AbstractTransport` is deferred: there is a single real
implementation today, and the trait seam already delivers the
replaceability guarantee.

# Capability traits

Optional features are detected via trait functions and never assumed
by the runtime: `canws`, `cantls`,
`canstream`. A transport that cannot do WebSocket simply reports
`false`; HTTP-only apps keep working.
source
Mongoose.Kernel.canws — Function
canws(transport) → Bool

Whether the transport supports WebSocket upgrades. Defaults to false; implementations override it for their capability set.

source
Mongoose.FakeTransport — Type
FakeTransport — reference transport that runs the pipeline with no FFI.

A `FakeTransport` really is a fake transport: it dispatches requests directly
through the middleware pipeline and router (`process`), bypassing
the C event loop entirely. It declares its capabilities via the ability
traits (`canws`, `cantls`, `canstream`): no WebSocket,
no TLS, streaming supported. It can
drive a full request cycle without a running server — including on systems
where `Mongoose_jll` was never loaded.

The transport is **stateful**: it owns a registry of in-flight streams
(`transport.streams`). A streamed response is bound to exactly one
`FakeStream` — after it is delivered (producer completes) the stream is
`done`, and any further write raises `StreamClosedError` (one response per
stream). `close!(transport)` closes every owned stream (writers become
closed) and rejects new requests, modeling the C transport's close cascade.

# Example
```julia
app = App()
get!(app, "/hello") do req
    json((message="Hello World",))
end

client = FakeTransport(app)
resp = client(:get, "/hello")
@assert resp.status == 200
@assert contains(resp.body, "Hello World")
```
source
Mongoose.close! — Function
close!(transport::FakeTransport)

Close the transport: every owned stream is closed (its writer becomes closed) and further requests raise an error.

source
Mongoose.Kernel.validate — Function
validate(req, ::Type{T}; on_error=nothing) → T | Response

Parse and validate the JSON request body into type T. T must be a struct with a keyword constructor or accept a Dict.

Returns the parsed struct, or throws ValidationError if parsing fails. With on_error, a callback (e::ValidationError) → Response is called with the error instead of throwing; the do-block form validate(req, T) do e … end is sugar for on_error=e.

Example

struct CreateUser
    name::String
    email::String
    age::Int
end

post!(app, "/users") do req
    user = validate(req, CreateUser) do e
        json((error=e.message, field=e.field); status=422)
    end
    json((id=1, name=user.name))
end
source
Mongoose.Kernel.ValidationError — Type
ValidationError — Thrown when request body fails validation.

An unhandled ValidationError maps to a 422 Unprocessable Entity response by default at the transport boundary (override with onerror!(app, ValidationError) do req, e … end).

source

Base integrations

Framework types implement the standard Base protocols where it makes sense: length/isempty on Router and App, ordered dict-like views on Headers (pairs, keys, values, plus getindex, haskey, get, iterate, push!/append!/delete!), == on Headers and Response, and terse one-line show for Router, App, Request, Response, and StreamResponse.

Content Formats

Mongoose.Kernel.Plain — Type
Plain — `text/plain; charset=utf-8` content format.

Built-in format marker types (all subtypes of `AbstractFormat`) are
dispatched by the type system for zero-cost content-type resolution. New
formats are added by subtyping `AbstractFormat` and defining `mime` /
`encode` / `decode`.
source
Mongoose.Kernel.encode — Function
encode(Format, body) → String / Vector{UInt8}

Convert body to the wire representation for Format. Extend for custom formats:

Mongoose.encode(::Type{MyFormat}, body) = serialize(body)
source
Mongoose.Kernel.decode — Function
decode(Format, body::String) → Any

Parse a request body from its wire representation. Extend for custom formats:

Mongoose.decode(::Type{MyFormat}, body::String) = deserialize(body)
source

Module

Mongoose.Kernel — Module
Kernel — transport-agnostic core of Mongoose.jl.

Contains everything that does NOT depend on a server or an FFI transport:
protocol types (Request, Response, Headers, formats, cookies, WS types,
validation), the pluggable router, the middleware protocol + built-in
middleware, and the URL/string utilities.

This module is self-contained and can be loaded and tested without the C
Mongoose library: `using Mongoose.Kernel`.

The availability of this layer is what makes the transport replaceable —
anything in `Kernel` can be exercised with pure Julia (see
`Kernel.process` for the request→response seam).
source

Errors

Mongoose.Kernel.HTTPError — Type
HTTPError{status} <: Exception

Exception that maps to an HTTP error response. The status code is a compile-time constant type parameter, so errorstatus(e) is free and onerror!(app, NotFoundError) (or onerror!(app, HTTPError{404})) registers a handler for exactly that status.

Throw it inside a handler (or middleware) to signal a non-200 reply with a custom message:

get!(app, "/users/:id::Int") do req, id
    id in 1:999 || throw(NotFoundError("user $id not found"))
    json((id=id,))
end

A thrown HTTPError is mapped to Response(status, headers, message) automatically at the transport boundary, unless a more specific onerror! handler (checked first) or a custom onerror!(app, status, …) error page takes precedence.

Named aliases are provided for every standard status from 400 to 511 (RFC 9110 plus the common extensions): BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, MethodNotAllowedError, RequestHeaderFieldsTooLargeError, PayloadTooLargeError, UnsupportedMediaTypeError, UnprocessableEntityError, TooManyRequestsError, InternalServerError, HTTPVersionNotSupportedError, … One deliberate gap: 501 has no alias because NotImplementedError is a Base type — use HTTPError{501}.

source