From 8d8388e81aa2b1866bb8214a3cb53c3615a05593 Mon Sep 17 00:00:00 2001 From: aleidk Date: Thu, 13 Feb 2025 15:45:06 -0300 Subject: [PATCH] feat: add error handling --- Cargo.lock | 21 +++++++++++++++++++++ Cargo.toml | 1 + src/error.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ src/main.rs | 22 +++++++++++++--------- 5 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 src/error.rs create mode 100644 src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 81af35d..5f54971 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,6 +118,7 @@ dependencies = [ "minijinja", "notify", "serde", + "thiserror", "tokio", "tower-livereload", ] @@ -594,6 +595,26 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio" version = "1.43.0" diff --git a/Cargo.toml b/Cargo.toml index ce91065..c3e0b36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,6 @@ axum = "0.8.1" minijinja = "2.7.0" notify = "8.0.0" serde = "1.0.217" +thiserror = "2.0.11" tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] } tower-livereload = "0.9.6" diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..d4fc4fb --- /dev/null +++ b/src/error.rs @@ -0,0 +1,39 @@ +use axum::response::Html; +use axum::{http::StatusCode, response::IntoResponse}; + +pub type Result = std::result::Result; + +pub type ResultTemplate = std::result::Result, Error>; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Unhandled error: {0}")] + Generic(String), + + #[error("Unhandled error: {0}")] + Static(&'static str), + + #[error(transparent)] + IO(#[from] std::io::Error), + + #[error(transparent)] + Template(#[from] minijinja::Error), + + #[error("Error in runtime execution: {0}")] + Runtime(&'static str), + // #[error(transparent)] + // DatabaseOperation(#[from] sqlx::Error), +} + +impl IntoResponse for Error { + fn into_response(self) -> axum::response::Response { + let (status, message) = match self { + _ => ( + StatusCode::INTERNAL_SERVER_ERROR, + "An unexpected error has ocurred!", + ), + }; + + (status, message).into_response() + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..4163390 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +mod error; + +pub use error::{Error, Result, ResultTemplate}; diff --git a/src/main.rs b/src/main.rs index 6835694..d169df6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +#![allow(unused)] +#![allow(dead_code)] + use std::sync::Arc; use axum::extract::State; @@ -5,6 +8,7 @@ use axum::http::StatusCode; use axum::response::Html; use axum::routing::get; use axum::Router; +use compendium::{Result, ResultTemplate}; use minijinja::{context, Environment}; struct AppState { @@ -12,11 +16,9 @@ struct AppState { } #[tokio::main] -async fn main() { +async fn main() -> Result<()> { let mut tmpl_env = Environment::new(); - tmpl_env - .add_template("base", include_str!("../templates/base.html")) - .unwrap(); + tmpl_env.add_template("base", include_str!("../templates/base.html"))?; let app_state = Arc::new(AppState { tmpl_env }); @@ -28,14 +30,16 @@ async fn main() { #[cfg(debug_assertions)] let app = app.layer(tower_livereload::LiveReloadLayer::new()); - let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); - axum::serve(listener, app).await.unwrap(); + let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?; + axum::serve(listener, app).await?; + + Ok(()) } -async fn handler_home(State(state): State>) -> Result, StatusCode> { - let template = state.tmpl_env.get_template("base").unwrap(); +async fn handler_home(State(state): State>) -> ResultTemplate { + let template = state.tmpl_env.get_template("base")?; - let content = template.render(context!()).unwrap(); + let content = template.render(context!())?; Ok(Html(content)) }