API Reference
Server Types
Mongoose.Async — Type
Async(router=Router(); nworkers=4, nqueue=1024, poll_timeout=0, max_body,
drain_timeout, request_timeout=0, errors=Dict{Int,Response}())Create a multi-threaded server with nworkers background tasks.
Async compiles with juliac --trim=safe but worker tasks do not receive CPU time in current AOT executables because the Julia task scheduler is not fully operational. Use Server for static binaries.
Keyword Arguments
nworkers::Integer: Number of worker tasks (default:4).nqueue::Integer: Channel buffer size (default:1024).poll_timeout::Integer: Event-loop poll timeout in ms (default:0).max_body::Integer: Maximum request body size in bytes (default: 1MB).drain_timeout::Integer: Graceful shutdown drain timeout (default: 5000ms).request_timeout::Integer: Per-request timeout in ms, 0 = disabled (default:0).errors::Dict{Int,Response}: Custom responses keyed by HTTP status code (500,413,504). Seefail!.
Async(router, config::Config)Create an Async from a Config struct.
Mongoose.Server — Type
Server(router=Router(); poll_timeout=1, max_body, drain_timeout, errors)Create a single-threaded blocking server. Compatible with juliac --trim=safe.
Keyword Arguments
poll_timeout::Integer: Event-loop poll timeout in ms (default:1). Use0for minimum latency at the cost of CPU.max_body::Integer: Maximum request body size in bytes (default: 1MB).drain_timeout::Integer: Graceful shutdown drain timeout (default: 5000ms).errors::Dict{Int,Response}: Custom responses keyed by HTTP status code (500,413,504). Seefail!.
Server(router, config::Config)Create a Server from a Config struct.
Lifecycle
Mongoose.start! — Function
start!(server; host, port, blocking)Start the Mongoose HTTP server. Initializes the manager, binds an HTTP listener, starts worker threads (for Async), and begins the event loop.
When blocking=true, InterruptException (Ctrl+C) is caught and triggers a graceful shutdown automatically — no wrapper code needed in the caller.
Keyword Arguments
host::AbstractString: IP address to bind to (default:"127.0.0.1").port::Integer: Port number to listen on (default:8080).blocking::Bool: Iftrue, blocks until the server is stopped (default:true).
Mongoose.shutdown! — Function
shutdown!() — Stop all running servers.
Collects servers first to avoid mutating the registry during iteration.shutdown!(server)Gracefully stop the server:
- Signal the event loop to stop.
- Wait for in-flight requests to drain (up to
drain_timeout). - Stop worker threads.
- Free all C resources.
- Unregister from the global registry.
Mongoose.plug! — Function
plug!(server, middleware; paths=nothing)Register a middleware. Middleware is executed in FIFO order. Each middleware is a callable <: AbstractMiddleware that receives (request, params, next) and must call next() or return early.
Keyword Arguments
paths::Union{Nothing, Vector{String}}: If provided, the middleware only runs for requests whose URI starts with one of the given prefixes. Requests to other paths skip this middleware and go directly tonext().
Example
plug!(server, cors()) # all paths
plug!(server, apikey(keys=Set(["k"])); paths=["/api"]) # only /api/*
plug!(server, logger(); paths=["/api", "/admin"]) # selective loggingMongoose.mount! — Function
mount!(server, directory)Configure the server to serve static files from directory using the Mongoose C library (mg_http_serve_dir). This bypasses the Julia middleware pipeline and is handled directly on the event-loop thread for maximum performance.
Features provided by the C library at no extra cost:
Range/ partial content (206) for large files and media streamingETagandLast-Modified/ conditional304 Not Modified- Pre-compressed
.gzfiles served withContent-Encoding: gzip - Directory index (
index.html) fallback - Automatic MIME type detection
Static files are served before the middleware pipeline. If you need access control on static assets, use a reverse proxy or serve them from a separate path that is only reachable after authentication.
Example
mount!(server, "public") # GET /* → public/*
mount!(server, "public/assets"; uri_prefix="/assets") # GET /assets/* → public/assets/*Mongoose.fail! — Function
fail!(server, status::Int, response::Response)Register a custom Response to be returned for the given HTTP status code. Applies to: 500 (unhandled exception), 413 (body too large), 504 (timeout).
Custom 404/405 responses are better handled via a wildcard route:
route!(router, :get, "*", req -> Response(Html, read("404.html", String); status=404))Example
fail!(server, 500, Response(Json, """{"error":"Internal error"}"""; status=500))
fail!(server, 413, Response(Json, """{"error":"Body too large"}"""; status=413))Routing
Mongoose.Router — Type
Router — Trie-based dynamic HTTP + WebSocket router.Mongoose.route! — Function
route!(router, method, path, handler) -> routerRegister an HTTP route on router for method and path.
path supports:
- Static segments, e.g.
/health - Typed params, e.g.
/users/:id::Int - Untyped params (String), e.g.
/posts/:slug
Returns the same router to allow chaining.
Mongoose.ws! — Function
ws!(router, path; on_message, on_open=nothing, on_close=nothing)Register a WebSocket endpoint.
Callbacks
on_message(msg::Message) → Message | String | Vector{UInt8} | nothing— called for each frame.on_open(req::Request)— called on upgrade with the HTTP request (optional).on_close()— called on disconnect with no arguments (optional).
Request & Response
Mongoose.Request — Type
Request — Full HTTP request with owned string data.context is lazily allocated — starts as nothing and becomes a Dict{Symbol,Any} on first access via context!.
Mongoose.Response — Type
Response — HTTP response.Mongoose.context! — Function
context!(req) → Dict{Symbol,Any}Return the request context, creating it on first access.
Utilities
Mongoose.Config — Type
ConfigConsolidated configuration for Server and Async. Pass a Config as the second positional argument to either constructor instead of individual keyword arguments.
Fields
| Field | Default | Description |
|---|---|---|
poll_timeout | 1 | Event-loop poll timeout in ms. Use 0 for min latency (high CPU). |
max_body | 1 MB | Maximum request body size in bytes. |
drain_timeout | 5000 | Graceful-shutdown drain period in ms. |
request_timeout | 0 | Per-request timeout in ms; 0 = disabled (Async only). |
nworkers | 4 | Number of worker tasks (Async only). |
nqueue | 1024 | Channel buffer size (Async only). |
errors | Dict() | Custom Response objects keyed by HTTP status (500, 413, 504). |
Example
config = Config(nworkers=8, request_timeout=15_000, max_body=5_242_880)
server = Async(router, config)
plug!(server, health())
start!(server; host="0.0.0.0", port=8080)Config can be built from environment variables:
config = Config(
nworkers = parse(Int, get(ENV, "WORKERS", "4")),
max_body = parse(Int, get(ENV, "MAX_BODY", "1048576")),
request_timeout = parse(Int, get(ENV, "REQ_TIMEOUT", "0")),
)WebSocket Types
Mongoose.Message — Type
Message — WebSocket message payload (text or binary).Middleware
Mongoose.cors — Function
cors(; origins, methods, headers, max_age)Create a CORS middleware.
Keyword Arguments
origins::String: Allowed origins (default:"*").methods::String: Allowed HTTP methods (default:"GET, POST, PUT, PATCH, DELETE, OPTIONS").headers::String: Allowed request headers (default:"Content-Type, Authorization").max_age::Int: Preflight cache duration in seconds (default:86400= 24h).
Example
plug!(server, cors(origins="https://myapp.com"))Mongoose.ratelimit — Function
ratelimit(; max_requests, window_seconds)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).
Example
plug!(server, ratelimit(max_requests=50, window_seconds=30))Mongoose.bearer — Function
bearer(validator)Create a Bearer token authentication middleware. The validator function receives the token string and must return true if valid.
Example
plug!(server, bearer(token -> token == "my-secret-token"))Mongoose.apikey — Function
apikey(; header_name, keys)Create an API key authentication middleware.
Keyword Arguments
header_name::String: Header to read the API key from (default:"X-API-Key").keys::Set{String}: Set of valid API keys.
Example
plug!(server, apikey(keys=Set(["key-123"])))Mongoose.logger — Function
logger(; threshold=0, output=stderr, structured=false)Create a request-logging middleware.
Keyword Arguments
threshold::Int: Only log requests slower than this (default:0= log all) ms.output::IO: IO stream for log output (default:stderr).structured::Bool: Iftrue, emit one JSON object per line (default:false).
Example
plug!(server, logger()) # plain text, all requests
plug!(server, logger(threshold=100)) # only slow requests
plug!(server, logger(structured=true)) # JSON structured logsMongoose.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 returnstrueif the service is healthy (default: always true)ready_check::Function: Function that returnstrueif the service is ready to accept traffic (default: always true)live_check::Function: Function that returnstrueif 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
plug!(server, health(
health_check = () -> check_database(),
ready_check = () -> check_dependencies(),
live_check = () -> true # Process is always alive if running
))Mongoose.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
| Metric | Type | Labels |
|---|---|---|
http_requests_total | counter | method, status |
http_request_duration_seconds | histogram | le (11 buckets: 5ms–10s) |
Example
server = Async(router; nworkers=4)
plug!(server, health())
plug!(server, metrics()) # exposes GET /metrics
start!(server, port=8080)Prometheus scrape_configs:
- job_name: myapp
static_configs:
- targets: ['localhost:8080']
metrics_path: /metricsErrors
Mongoose.RouteError — Type
RouteError — Thrown when route registration fails (e.g., parameter conflicts, invalid methods).Mongoose.ServerError — Type
ServerError — Thrown when server operations fail (e.g., memory allocation, initialization).Mongoose.BindError — Type
BindError — Thrown when the server fails to bind to the specified address/port.JSON
JSON support is enabled by extending encode:
using JSON
Mongoose.encode(::Type{Json}, body) = JSON.json(body)Then use Response(Json, value) anywhere in your handlers.
Static Router
Mongoose.@router — Macro
@router AppType blockGenerate a static router for AppType. Routes are defined as: METHOD("/path", handler)
Typed parameters use :name::Type syntax (mirrors the dynamic router):
@router MyApp begin
get("/", (req) -> Response(200, "OK"))
get("/users/:id::Int", (req, id) -> Response(200, "User $id"))
end