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;
|
2024-12-02 20:07:54 +03:00
|
|
|
use tracing::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),
|
2024-12-16 01:49:04 +03:00
|
|
|
#[error("{0}")]
|
|
|
|
ParseError(String),
|
|
|
|
#[error("{0}")]
|
|
|
|
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 {
|
2024-12-02 20:07:54 +03:00
|
|
|
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
|
|
|
};
|
2024-12-02 20:07:54 +03:00
|
|
|
(status_code, ErrorTemplate { error }).into_response()
|
2024-05-01 18:25:01 +03:00
|
|
|
}
|
|
|
|
}
|