use std::{error, fmt}; use axum::{ http::StatusCode, response::{IntoResponse, Response}, }; use crate::id::Id as BaseId; // I'm making an effort to avoid `anyhow` here, as that crate is _enormously_ // complex (though very usable). We don't need to be overly careful about // allocations on errors in this app, so this is fine for most "general // failure" cases. type BoxedError = Box; // Returns a 500 Internal Server Error to the client. Meant to be used via the // `?` operator; _does not_ return the originating error to the client. pub struct InternalError(Id, BoxedError); impl From for InternalError where E: Into, { fn from(error: E) -> Self { let id = Id::generate(); Self(id, error.into()) } } impl IntoResponse for InternalError { fn into_response(self) -> Response { let Self(id, error) = self; eprintln!("hi: [{id}] {error}"); ( StatusCode::INTERNAL_SERVER_ERROR, format!("internal server error\nerror id: {}", id), ) .into_response() } } /// Transient identifier for an InternalError. Prefixed with `E`. pub struct Id(BaseId); impl From for Id { fn from(id: BaseId) -> Self { Self(id) } } impl Id { pub fn generate() -> Self { BaseId::generate("E") } } impl fmt::Display for Id { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } }