Filters and Errors

Filters

before/after take an optional path. A trailing covers the prefix and everything under it, so /admin/ guards /admin as well as /admin/users, which is what a guard almost always means:

app.before("/admin/*", req -> req.sessionAttr("user") == null
        ? WebResponse.redirect("/login")    // answers here, so the route handler never runs
        : null);                            // carry on

A before-filter that returns a response ends the request there; returning null continues to the route. To reject without a body of your own, throw new HttpException(HttpStatus.UNAUTHORIZED, "…​") and let error(HttpStatus.UNAUTHORIZED, …​) render it.

An after-filter takes the response the route returned and hands back a replacement, or null to leave it alone:

app.after((req, res) -> res.header("X-Request-Id", requestId()));

Error handlers

error(status, handler) fills in the body for any response that ended on that status with no body, whether from the router, from an HttpException, or from a handler that returned WebResponse.empty(HttpStatus.FORBIDDEN). notFound(handler) is shorthand for error(HttpStatus.NOT_FOUND, handler), so one registration styles the router’s own 404 and every handler-made one alike. A response that already carries a body is left alone. What the error handler returns keeps the headers the framework had already worked out, such as the Allow of a 405, and answers with the registered status unless it sets one of its own. Inside an error handler, req.errorMessage() is the plain-text message the framework would have used.