mcp_runner/sse_proxy/
actix_error.rs

1//! Actix Web error adapters for MCP Runner errors.
2//!
3//! This module provides implementations of Actix Web error traits
4//! for the MCP Runner error types, allowing them to be used in Actix Web handlers.
5
6use crate::error::Error;
7use actix_web::{HttpResponse, ResponseError, http::StatusCode};
8use serde_json::json;
9
10// Implement ResponseError for our Error type
11impl ResponseError for Error {
12    fn error_response(&self) -> HttpResponse {
13        let status_code = match self {
14            Error::Unauthorized(_) => StatusCode::UNAUTHORIZED,
15            Error::ServerNotFound(_) => StatusCode::NOT_FOUND,
16            Error::ToolNotFound(_) => StatusCode::NOT_FOUND,
17            Error::ResourceNotFound(_) => StatusCode::NOT_FOUND,
18            Error::ConfigInvalid(_) => StatusCode::BAD_REQUEST,
19            Error::ConfigParse(_) => StatusCode::BAD_REQUEST,
20            Error::ConfigValidation(_) => StatusCode::BAD_REQUEST,
21            _ => StatusCode::INTERNAL_SERVER_ERROR,
22        };
23
24        HttpResponse::build(status_code)
25            .content_type("application/json")
26            .json(json!({
27                "error": self.to_string(),
28                "code": status_code.as_u16()
29            }))
30    }
31
32    fn status_code(&self) -> StatusCode {
33        match self {
34            Error::Unauthorized(_) => StatusCode::UNAUTHORIZED,
35            Error::ServerNotFound(_) => StatusCode::NOT_FOUND,
36            Error::ToolNotFound(_) => StatusCode::NOT_FOUND,
37            Error::ResourceNotFound(_) => StatusCode::NOT_FOUND,
38            Error::ConfigInvalid(_) => StatusCode::BAD_REQUEST,
39            Error::ConfigParse(_) => StatusCode::BAD_REQUEST,
40            Error::ConfigValidation(_) => StatusCode::BAD_REQUEST,
41            _ => StatusCode::INTERNAL_SERVER_ERROR,
42        }
43    }
44}
45
46// Create a wrapper error type for request validation errors
47#[derive(Debug, thiserror::Error)]
48pub enum ApiError {
49    #[error("Invalid request: {0}")]
50    InvalidRequest(String),
51
52    #[error("Unsupported operation: {0}")]
53    UnsupportedOperation(String),
54
55    #[error("Internal server error: {0}")]
56    Internal(#[from] Error),
57}
58
59impl ResponseError for ApiError {
60    fn error_response(&self) -> HttpResponse {
61        let status_code = match self {
62            ApiError::InvalidRequest(_) => StatusCode::BAD_REQUEST,
63            ApiError::UnsupportedOperation(_) => StatusCode::NOT_IMPLEMENTED,
64            ApiError::Internal(e) => e.status_code(),
65        };
66
67        HttpResponse::build(status_code)
68            .content_type("application/json")
69            .json(json!({
70                "error": self.to_string(),
71                "code": status_code.as_u16()
72            }))
73    }
74
75    fn status_code(&self) -> StatusCode {
76        match self {
77            ApiError::InvalidRequest(_) => StatusCode::BAD_REQUEST,
78            ApiError::UnsupportedOperation(_) => StatusCode::NOT_IMPLEMENTED,
79            ApiError::Internal(e) => e.status_code(),
80        }
81    }
82}