Skip to main content

agentlink_core/
error.rs

1//! SDK Error Types
2
3use thiserror::Error;
4
5/// SDK 错误类型
6#[derive(Error, Debug, Clone)]
7pub enum SdkError {
8    /// HTTP 请求错误
9    #[error("HTTP error: {0}")]
10    Http(String),
11
12    /// MQTT 错误
13    #[error("MQTT error: {0}")]
14    Mqtt(String),
15
16    /// 序列化/反序列化错误
17    #[error("Serialization error: {0}")]
18    Serialization(String),
19
20    /// 认证错误
21    #[error("Authentication error: {0}")]
22    Auth(String),
23
24    /// 网络错误
25    #[error("Network error: {0}")]
26    Network(String),
27
28    /// 配置错误
29    #[error("Configuration error: {0}")]
30    Config(String),
31
32    /// 未连接
33    #[error("Not connected")]
34    NotConnected,
35
36    /// 超时
37    #[error("Timeout")]
38    Timeout,
39
40    /// 其他错误
41    #[error("Other error: {0}")]
42    Other(String),
43}
44
45/// SDK 结果类型
46pub type SdkResult<T> = Result<T, SdkError>;
47
48
49
50impl From<serde_json::Error> for SdkError {
51    fn from(err: serde_json::Error) -> Self {
52        SdkError::Serialization(err.to_string())
53    }
54}
55
56impl From<std::io::Error> for SdkError {
57    fn from(err: std::io::Error) -> Self {
58        SdkError::Network(err.to_string())
59    }
60}
61
62/// HTTP 错误类型
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum HttpErrorType {
65    /// 未授权 (401)
66    Unauthorized,
67    /// 禁止访问 (403)
68    Forbidden,
69    /// 未找到 (404)
70    NotFound,
71    /// 请求错误 (400)
72    BadRequest,
73    /// 服务器错误 (5xx)
74    ServerError,
75    /// 网络错误
76    NetworkError,
77    /// 其他错误
78    Other,
79}
80
81/// 结构化的 HTTP 错误
82#[derive(Debug, Clone)]
83pub struct HttpError {
84    /// 错误类型
85    pub error_type: HttpErrorType,
86    /// HTTP 状态码
87    pub status_code: u16,
88    /// 错误消息
89    pub message: String,
90    /// 是否需要重新登录
91    pub requires_relogin: bool,
92}
93
94impl HttpError {
95    /// 从错误字符串解析
96    pub fn from_error(error: &str, default_message: &str) -> Self {
97        // 优先检查服务端返回的结构化错误(格式: "CODE: Message")
98        if let Some(colon_pos) = error.find(':') {
99            let code = &error[..colon_pos];
100            let message = error[colon_pos + 1..].trim();
101
102            // 只处理全大写的错误码
103            if code.chars().all(|c| c.is_ascii_uppercase() || c == '_') {
104                match code {
105                    "USER_NOT_FOUND" | "USER_DELETED" => {
106                        return Self {
107                            error_type: HttpErrorType::NotFound,
108                            status_code: 404,
109                            message: message.to_string(),
110                            requires_relogin: true,
111                        };
112                    }
113                    "INVALID_TOKEN" | "TOKEN_EXPIRED" => {
114                        return Self {
115                            error_type: HttpErrorType::Unauthorized,
116                            status_code: 401,
117                            message: message.to_string(),
118                            requires_relogin: true,
119                        };
120                    }
121                    "UNAUTHORIZED" | "AUTH_FAILED" => {
122                        return Self {
123                            error_type: HttpErrorType::Unauthorized,
124                            status_code: 401,
125                            message: message.to_string(),
126                            requires_relogin: true,
127                        };
128                    }
129                    "FORBIDDEN" => {
130                        return Self {
131                            error_type: HttpErrorType::Forbidden,
132                            status_code: 403,
133                            message: message.to_string(),
134                            requires_relogin: false,
135                        };
136                    }
137                    _ => {}
138                }
139            }
140        }
141
142        // 回退:尝试从错误消息中提取状态码和关键词
143        if error.contains("HTTP 错误: 401") || error.contains("HTTP 401") {
144            Self {
145                error_type: HttpErrorType::Unauthorized,
146                status_code: 401,
147                message: "登录已过期,请重新登录".to_string(),
148                requires_relogin: true,
149            }
150        } else if error.contains("HTTP 错误: 403") || error.contains("HTTP 403") {
151            Self {
152                error_type: HttpErrorType::Forbidden,
153                status_code: 403,
154                message: "无权限访问此资源".to_string(),
155                requires_relogin: false,
156            }
157        } else if error.contains("HTTP 错误: 404") || error.contains("HTTP 404") {
158            Self {
159                error_type: HttpErrorType::NotFound,
160                status_code: 404,
161                message: "资源不存在".to_string(),
162                requires_relogin: false,
163            }
164        } else if error.contains("HTTP 错误: 400") || error.contains("HTTP 400") {
165            Self {
166                error_type: HttpErrorType::BadRequest,
167                status_code: 400,
168                message: "请求参数错误".to_string(),
169                requires_relogin: false,
170            }
171        } else if error.contains("HTTP 错误: 5") || error.contains("HTTP 50") {
172            Self {
173                error_type: HttpErrorType::ServerError,
174                status_code: 500,
175                message: "服务器错误,请稍后重试".to_string(),
176                requires_relogin: false,
177            }
178        } else {
179            Self {
180                error_type: HttpErrorType::Other,
181                status_code: 0,
182                message: if default_message.is_empty() {
183                    error.to_string()
184                } else {
185                    format!("{}: {}", default_message, error)
186                },
187                requires_relogin: false,
188            }
189        }
190    }
191}