A decentralized event management and credentialing system built on atproto.
1use axum::http::StatusCode;
2use axum::response::IntoResponse;
3use axum::response::Response;
4
5use crate::errors::{AcudoError, EventError, HttpError};
6
7/// Web layer error wrapper for HTTP responses.
8///
9/// This type wraps the standardized HttpError and provides HTTP response conversion.
10/// All errors follow the format: `error-acudo-http-<number> <message>: <details>`
11#[derive(Debug)]
12pub(super) enum WebError {
13 /// HTTP layer error with proper error formatting
14 Http(HttpError),
15
16 /// Fallback for legacy anyhow errors during transition
17 Legacy(anyhow::Error),
18}
19
20impl From<HttpError> for WebError {
21 fn from(err: HttpError) -> Self {
22 WebError::Http(err)
23 }
24}
25
26impl From<AcudoError> for WebError {
27 fn from(err: AcudoError) -> Self {
28 match err {
29 AcudoError::Http(http_err) => WebError::Http(http_err),
30 other => WebError::Legacy(anyhow::Error::from(other)),
31 }
32 }
33}
34
35impl From<EventError> for WebError {
36 fn from(err: EventError) -> Self {
37 WebError::Legacy(anyhow::Error::from(err))
38 }
39}
40
41impl From<anyhow::Error> for WebError {
42 fn from(err: anyhow::Error) -> Self {
43 WebError::Legacy(err)
44 }
45}
46
47/// Implementation of Axum's `IntoResponse` trait for WebError.
48///
49/// This implementation converts errors into appropriate HTTP responses:
50/// - Authentication errors return 401 Unauthorized
51/// - Forbidden errors return 403 Forbidden
52/// - Not found errors return 404 Not Found
53/// - Validation errors return 400 Bad Request
54/// - All other errors return 500 Internal Server Error
55impl IntoResponse for WebError {
56 fn into_response(self) -> Response {
57 let (status, error_message) = match &self {
58 WebError::Http(http_err) => match http_err {
59 HttpError::AuthenticationRequired => {
60 (StatusCode::UNAUTHORIZED, http_err.to_string())
61 }
62 HttpError::Forbidden => (StatusCode::FORBIDDEN, http_err.to_string()),
63 HttpError::NotFound => (StatusCode::NOT_FOUND, http_err.to_string()),
64 HttpError::RequestValidation { .. } => {
65 (StatusCode::BAD_REQUEST, http_err.to_string())
66 }
67 HttpError::Unhandled { .. } => {
68 (StatusCode::INTERNAL_SERVER_ERROR, http_err.to_string())
69 }
70 },
71 WebError::Legacy(err) => (
72 StatusCode::INTERNAL_SERVER_ERROR,
73 format!("error-acudo-http-100 Unhandled web error: {}", err),
74 ),
75 };
76
77 tracing::error!(error = ?self, status = ?status, "HTTP error response");
78
79 // Return simple error response for now
80 // In production, you might want to return JSON or a proper error page
81 (status, error_message).into_response()
82 }
83}