Middleware
Middleware is a function of the form f(stream::HTTP.Stream, next)
, where next
is the following handler/middleware in the list. It’s called in the order it was added, with the matching handler (if any) called last. By default app.middleware
will run on all request methods however you can specify a specific method with app.middleware.get
Bellow are examples of common use cases for middleware
Logging
Log each request method and URL.
function log_request(stream, next)
@info "request" stream.message.method stream.message.url
next(stream)
end
# don't forget to register the middleware
"**"] = [log_request] app.middleware[
Time
The handler below logs the time taken to call the next handlers in the chain.
function time_taken(stream, next)
= now()
x next(stream)
= now() - x
elapsed @info "$(stream.message.target) took $elapsed"
end
# make sure the middleware is first so
# we measure the time of all the downstream handlers
"**"] = [time_taken, ...other_middleware] app.middleware[
Authentication
For example, authentication might look something like this
function authentication(stream, next)
= Bonsai.read(
headers
stream,Header(x_password=String)
)
if headers.x_password != "secret_password"
return Bonsai.write(stream, Status(403), Body("Forbidden"))
else
next(stream)
end
end
function protected_route(stream, next)
return Bonsai.write(stream, Body("Welcome to the club"))
end
function unproteced_route(stream, next)
return Bonsai.write(stream, Body("Welcome to the club"))
end
function register_middleware!(app)
"/protected/**"] = [authentication]
app.middleware["/protected/"] = protected_route
app.get["/"] = unproteced_route
app.get[end
TODO: a proper example using JWTs.
CORS
The below middleware will accept CORS requests from any domain and HTTP method. You can restrict it to specific domains by changing the relevant header e.g "Access-Control-Allow_Origin" => "https://my-website.com"
. For more information on CORS see https://cors-errors.info/
function cors(stream::Stream, next)
= stream.message.response
res
if stream.message.method == "OPTIONS"
= [
headers "Access-Control-Allow-Origin" => "*",
"Access-Control-Allow-Headers" => "*",
"Access-Control-Allow-Methods" => "*",
]for i in headers
setheader(res, i)
HTTP.end
else
= [
headers "Access-Control-Allow-Origin" => "*",
]for i in headers
setheader(res, i)
HTTP.end
next(stream)
end
end
function register_middleware!(app)
# runs on all routes
"**"] = [authentication]
app.middleware[end
Note you probably don’t want to use a wildcard *
for your origin but rather something more specific.