API Reference

Server Types

Mongoose.AsyncType
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.

AOT Compilation

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). See fail!.
source
Async(router, config::Config)

Create an Async from a Config struct.

source
Mongoose.ServerType
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). Use 0 for 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). See fail!.
source
Server(router, config::Config)

Create a Server from a Config struct.

Note

request_timeout is ignored by Server (single-threaded, no task to enforce it). Use Async for per-request timeouts.

source

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: If true, blocks until the server is stopped (default: true).
source
Mongoose.shutdown!Function
shutdown!() — Stop all running servers.
Collects servers first to avoid mutating the registry during iteration.
source
shutdown!(server)

Gracefully stop the server:

  1. Signal the event loop to stop.
  2. Wait for in-flight requests to drain (up to drain_timeout).
  3. Stop worker threads.
  4. Free all C resources.
  5. Unregister from the global registry.
source
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 to next().

Example

plug!(server, cors())                                          # all paths
plug!(server, apikey(keys=Set(["k"])); paths=["/api"])         # only /api/*
plug!(server, logger(); paths=["/api", "/admin"])               # selective logging
Note

Middleware is only supported with the dynamic route! API. The static @router macro bypasses middleware for trim-safe compilation.

source
Mongoose.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 streaming
  • ETag and Last-Modified / conditional 304 Not Modified
  • Pre-compressed .gz files served with Content-Encoding: gzip
  • Directory index (index.html) fallback
  • Automatic MIME type detection
Note

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

Routing

Mongoose.route!Function
route!(router, method, path, handler) -> router

Register 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.

source
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).
source

Request & Response

Mongoose.RequestType
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!.

source
Mongoose.context!Function
context!(req) → Dict{Symbol,Any}

Return the request context, creating it on first access.

source

Utilities

Mongoose.ConfigType
Config

Consolidated configuration for Server and Async. Pass a Config as the second positional argument to either constructor instead of individual keyword arguments.

Fields

FieldDefaultDescription
poll_timeout1Event-loop poll timeout in ms. Use 0 for min latency (high CPU).
max_body1 MBMaximum request body size in bytes.
drain_timeout5000Graceful-shutdown drain period in ms.
request_timeout0Per-request timeout in ms; 0 = disabled (Async only).
nworkers4Number of worker tasks (Async only).
nqueue1024Channel buffer size (Async only).
errorsDict()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")),
)
source

WebSocket Types

Middleware

Mongoose.corsFunction
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"))
source
Mongoose.ratelimitFunction
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))
source
Mongoose.bearerFunction
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"))
source
Mongoose.apikeyFunction
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"])))
source
Mongoose.loggerFunction
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: If true, 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 logs
source
Mongoose.healthFunction
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

plug!(server, health(
    health_check = () -> check_database(),
    ready_check = () -> check_dependencies(),
    live_check = () -> true  # Process is always alive if running
))
source
Mongoose.metricsFunction
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)

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: /metrics
source

Errors

Mongoose.RouteErrorType
RouteError — Thrown when route registration fails (e.g., parameter conflicts, invalid methods).
source

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.@routerMacro
@router AppType block

Generate 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
source