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    fn data_format() -> ResponseFormat {
109        ResponseFormat::Data
110    }
111}
112
113/// 通用响应结构
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct Response<T> {
116    /// 响应数据
117    pub data: Option<T>,
118    /// 原始响应
119    pub raw_response: RawResponse,
120}
121
122impl<T> Response<T> {
123    /// 创建新响应
124    pub fn new(data: Option<T>, raw_response: RawResponse) -> Self {
125        Self { data, raw_response }
126    }
127
128    /// 创建成功响应
129    pub fn success(data: T) -> Self {
130        Self {
131            data: Some(data),
132            raw_response: RawResponse::success(),
133        }
134    }
135
136    /// 创建空成功响应
137    pub fn success_empty() -> Self {
138        Self {
139            data: None,
140            raw_response: RawResponse::success(),
141        }
142    }
143
144    /// 创建错误响应
145    pub fn error(code: i32, msg: impl Into<String> + Clone) -> Self {
146        Self {
147            data: None,
148            raw_response: RawResponse::error(code, msg),
149        }
150    }
151
152    /// 检查是否成功
153    pub fn is_success(&self) -> bool {
154        self.raw_response.is_success()
155    }
156
157    /// 获取响应代码
158    pub fn code(&self) -> i32 {
159        self.raw_response.code
160    }
161
162    /// 获取响应消息
163    pub fn message(&self) -> &str {
164        &self.raw_response.msg
165    }
166
167    /// 获取响应消息(兼容方法)
168    pub fn msg(&self) -> &str {
169        &self.raw_response.msg
170    }
171
172    /// 获取数据
173    pub fn data(&self) -> Option<&T> {
174        self.data.as_ref()
175    }
176
177    /// 获取原始响应
178    pub fn raw(&self) -> &RawResponse {
179        &self.raw_response
180    }
181
182    /// 转换为结果类型
183    pub fn into_result(self) -> Result<T, crate::error::CoreError> {
184        let is_success = self.is_success();
185        let code = self.raw_response.code;
186        let request_id = self.raw_response.request_id.clone();
187
188        if is_success {
189            match self.data {
190                Some(data) => Ok(data),
191                None => Err(crate::error::api_error(
192                    code as u16,
193                    "response",
194                    "响应数据为空",
195                    request_id,
196                )),
197            }
198        } else {
199            Err(crate::error::api_error(
200                code as u16,
201                "response",
202                self.raw_response.msg.clone(),
203                request_id,
204            ))
205        }
206    }
207}
208
209// 为常见类型实现ApiResponseTrait
210impl ApiResponseTrait for serde_json::Value {}
211impl ApiResponseTrait for String {}
212impl ApiResponseTrait for Vec<u8> {
213    fn data_format() -> ResponseFormat {
214        ResponseFormat::Binary
215    }
216}
217impl ApiResponseTrait for () {}
218
219// 类型别名,用于向后兼容
220pub type BaseResponse<T> = Response<T>;
221
222#[cfg(test)]
223mod tests {
224    use super::*;
225
226    #[test]
227    fn test_raw_response_default() {
228        let response = RawResponse::default();
229        assert_eq!(response.code, 0);
230        assert_eq!(response.msg, "success");
231        assert!(response.request_id.is_none());
232        assert!(response.data.is_none());
233        assert!(response.error.is_none());
234    }
235
236    #[test]
237    fn test_raw_response_success() {
238        let response = RawResponse::success();
239        assert!(response.is_success());
240    }
241
242    #[test]
243    fn test_raw_response_success_with_data() {
244        let data = serde_json::json!({"key": "value"});
245        let response = RawResponse::success_with_data(data.clone());
246        assert!(response.is_success());
247        assert_eq!(response.data, Some(data));
248    }
249
250    #[test]
251    fn test_raw_response_error() {
252        let response = RawResponse::error(400, "Bad Request");
253        assert!(!response.is_success());
254        assert_eq!(response.code, 400);
255        assert!(response.error.is_some());
256    }
257
258    #[test]
259    fn test_raw_response_get_error() {
260        let response = RawResponse::error(404, "Not Found");
261        let error = response.get_error();
262        assert!(error.is_some());
263        assert_eq!(error.unwrap().code, 404);
264    }
265
266    #[test]
267    fn test_raw_response_serialization() {
268        let response = RawResponse::success_with_data(serde_json::json!({"test": 123}));
269        let json = serde_json::to_string(&response).unwrap();
270        let parsed: RawResponse = serde_json::from_str(&json).unwrap();
271        assert!(parsed.is_success());
272    }
273
274    #[test]
275    fn test_error_info_creation() {
276        let error = ErrorInfo {
277            code: 500,
278            message: "Internal Error".to_string(),
279            details: None,
280        };
281        assert_eq!(error.code, 500);
282        assert_eq!(error.message, "Internal Error");
283    }
284
285    #[test]
286    fn test_response_format() {
287        assert_eq!(ResponseFormat::Data, ResponseFormat::Data);
288        assert_ne!(ResponseFormat::Data, ResponseFormat::Flatten);
289    }
290
291    #[test]
292    fn test_response_format_binary() {
293        assert_eq!(<Vec<u8>>::data_format(), ResponseFormat::Binary);
294    }
295
296    #[test]
297    fn test_response_format_default() {
298        assert_eq!(<()>::data_format(), ResponseFormat::Data);
299    }
300
301    #[test]
302    fn test_response_deserialize_requires_raw_response() {
303        let payload = r#"{"code":400,"msg":"Bad Request"}"#;
304        let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload);
305        assert!(parsed.is_err());
306    }
307
308    #[test]
309    fn test_response_deserialize_with_raw_response_error_keeps_code_and_msg() {
310        let payload = r#"{"raw_response":{"code":400,"msg":"Bad Request","request_id":null,"data":null,"error":null},"data":null}"#;
311        let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload).unwrap();
312        assert_eq!(parsed.raw_response.code, 400);
313        assert_eq!(parsed.raw_response.msg, "Bad Request");
314        assert!(!parsed.is_success());
315    }
316}