Parent [>]
1//! Application error types and HTTP response rendering.
2//!
3//! Defines the unified [`Error`] enum used across all handlers and the
4//! [`Result`] type alias.  `Error` implements [`IntoResponse`] via askama's
5//! `error.html` template.
6
7use askama::Template;
8use axum::http::{StatusCode, header};
9use axum::response::{IntoResponse, Response};
10use thiserror::Error;
11
12/// Unified error type for the application.
13///
14/// Each variant maps to an HTTP status code and a rendered error page.
15#[derive(Debug, Error)]
16pub enum Error {
17    #[error(transparent)]
18    Io(#[from] std::io::Error),
19    #[error("repository not found: {0}")]
20    RepoNotFound(String),
21    #[error("not found: {0}")]
22    NotFound(String),
23    #[error("bad request: {0}")]
24    BadRequest(String),
25    #[error("corrupt object: {0}")]
26    GitCorrupt(String),
27}
28
29/// Convenience alias for `std::result::Result<T, Error>`.
30pub type Result<T> = std::result::Result<T, Error>;
31
32#[derive(Template)]
33#[template(path = "error.html")]
34struct ErrorTemplate {
35    status: u16,
36    kind: &'static str,
37    message: String,
38    base_url: String,
39}
40
41impl IntoResponse for Error {
42    fn into_response(self) -> Response {
43        let (status, kind) = match &self {
44            Self::RepoNotFound(_) | Self::NotFound(_) => (StatusCode::NOT_FOUND, "Not Found"),
45            Self::BadRequest(_) => (StatusCode::BAD_REQUEST, "Bad Request"),
46            Self::Io(_) | Self::GitCorrupt(_) => {
47                (StatusCode::INTERNAL_SERVER_ERROR, "Internal Server Error")
48            }
49        };
50
51        let tpl = ErrorTemplate {
52            status: status.as_u16(),
53            kind,
54            message: self.to_string(),
55            base_url: crate::base_url().to_string(),
56        };
57
58        tpl.render().map_or_else(
59            |_| (status, self.to_string()).into_response(),
60            |html| ([(header::CONTENT_TYPE, "text/html; charset=utf-8")], html).into_response(),
61        )
62    }
63}