diff --git a/examples/anyhow-error-response/Cargo.toml b/examples/anyhow-error-response/Cargo.toml new file mode 100644 index 00000000..0c2beb50 --- /dev/null +++ b/examples/anyhow-error-response/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "example-anyhow-error-response" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +anyhow = "1.0" +axum = { path = "../../axum" } +tokio = { version = "1.0", features = ["full"] } diff --git a/examples/anyhow-error-response/src/main.rs b/examples/anyhow-error-response/src/main.rs new file mode 100644 index 00000000..5116b12f --- /dev/null +++ b/examples/anyhow-error-response/src/main.rs @@ -0,0 +1,59 @@ +//! Run with +//! +//! ```not_rust +//! cd examples && cargo run -p example-anyhow-error-response +//! ``` + +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, + routing::get, + Router, +}; +use std::net::SocketAddr; + +#[tokio::main] +async fn main() { + let app = Router::new().route("/", get(handler)); + + let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); + println!("listening on {}", addr); + axum::Server::bind(&addr) + .serve(app.into_make_service()) + .await + .unwrap(); +} + +async fn handler() -> Result<(), AppError> { + try_thing()?; + Ok(()) +} + +fn try_thing() -> Result<(), anyhow::Error> { + anyhow::bail!("it failed!") +} + +// Make our own error that wraps `anyhow::Error`. +struct AppError(anyhow::Error); + +// Tell axum how to convert `AppError` into a response. +impl IntoResponse for AppError { + fn into_response(self) -> Response { + ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("Something went wrong: {}", self.0), + ) + .into_response() + } +} + +// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into +// `Result<_, AppError>`. That way you don't need to do that manually. +impl<E> From<E> for AppError +where + E: Into<anyhow::Error>, +{ + fn from(err: E) -> Self { + Self(err.into()) + } +}