Skip to main content

openlark_core/api/
responses.rs

1//! API响应类型定义
2//!
3//! 独立的响应处理系统,替代api_resp模块
4
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8/// 原始响应数据
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct RawResponse {
11    /// 响应代码
12    pub code: i32,
13    /// 响应消息
14    pub msg: String,
15    /// 请求数据ID
16    pub request_id: Option<String>,
17    /// 额外数据
18    pub data: Option<serde_json::Value>,
19    /// 错误信息
20    pub error: Option<ErrorInfo>,
21}
22
23/// 错误信息
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct ErrorInfo {
26    /// 错误代码
27    pub code: i32,
28    /// 错误消息
29    pub message: String,
30    /// 错误详情
31    pub details: Option<HashMap<String, serde_json::Value>>,
32}
33
34impl Default for RawResponse {
35    fn default() -> Self {
36        Self {
37            code: 0,
38            msg: "success".to_string(),
39            request_id: None,
40            data: None,
41            error: None,
42        }
43    }
44}
45
46impl RawResponse {
47    /// 创建成功响应
48    pub fn success() -> Self {
49        Self::default()
50    }
51
52    /// 创建带数据的成功响应
53    pub fn success_with_data(data: serde_json::Value) -> Self {
54        Self {
55            data: Some(data),
56            ..Default::default()
57        }
58    }
59
60    /// 创建错误响应
61    pub fn error(code: i32, msg: impl Into<String> + Clone) -> Self {
62        let msg_str = msg.into();
63        Self {
64            code,
65            msg: msg_str.clone(),
66            error: Some(ErrorInfo {
67                code,
68                message: msg_str,
69                details: None,
70            }),
71            ..Default::default()
72        }
73    }
74
75    /// 检查是否成功
76    pub fn is_success(&self) -> bool {
77        self.code == 0
78    }
79
80    /// 获取错误信息
81    pub fn get_error(&self) -> Option<&ErrorInfo> {
82        self.error.as_ref()
83    }
84}
85
86/// 响应格式枚举
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
88pub enum ResponseFormat {
89    /// 标准数据格式
90    #[serde(rename = "data")]
91    Data,
92    /// 扁平格式
93    #[serde(rename = "flatten")]
94    Flatten,
95    /// 二进制数据
96    #[serde(rename = "binary")]
97    Binary,
98    /// 文本数据
99    #[serde(rename = "text")]
100    Text,
101    /// 自定义格式
102    #[serde(rename = "custom")]
103    Custom,
104}
105
106/// API响应特征
107pub trait ApiResponseTrait: Send + Sync + 'static {
108    /// 获取响应数据格式
109    fn data_format() -> ResponseFormat {
110        ResponseFormat::Data
111    }
112}
113
114/// 通用响应结构
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct Response<T> {
117    /// 响应数据
118    pub data: Option<T>,
119    /// 原始响应
120    pub raw_response: RawResponse,
121}
122
123impl<T> Response<T> {
124    /// 创建新响应
125    pub fn new(data: Option<T>, raw_response: RawResponse) -> Self {
126        Self { data, raw_response }
127    }
128
129    /// 创建成功响应
130    pub fn success(data: T) -> Self {
131        Self {
132            data: Some(data),
133            raw_response: RawResponse::success(),
134        }
135    }
136
137    /// 创建空成功响应
138    pub fn success_empty() -> Self {
139        Self {
140            data: None,
141            raw_response: RawResponse::success(),
142        }
143    }
144
145    /// 创建错误响应
146    pub fn error(code: i32, msg: impl Into<String> + Clone) -> Self {
147        Self {
148            data: None,
149            raw_response: RawResponse::error(code, msg),
150        }
151    }
152
153    /// 检查是否成功
154    pub fn is_success(&self) -> bool {
155        self.raw_response.is_success()
156    }
157
158    /// 获取响应代码
159    pub fn code(&self) -> i32 {
160        self.raw_response.code
161    }
162
163    /// 获取响应消息
164    pub fn message(&self) -> &str {
165        &self.raw_response.msg
166    }
167
168    /// 获取响应消息(兼容方法)
169    pub fn msg(&self) -> &str {
170        &self.raw_response.msg
171    }
172
173    /// 获取数据
174    pub fn data(&self) -> Option<&T> {
175        self.data.as_ref()
176    }
177
178    /// 获取原始响应
179    pub fn raw(&self) -> &RawResponse {
180        &self.raw_response
181    }
182
183    /// 转换为结果类型
184    pub fn into_result(self) -> Result<T, crate::error::CoreError> {
185        let is_success = self.is_success();
186        let code = self.raw_response.code;
187        let request_id = self.raw_response.request_id.clone();
188
189        if is_success {
190            match self.data {
191                Some(data) => Ok(data),
192                None => Err(crate::error::api_error(
193                    code as u16,
194                    "response",
195                    "响应数据为空",
196                    request_id,
197                )),
198            }
199        } else {
200            Err(crate::error::api_error(
201                code as u16,
202                "response",
203                self.raw_response.msg.clone(),
204                request_id,
205            ))
206        }
207    }
208}
209
210// 为常见类型实现ApiResponseTrait
211impl ApiResponseTrait for serde_json::Value {}
212impl ApiResponseTrait for String {}
213impl ApiResponseTrait for Vec<u8> {
214    fn data_format() -> ResponseFormat {
215        ResponseFormat::Binary
216    }
217}
218impl ApiResponseTrait for () {}
219
220// 类型别名,用于向后兼容
221/// 基础响应类型别名
222pub type BaseResponse<T> = Response<T>;
223
224#[cfg(test)]
225mod tests {
226    use super::*;
227
228    #[test]
229    fn test_raw_response_default() {
230        let response = RawResponse::default();
231        assert_eq!(response.code, 0);
232        assert_eq!(response.msg, "success");
233        assert!(response.request_id.is_none());
234        assert!(response.data.is_none());
235        assert!(response.error.is_none());
236    }
237
238    #[test]
239    fn test_raw_response_success() {
240        let response = RawResponse::success();
241        assert!(response.is_success());
242    }
243
244    #[test]
245    fn test_raw_response_success_with_data() {
246        let data = serde_json::json!({"key": "value"});
247        let response = RawResponse::success_with_data(data.clone());
248        assert!(response.is_success());
249        assert_eq!(response.data, Some(data));
250    }
251
252    #[test]
253    fn test_raw_response_error() {
254        let response = RawResponse::error(400, "Bad Request");
255        assert!(!response.is_success());
256        assert_eq!(response.code, 400);
257        assert!(response.error.is_some());
258    }
259
260    #[test]
261    fn test_raw_response_get_error() {
262        let response = RawResponse::error(404, "Not Found");
263        let error = response.get_error();
264        assert!(error.is_some());
265        assert_eq!(error.unwrap().code, 404);
266    }
267
268    #[test]
269    fn test_raw_response_serialization() {
270        let response = RawResponse::success_with_data(serde_json::json!({"test": 123}));
271        let json = serde_json::to_string(&response).unwrap();
272        let parsed: RawResponse = serde_json::from_str(&json).unwrap();
273        assert!(parsed.is_success());
274    }
275
276    #[test]
277    fn test_error_info_creation() {
278        let error = ErrorInfo {
279            code: 500,
280            message: "Internal Error".to_string(),
281            details: None,
282        };
283        assert_eq!(error.code, 500);
284        assert_eq!(error.message, "Internal Error");
285    }
286
287    #[test]
288    fn test_response_format() {
289        assert_eq!(ResponseFormat::Data, ResponseFormat::Data);
290        assert_ne!(ResponseFormat::Data, ResponseFormat::Flatten);
291    }
292
293    #[test]
294    fn test_response_format_binary() {
295        assert_eq!(<Vec<u8>>::data_format(), ResponseFormat::Binary);
296    }
297
298    #[test]
299    fn test_response_format_default() {
300        assert_eq!(<()>::data_format(), ResponseFormat::Data);
301    }
302
303    #[test]
304    fn test_response_deserialize_requires_raw_response() {
305        let payload = r#"{"code":400,"msg":"Bad Request"}"#;
306        let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload);
307        assert!(parsed.is_err());
308    }
309
310    #[test]
311    fn test_response_deserialize_with_raw_response_error_keeps_code_and_msg() {
312        let payload = r#"{"raw_response":{"code":400,"msg":"Bad Request","request_id":null,"data":null,"error":null},"data":null}"#;
313        let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload).unwrap();
314        assert_eq!(parsed.raw_response.code, 400);
315        assert_eq!(parsed.raw_response.msg, "Bad Request");
316        assert!(!parsed.is_success());
317    }
318}