/leaf-error-middleware

Serve up custom 404 and server error pages for your Vapor App

Primary LanguageSwiftMIT LicenseMIT

Leaf Error Middleware

Language Build Status Code Coverage MIT License

Leaf Error Middleware is a piece of middleware for Vapor which allows you to return custom 404 and server error pages.

Note that this middleware is designed to be used for Leaf front-end websites only - it should not be used for providing JSON error responses for an API, for example.

Usage

First, add LeafErrorMiddleware as a dependency in your Package.swift file:

dependencies: [
    // ...,
    .package(url: "https://github.com/brokenhandsio/leaf-error-middleware.git", from: "4.0.0")
],
targets: [
    .target(
        name: "App", 
        dependencies: [
            .product(name: "Vapor", package: "vapor"),
            ..., 
            .product(name: "LeafErrorMiddleware", package: "leaf-error-middleware")
        ]
    ),
    // ...
]

Default Context

To use the LeafErrorMiddleware with the default context passed to templates, register the middleware service in configure.swift to your Application's middleware (make sure you import LeafErrorMiddleware at the top):

app.middleware.use(LeafErrorMiddlewareDefaultGenerator.build())

Make sure it appears before all other middleware to catch errors.

Custom Context

Leaf Error Middleware allows you to pass a closure to LeafErrorMiddleware to generate a custom context for the error middleware. This is useful if you want to be able to tell if a user is logged in on a 404 page for instance.

Register the middleware as follows:

let leafMiddleware = LeafErrorMiddleware() { status, error, req async throws -> SomeContext in
    SomeContext()
}
app.middleware.use(leafMiddleware)

The closure receives three parameters:

  • HTTPStatus - the status code of the response returned.
  • Error - the error caught to be handled.
  • Request - the request currently being handled. This can be used to log information, make external API calls or check the session.

Custom Mappings

By default, you need to include two Leaf templates in your application:

  • 404.leaf
  • serverError.leaf

However, you may elect to provide a dictionary mapping arbitrary error responses (i.e >= 400) to custom template names, like so:

let mappings: [HTTPStatus: String] = [
    .notFound: "404",
    .unauthorized: "401",
    .forbidden: "403"
]
let leafMiddleware = LeafErrorMiddleware(errorMappings: mappings) { status, error, req async throws -> SomeContext in
    SomeContext()
}

app.middleware.use(leafMiddleware)
// OR
app.middleware.use(LeafErrorMiddlewareDefaultGenerator.build(errorMappings: mapping))

By default, when Leaf Error Middleware catches a 404 error, it will return the 404.leaf template. This particular mapping also allows returning a 401.leaf or 403.leaf template based on the error. Any other error caught will return the serverError.leaf template. By providing a mapping, you override the default 404 template and will need to respecify it if you want to use it.

Default Context

If using the default context, the serverError.leaf template will be passed up to three parameters in its context:

  • status - the status code of the error caught
  • statusMessage - a reason for the status code
  • reason - the reason for the error, if known. Otherwise this won't be passed in.

The 404.leaf template and any other custom error templates will get a reason parameter in the context if one is known.