Parent
[>]
1use askama::Template; 2use axum::http::{StatusCode, header}; 3use axum::response::{IntoResponse, Response}; 4use thiserror::Error; 5 6#[derive(Debug, Error)] 7pub enum Error { 8 #[error(transparent)] 9 Io(#[from] std::io::Error), 10 #[error("repository not found: {0}")] 11 RepoNotFound(String), 12 #[error("not found: {0}")] 13 NotFound(String), 14 #[error("bad request: {0}")] 15 BadRequest(String), 16 #[error("corrupt object: {0}")] 17 GitCorrupt(String), 18} 19 20pub type Result<T> = std::result::Result<T, Error>; 21 22#[derive(Template)] 23#[template(path = "error.html")] 24struct ErrorTemplate { 25 status: u16, 26 kind: &'static str, 27 message: String, 28 base_url: String, 29} 30 31impl IntoResponse for Error { 32 fn into_response(self) -> Response { 33 let (status, kind) = match &self { 34 Error::RepoNotFound(_) | Error::NotFound(_) => (StatusCode::NOT_FOUND, "Not Found"), 35 Error::BadRequest(_) => (StatusCode::BAD_REQUEST, "Bad Request"), 36 Error::Io(_) | Error::GitCorrupt(_) => { 37 (StatusCode::INTERNAL_SERVER_ERROR, "Internal Server Error") 38 } 39 }; 40 41 let tpl = ErrorTemplate { 42 status: status.as_u16(), 43 kind, 44 message: self.to_string(), 45 base_url: crate::base_url().to_string(), 46 }; 47 48 match tpl.render() { 49 Ok(html) => ([(header::CONTENT_TYPE, "text/html; charset=utf-8")], html).into_response(), 50 Err(_) => (status, self.to_string()).into_response(), 51 } 52 } 53}