fedimint_server_ui/
error.rs

1use axum::extract::FromRequest;
2use axum::http::StatusCode;
3use axum::response::{IntoResponse, Response};
4use serde::Serialize;
5use thiserror::Error;
6use tracing::debug;
7
8use crate::LOG_UI;
9
10/// Wrapper over `T` to make it a json request response
11#[derive(FromRequest)]
12#[from_request(via(axum::Json), rejection(RequestError))]
13pub struct AppJson<T>(pub T);
14
15impl<T> IntoResponse for AppJson<T>
16where
17    axum::Json<T>: IntoResponse,
18{
19    fn into_response(self) -> Response {
20        axum::Json(self.0).into_response()
21    }
22}
23
24/// Whatever can go wrong with a request
25#[derive(Debug, Error)]
26pub enum RequestError {
27    #[error("Bad request: {source}")]
28    BadRequest { source: anyhow::Error },
29    #[error("Internal Error")]
30    InternalError,
31}
32pub type RequestResult<T> = std::result::Result<T, RequestError>;
33
34impl IntoResponse for RequestError {
35    fn into_response(self) -> Response {
36        debug!(target: LOG_UI, err=%self, "Request Error");
37
38        let (status_code, message) = match self {
39            Self::BadRequest { source } => {
40                (StatusCode::BAD_REQUEST, format!("Bad Request: {source}"))
41            }
42            _ => (
43                StatusCode::INTERNAL_SERVER_ERROR,
44                "Internal Service Error".to_owned(),
45            ),
46        };
47
48        (status_code, AppJson(UserErrorResponse { message })).into_response()
49    }
50}
51
52// How we want user errors responses to be serialized
53#[derive(Serialize)]
54pub struct UserErrorResponse {
55    pub message: String,
56}