Middleware
Bastion.Middleware — plug-style middleware pipeline composition.
Middleware in Bastion is a plain function: Conn -> Conn
A pipeline is an ordered list of such functions. Each function receives the conn returned by the previous one. Processing stops early if any plug marks the conn as halted (via HttpServer.halt or HttpServer.send_resp).
Functions
Returns a plug that halts with 405 Method Not Allowed if the request method is not in the allowed list.
Example:
let only_get = Middleware.allow_methods([Get])Compose two plugs left-to-right into a single plug.
Calls a(conn), then b on the result only if the conn is not halted.CORS middleware builder. Takes an explicit list of allowed origins and returns a plug that echoes the request's Origin header back if — and only if — it is on the allowlist. Unlisted origins receive no Access-Control-Allow-Origin header, which browsers interpret as a block.
There is deliberately no wildcard helper: `*` with credentials-bearing
requests is the classic CORS misconfiguration that leaks authenticated
responses to any site. If you truly need a public API with no cookies,
pass a single-element list containing the literal origin, or write your
own plug.
Example:
let cors = Middleware.cors(["https://app.example.com", "https://admin.example.com"])Sets a default content-type response header of text/html if none has been set.
Logging middleware.
Logs the request method, path, and request_id on every request using
Logger.info. Call this after request_id/1 in your pipeline so the
request_id is available.
Note: response status and timing are not logged here because they are
not yet known when this middleware runs. For full request/response logging
use the Logger.info_conn helper in your handler or after-send hook.Execute a list of plugs in order, stopping when the conn is halted.
Example:
let conn = Middleware.pipeline([logger, auth, my_handler], conn)Request ID middleware.
Reads the incoming x-request-id header if present; otherwise generates a
fresh cryptographically random 16-byte hex ID. Assigns the ID under the
"request_id" key and echoes it back as an x-request-id response header so
clients and proxies can correlate log entries.Returns a plug that assigns a unique sequential request ID to each conn.
Prefers an incoming x-request-id header if present; otherwise calls the
IdCounter actor for a monotonically increasing integer ID.
Spawn the counter once at startup with Middleware.start_id_counter/0:
let counter = Middleware.start_id_counter()
let pipe = Middleware.pipeline([Middleware.request_id_counter(counter), ...], conn)Spawn a sequential ID counter actor. Pass the returned handle to request_id_counter/1.