73 lines
2.0 KiB
Rust
73 lines
2.0 KiB
Rust
use actix_web::body::BoxBody;
|
|
use actix_web::dev::ServiceResponse;
|
|
use actix_web::http::header::ContentType;
|
|
use actix_web::http::StatusCode;
|
|
use actix_web::middleware::ErrorHandlerResponse;
|
|
use actix_web::{web, HttpResponse, ResponseError};
|
|
use derive_more::{Display, Error};
|
|
|
|
use super::SharedData;
|
|
use crate::template_utils::{render_template, ErrorMessage, TemplateArgs};
|
|
|
|
#[derive(Debug, Display, Error)]
|
|
pub enum UserError {
|
|
NotFound,
|
|
#[display(fmt = "Internal error. Try again later.")]
|
|
InternalError,
|
|
}
|
|
|
|
impl ResponseError for UserError {
|
|
fn error_response(&self) -> HttpResponse {
|
|
HttpResponse::build(self.status_code())
|
|
.insert_header(ContentType::html())
|
|
.body(self.to_string())
|
|
}
|
|
|
|
fn status_code(&self) -> StatusCode {
|
|
match *self {
|
|
UserError::NotFound => StatusCode::NOT_FOUND,
|
|
UserError::InternalError => StatusCode::INTERNAL_SERVER_ERROR,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn generic_error<B>(
|
|
res: ServiceResponse<B>,
|
|
) -> actix_web::Result<ErrorHandlerResponse<BoxBody>> {
|
|
let data = res
|
|
.request()
|
|
.app_data::<web::Data<SharedData>>()
|
|
.map(|t| t.get_ref());
|
|
|
|
let status_code = res.response().status();
|
|
let message = if let Some(error) = status_code.canonical_reason() {
|
|
error
|
|
} else {
|
|
""
|
|
};
|
|
|
|
let response = match data {
|
|
Some(SharedData {
|
|
handlebars,
|
|
config: _,
|
|
}) => {
|
|
let args = TemplateArgs::builder()
|
|
.error_page(ErrorMessage::new(message, status_code.as_u16()))
|
|
.build();
|
|
|
|
let body = render_template(handlebars, "error", &args)
|
|
.map_err(|_| UserError::InternalError)?;
|
|
|
|
HttpResponse::build(res.status())
|
|
.content_type(ContentType::html())
|
|
.body(body)
|
|
}
|
|
None => Err(UserError::InternalError)?,
|
|
};
|
|
|
|
Ok(ErrorHandlerResponse::Response(ServiceResponse::new(
|
|
res.into_parts().0,
|
|
response.map_into_left_body(),
|
|
)))
|
|
}
|