Skip to content

Latest commit

 

History

History
46 lines (31 loc) · 2.71 KB

14 - Error Renderers.md

File metadata and controls

46 lines (31 loc) · 2.71 KB

14 - Error Renderers

Different parts of your app may need to render errors in different ways. For example, a website with a landing page and an API may need two different error renderings. If you go to the wrong address anywhere other than the API, you should get an HTML page that helps you get back to where you want to go. However, if you are in the /api subdirectory, you should get a machine readable JSON error. Here's an example:

Server(errorRenderer: BasicErrorRenderer())
    .register {
        LandingPage()
            .on(.get(.root))
    }
    .group(prefix: "/api", errorRenderer: JSONErrorRenderer()) {
        ListTodos()
            .on(.get("/todos))
    }
    .listen()

With the example, if you go anywhere other than a child of /api, you will get the BasicErrorRenderer. That will simply render the localized description of the error as a string. If you're in the /api subdirectory (or any child), it'll use the JSONErrorRenderer, and show a JSON-parseable error.

BasicErrorRenderer and JSONErrorRenderer are the two error renderers that Meridian ships with. It's likely that you'll want to write your own error renderers, either to match the HTML style of your site, or to customize the output of the JSON.

To create a new error renderer, you need to conform to the ErrorRenderer protocol:

protocol ErrorRenderer {

    func render(primaryError: Error, context: ErrorsContext) async throws -> Response

}

ErrorRenderers can return any Response — JSON, HTML, plain text, or something else — with the content of the error rendered into it. Error renderers will always get at least one error, the primaryError, but the context includes an allErrors array, which can contain more than one error. Because Meridian can find errors in more than one property wrapper simultaneously, any errors besides the first will be included in the context.

ErrorsContext contains a few useful helpers, including a status code you can use when rendering your response (statusCode), a single error message string (errorMessage), and an array of error message strings (errorMessages). These can be useful when rendering your own error responses.

As an example, Meridian's JSONErrorRenderer looks like this:

struct ErrorContainer: Codable {
    let errors: [String]
}

struct JSONErrorRenderer: ErrorRenderer {

    func render(primaryError error: Error, context: ErrorsContext) async throws -> Response {
        return JSON(ErrorContainer(errors: context.errorMessages))
            .statusCode(context.statusCode)
    }
}

The render function can throw, which will close the connection to the peer. This should not be relied on.