Skip to main content

openlark_core/
req_option.rs

1use std::collections::HashMap;
2
3#[derive(Debug, Clone, Default)]
4pub struct RequestOption {
5    pub(crate) tenant_key: Option<String>,
6    pub(crate) user_access_token: Option<String>,
7    pub(crate) app_access_token: Option<String>,
8    pub(crate) tenant_access_token: Option<String>,
9    pub(crate) need_helpdesk_auth: bool,
10    pub(crate) request_id: Option<String>,
11    pub(crate) app_ticket: Option<String>,
12    pub(crate) file_upload: bool,
13    pub(crate) file_download: bool,
14    pub(crate) header: HashMap<String, String>,
15}
16
17impl RequestOption {
18    pub fn builder() -> RequestOptionBuilder {
19        RequestOptionBuilder::default()
20    }
21}
22
23#[derive(Default)]
24pub struct RequestOptionBuilder {
25    option: RequestOption,
26}
27
28impl RequestOptionBuilder {
29    pub fn tenant_key(mut self, tenant_key: impl ToString) -> Self {
30        self.option.tenant_key = Some(tenant_key.to_string());
31        self
32    }
33
34    pub fn user_access_token(mut self, user_access_token: impl ToString) -> Self {
35        self.option.user_access_token = Some(user_access_token.to_string());
36        self
37    }
38
39    pub fn app_access_token(mut self, app_access_token: impl ToString) -> Self {
40        self.option.app_access_token = Some(app_access_token.to_string());
41        self
42    }
43
44    pub fn tenant_access_token(mut self, tenant_access_token: impl ToString) -> Self {
45        self.option.tenant_access_token = Some(tenant_access_token.to_string());
46        self
47    }
48
49    pub fn need_helpdesk_auth(mut self, need_helpdesk_auth: bool) -> Self {
50        self.option.need_helpdesk_auth = need_helpdesk_auth;
51        self
52    }
53
54    pub fn request_id(mut self, request_id: impl ToString) -> Self {
55        self.option.request_id = Some(request_id.to_string());
56        self
57    }
58
59    pub fn app_ticket(mut self, app_ticket: impl ToString) -> Self {
60        self.option.app_ticket = Some(app_ticket.to_string());
61        self
62    }
63
64    pub fn file_upload(mut self, file_upload: bool) -> Self {
65        self.option.file_upload = file_upload;
66        self
67    }
68
69    pub fn file_download(mut self, file_download: bool) -> Self {
70        self.option.file_download = file_download;
71        self
72    }
73
74    pub fn header(mut self, header: HashMap<String, String>) -> Self {
75        self.option.header = header;
76        self
77    }
78
79    /// 添加请求头
80    pub fn add_header(mut self, key: impl ToString, value: impl ToString) -> Self {
81        self.option
82            .header
83            .insert(key.to_string(), value.to_string());
84        self
85    }
86
87    pub fn build(self) -> RequestOption {
88        self.option
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use std::collections::HashMap;
96
97    #[test]
98    fn test_request_option_default() {
99        let option = RequestOption::default();
100        assert_eq!(option.tenant_key, None);
101        assert_eq!(option.user_access_token, None);
102        assert_eq!(option.app_access_token, None);
103        assert_eq!(option.tenant_access_token, None);
104        assert!(!option.need_helpdesk_auth);
105        assert_eq!(option.request_id, None);
106        assert_eq!(option.app_ticket, None);
107        assert!(!option.file_upload);
108        assert!(!option.file_download);
109        assert!(option.header.is_empty());
110    }
111
112    #[test]
113    fn test_request_option_builder_creation() {
114        let builder = RequestOption::builder();
115        let option = builder.build();
116
117        // Should be same as default
118        assert_eq!(option.tenant_key, None);
119        assert_eq!(option.user_access_token, None);
120        assert_eq!(option.app_access_token, None);
121        assert_eq!(option.tenant_access_token, None);
122        assert!(!option.need_helpdesk_auth);
123        assert_eq!(option.request_id, None);
124        assert_eq!(option.app_ticket, None);
125        assert!(!option.file_upload);
126        assert!(!option.file_download);
127        assert!(option.header.is_empty());
128    }
129
130    #[test]
131    fn test_request_option_builder_tenant_key() {
132        let option = RequestOption::builder().tenant_key("test_tenant").build();
133
134        assert_eq!(option.tenant_key, Some("test_tenant".to_string()));
135
136        // Test with String
137        let option = RequestOption::builder()
138            .tenant_key("another_tenant".to_string())
139            .build();
140
141        assert_eq!(option.tenant_key, Some("another_tenant".to_string()));
142    }
143
144    #[test]
145    fn test_request_option_builder_user_access_token() {
146        let option = RequestOption::builder()
147            .user_access_token("user_token_123")
148            .build();
149
150        assert_eq!(option.user_access_token, Some("user_token_123".to_string()));
151
152        // Test with String
153        let option = RequestOption::builder()
154            .user_access_token("user_token_456".to_string())
155            .build();
156
157        assert_eq!(option.user_access_token, Some("user_token_456".to_string()));
158    }
159
160    #[test]
161    fn test_request_option_builder_app_access_token() {
162        let option = RequestOption::builder()
163            .app_access_token("app_token_789")
164            .build();
165
166        assert_eq!(option.app_access_token, Some("app_token_789".to_string()));
167
168        // Test with String
169        let option = RequestOption::builder()
170            .app_access_token("app_token_012".to_string())
171            .build();
172
173        assert_eq!(option.app_access_token, Some("app_token_012".to_string()));
174    }
175
176    #[test]
177    fn test_request_option_builder_tenant_access_token() {
178        let option = RequestOption::builder()
179            .tenant_access_token("tenant_token_345")
180            .build();
181
182        assert_eq!(
183            option.tenant_access_token,
184            Some("tenant_token_345".to_string())
185        );
186
187        // Test with String
188        let option = RequestOption::builder()
189            .tenant_access_token("tenant_token_678".to_string())
190            .build();
191
192        assert_eq!(
193            option.tenant_access_token,
194            Some("tenant_token_678".to_string())
195        );
196    }
197
198    #[test]
199    fn test_request_option_builder_need_helpdesk_auth() {
200        let option = RequestOption::builder().need_helpdesk_auth(true).build();
201
202        assert!(option.need_helpdesk_auth);
203
204        let option = RequestOption::builder().need_helpdesk_auth(false).build();
205
206        assert!(!option.need_helpdesk_auth);
207    }
208
209    #[test]
210    fn test_request_option_builder_request_id() {
211        let option = RequestOption::builder().request_id("req_12345").build();
212
213        assert_eq!(option.request_id, Some("req_12345".to_string()));
214
215        // Test with String
216        let option = RequestOption::builder()
217            .request_id("req_67890".to_string())
218            .build();
219
220        assert_eq!(option.request_id, Some("req_67890".to_string()));
221    }
222
223    #[test]
224    fn test_request_option_builder_app_ticket() {
225        let option = RequestOption::builder().app_ticket("ticket_abc").build();
226
227        assert_eq!(option.app_ticket, Some("ticket_abc".to_string()));
228
229        // Test with String
230        let option = RequestOption::builder()
231            .app_ticket("ticket_def".to_string())
232            .build();
233
234        assert_eq!(option.app_ticket, Some("ticket_def".to_string()));
235    }
236
237    #[test]
238    fn test_request_option_builder_file_upload() {
239        let option = RequestOption::builder().file_upload(true).build();
240
241        assert!(option.file_upload);
242
243        let option = RequestOption::builder().file_upload(false).build();
244
245        assert!(!option.file_upload);
246    }
247
248    #[test]
249    fn test_request_option_builder_file_download() {
250        let option = RequestOption::builder().file_download(true).build();
251
252        assert!(option.file_download);
253
254        let option = RequestOption::builder().file_download(false).build();
255
256        assert!(!option.file_download);
257    }
258
259    #[test]
260    fn test_request_option_builder_header() {
261        let mut headers = HashMap::new();
262        headers.insert("Content-Type".to_string(), "application/json".to_string());
263        headers.insert("Authorization".to_string(), "Bearer token".to_string());
264
265        let option = RequestOption::builder().header(headers.clone()).build();
266
267        assert_eq!(option.header.len(), 2);
268        assert_eq!(
269            option.header.get("Content-Type"),
270            Some(&"application/json".to_string())
271        );
272        assert_eq!(
273            option.header.get("Authorization"),
274            Some(&"Bearer token".to_string())
275        );
276    }
277
278    #[test]
279    fn test_request_option_builder_add_header() {
280        let option = RequestOption::builder()
281            .add_header("X-Custom-Header", "custom_value")
282            .add_header("X-Another-Header", "another_value")
283            .build();
284
285        assert_eq!(option.header.len(), 2);
286        assert_eq!(
287            option.header.get("X-Custom-Header"),
288            Some(&"custom_value".to_string())
289        );
290        assert_eq!(
291            option.header.get("X-Another-Header"),
292            Some(&"another_value".to_string())
293        );
294
295        // Test with String types
296        let option = RequestOption::builder()
297            .add_header("X-String-Header".to_string(), "string_value".to_string())
298            .build();
299
300        assert_eq!(option.header.len(), 1);
301        assert_eq!(
302            option.header.get("X-String-Header"),
303            Some(&"string_value".to_string())
304        );
305    }
306
307    #[test]
308    fn test_request_option_builder_add_header_multiple() {
309        let option = RequestOption::builder()
310            .add_header("Header1", "value1")
311            .add_header("Header2", "value2")
312            .add_header("Header3", "value3")
313            .build();
314
315        assert_eq!(option.header.len(), 3);
316        assert_eq!(option.header.get("Header1"), Some(&"value1".to_string()));
317        assert_eq!(option.header.get("Header2"), Some(&"value2".to_string()));
318        assert_eq!(option.header.get("Header3"), Some(&"value3".to_string()));
319    }
320
321    #[test]
322    fn test_request_option_builder_header_and_add_header() {
323        let mut initial_headers = HashMap::new();
324        initial_headers.insert("Initial-Header".to_string(), "initial_value".to_string());
325
326        let option = RequestOption::builder()
327            .header(initial_headers)
328            .add_header("Added-Header", "added_value")
329            .build();
330
331        assert_eq!(option.header.len(), 2);
332        assert_eq!(
333            option.header.get("Initial-Header"),
334            Some(&"initial_value".to_string())
335        );
336        assert_eq!(
337            option.header.get("Added-Header"),
338            Some(&"added_value".to_string())
339        );
340    }
341
342    #[test]
343    fn test_request_option_builder_chaining() {
344        let option = RequestOption::builder()
345            .tenant_key("test_tenant")
346            .user_access_token("user_token")
347            .app_access_token("app_token")
348            .tenant_access_token("tenant_token")
349            .need_helpdesk_auth(true)
350            .request_id("req_123")
351            .app_ticket("ticket_456")
352            .file_upload(true)
353            .file_download(false)
354            .add_header("X-Test", "test_value")
355            .build();
356
357        assert_eq!(option.tenant_key, Some("test_tenant".to_string()));
358        assert_eq!(option.user_access_token, Some("user_token".to_string()));
359        assert_eq!(option.app_access_token, Some("app_token".to_string()));
360        assert_eq!(option.tenant_access_token, Some("tenant_token".to_string()));
361        assert!(option.need_helpdesk_auth);
362        assert_eq!(option.request_id, Some("req_123".to_string()));
363        assert_eq!(option.app_ticket, Some("ticket_456".to_string()));
364        assert!(option.file_upload);
365        assert!(!option.file_download);
366        assert_eq!(option.header.len(), 1);
367        assert_eq!(option.header.get("X-Test"), Some(&"test_value".to_string()));
368    }
369
370    #[test]
371    fn test_request_option_builder_empty_strings() {
372        let option = RequestOption::builder()
373            .tenant_key("")
374            .user_access_token("")
375            .app_access_token("")
376            .tenant_access_token("")
377            .request_id("")
378            .app_ticket("")
379            .build();
380
381        assert_eq!(option.tenant_key, Some("".to_string()));
382        assert_eq!(option.user_access_token, Some("".to_string()));
383        assert_eq!(option.app_access_token, Some("".to_string()));
384        assert_eq!(option.tenant_access_token, Some("".to_string()));
385        assert_eq!(option.request_id, Some("".to_string()));
386        assert_eq!(option.app_ticket, Some("".to_string()));
387    }
388
389    #[test]
390    fn test_request_option_builder_special_characters() {
391        let option = RequestOption::builder()
392            .tenant_key("tenant@#$%^&*()")
393            .user_access_token("token_with_symbols!@#")
394            .request_id("req_with_unicode_测试")
395            .add_header("X-Special-Chars", "value@#$%")
396            .build();
397
398        assert_eq!(option.tenant_key, Some("tenant@#$%^&*()".to_string()));
399        assert_eq!(
400            option.user_access_token,
401            Some("token_with_symbols!@#".to_string())
402        );
403        assert_eq!(option.request_id, Some("req_with_unicode_测试".to_string()));
404        assert_eq!(
405            option.header.get("X-Special-Chars"),
406            Some(&"value@#$%".to_string())
407        );
408    }
409
410    #[test]
411    fn test_request_option_builder_overwrite_header() {
412        let mut initial_headers = HashMap::new();
413        initial_headers.insert("Test-Header".to_string(), "initial_value".to_string());
414
415        let option = RequestOption::builder()
416            .header(initial_headers)
417            .add_header("Test-Header", "overwritten_value")
418            .build();
419
420        assert_eq!(option.header.len(), 1);
421        assert_eq!(
422            option.header.get("Test-Header"),
423            Some(&"overwritten_value".to_string())
424        );
425    }
426
427    #[test]
428    fn test_request_option_builder_empty_header_map() {
429        let empty_headers = HashMap::new();
430
431        let option = RequestOption::builder().header(empty_headers).build();
432
433        assert!(option.header.is_empty());
434    }
435
436    #[test]
437    fn test_request_option_debug_clone() {
438        let option = RequestOption::builder()
439            .tenant_key("test")
440            .need_helpdesk_auth(true)
441            .build();
442
443        // Test Debug trait
444        let debug_str = format!("{:?}", option);
445        assert!(debug_str.contains("RequestOption"));
446
447        // Test Clone trait
448        let cloned_option = option.clone();
449        assert_eq!(option.tenant_key, cloned_option.tenant_key);
450        assert_eq!(option.need_helpdesk_auth, cloned_option.need_helpdesk_auth);
451    }
452
453    #[test]
454    fn test_request_option_builder_default() {
455        let builder = RequestOptionBuilder::default();
456        let option = builder.build();
457
458        // Should be equivalent to RequestOption::default()
459        let default_option = RequestOption::default();
460
461        assert_eq!(option.tenant_key, default_option.tenant_key);
462        assert_eq!(option.user_access_token, default_option.user_access_token);
463        assert_eq!(option.app_access_token, default_option.app_access_token);
464        assert_eq!(
465            option.tenant_access_token,
466            default_option.tenant_access_token
467        );
468        assert_eq!(option.need_helpdesk_auth, default_option.need_helpdesk_auth);
469        assert_eq!(option.request_id, default_option.request_id);
470        assert_eq!(option.app_ticket, default_option.app_ticket);
471        assert_eq!(option.file_upload, default_option.file_upload);
472        assert_eq!(option.file_download, default_option.file_download);
473        assert_eq!(option.header.len(), default_option.header.len());
474    }
475}