bingus-blog/src/error.rs

89 lines
2.5 KiB
Rust
Raw Normal View History

2024-05-01 18:25:01 +03:00
use askama_axum::Template;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
2024-04-18 04:05:38 +03:00
use thiserror::Error;
use tracing::error;
2024-04-18 04:05:38 +03:00
#[derive(Error, Debug)]
#[allow(clippy::enum_variant_names)]
pub enum PostError {
#[error("io error: {0}")]
2024-04-18 04:05:38 +03:00
IoError(#[from] std::io::Error),
#[error("failed to parse post metadata: {0}")]
2024-12-16 01:49:04 +03:00
ParseError(String),
#[error("failed to render post: {0}")]
2024-12-16 01:49:04 +03:00
RenderError(String),
2024-04-18 04:05:38 +03:00
#[error("post {0:?} not found")]
NotFound(String),
}
impl From<fronma::error::Error> for PostError {
fn from(value: fronma::error::Error) -> Self {
2024-12-16 01:49:04 +03:00
let binding;
Self::ParseError(format!(
"failed to parse front matter: {}",
match value {
fronma::error::Error::MissingBeginningLine => "missing beginning line",
fronma::error::Error::MissingEndingLine => "missing ending line",
fronma::error::Error::SerdeYaml(yaml_error) => {
binding = yaml_error.to_string();
&binding
}
}
))
}
}
impl From<serde_json::Error> for PostError {
fn from(value: serde_json::Error) -> Self {
Self::ParseError(value.to_string())
2024-04-18 04:05:38 +03:00
}
}
impl IntoResponse for PostError {
fn into_response(self) -> axum::response::Response {
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response()
}
}
2024-05-01 18:25:01 +03:00
pub type AppResult<T> = Result<T, AppError>;
#[derive(Error, Debug)]
pub enum AppError {
#[error("failed to fetch post: {0}")]
PostError(#[from] PostError),
2024-08-13 15:53:18 +03:00
#[error(transparent)]
HandlebarsError(#[from] handlebars::RenderError),
2024-05-02 19:23:20 +03:00
#[error("rss is disabled")]
RssDisabled,
#[error(transparent)]
UrlError(#[from] url::ParseError),
2024-05-01 18:25:01 +03:00
}
impl From<std::io::Error> for AppError {
#[inline(always)]
fn from(value: std::io::Error) -> Self {
Self::PostError(PostError::IoError(value))
}
}
#[derive(Template)]
#[template(path = "error.html")]
struct ErrorTemplate {
error: String,
}
impl IntoResponse for AppError {
fn into_response(self) -> Response {
let error = self.to_string();
error!("error while handling request: {error}");
2024-05-01 18:25:01 +03:00
let status_code = match &self {
2024-08-13 15:53:18 +03:00
AppError::PostError(PostError::NotFound(_)) => StatusCode::NOT_FOUND,
2024-05-02 19:23:20 +03:00
AppError::RssDisabled => StatusCode::FORBIDDEN,
2024-08-13 15:53:18 +03:00
_ => StatusCode::INTERNAL_SERVER_ERROR,
2024-05-01 18:25:01 +03:00
};
(status_code, ErrorTemplate { error }).into_response()
2024-05-01 18:25:01 +03:00
}
}