pub fn error_page(
response: Response,
render: impl FnOnce(&ErrorPage) -> Result<Html<String>>,
) -> ResponseExpand description
Renders error responses with the app’s own template (Rails’ public/404.html and 500.html).
Call it from an [axum::middleware::map_response] layer on the app’s
router, so every HTML error gets the layout: Errors returned by
handlers (their ErrorPage), the 404 of the router’s fallback, and
bodyless or plain-text error statuses (axum’s rejections, e.g. a path
that does not parse), whose message is the status’s reason phrase.
Responses that already have an HTML or JSON body, and success
responses, go out unchanged. The status and headers are kept. When
render fails, the error is logged and the plain page is sent. Costs a
template render per error response, no binding call.
ocre new generates this in src/lib.rs, with templates/error.html:
use askama::Template;
use axum::{Router, middleware::map_response, response::{Html, Response}};
use ocre::{Ctx, Error, ErrorPage, Result, render};
fn routes() -> Router<Ctx> {
Router::new()
// ...routes...
.fallback(not_found)
.layer(map_response(error_page))
}
async fn not_found() -> Error {
Error::NotFound
}
#[derive(Template)]
#[template(source = "<h1>{{ error.message }}</h1>", ext = "html")]
struct ErrorView<'a> {
error: &'a ErrorPage,
}
async fn error_page(response: Response) -> Response {
ocre::error_page(response, |error| render(&ErrorView { error }))
}§Examples
use axum::{http::StatusCode, response::{Html, IntoResponse}};
use ocre::Error;
let custom = |error: &ocre::ErrorPage| Ok(Html(format!("<main>{}</main>", error.message)));
let response = ocre::error_page(Error::NotFound.into_response(), custom);
assert_eq!(response.status(), StatusCode::NOT_FOUND);
let rejected = (StatusCode::BAD_REQUEST, "Invalid URL").into_response();
assert_eq!(ocre::error_page(rejected, custom).status(), StatusCode::BAD_REQUEST);