jae-blog/src/error.rs

94 lines
2.5 KiB
Rust
Raw Normal View History

2024-04-18 04:05:38 +03:00
use std::fmt::Display;
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;
#[derive(Debug)]
#[repr(transparent)]
2024-04-19 16:46:12 +03:00
pub struct FronmaError(fronma::error::Error);
2024-04-18 04:05:38 +03:00
2024-04-19 16:46:12 +03:00
impl std::error::Error for FronmaError {}
2024-04-18 04:05:38 +03:00
2024-04-19 16:46:12 +03:00
impl Display for FronmaError {
2024-04-18 04:05:38 +03:00
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("failed to parse front matter: ")?;
match &self.0 {
fronma::error::Error::MissingBeginningLine => f.write_str("missing beginning line"),
fronma::error::Error::MissingEndingLine => f.write_str("missing ending line"),
2024-04-18 04:12:03 +03:00
fronma::error::Error::SerdeYaml(yaml_error) => write!(f, "{}", yaml_error),
2024-04-18 04:05:38 +03:00
}
}
}
#[derive(Error, Debug)]
#[allow(clippy::enum_variant_names)]
pub enum PostError {
#[error(transparent)]
IoError(#[from] std::io::Error),
#[error(transparent)]
AskamaError(#[from] askama::Error),
#[error(transparent)]
2024-04-19 16:46:12 +03:00
ParseError(#[from] FronmaError),
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-04-19 16:46:12 +03:00
Self::ParseError(FronmaError(value))
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-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 status_code = match &self {
AppError::PostError(err) => match err {
PostError::NotFound(_) => StatusCode::NOT_FOUND,
_ => StatusCode::INTERNAL_SERVER_ERROR,
},
2024-05-02 19:23:20 +03:00
AppError::RssDisabled => StatusCode::FORBIDDEN,
AppError::UrlError(_) => StatusCode::INTERNAL_SERVER_ERROR,
2024-05-01 18:25:01 +03:00
};
(
status_code,
ErrorTemplate {
error: self.to_string(),
},
)
.into_response()
}
}