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 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 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 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 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 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 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 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 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 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 let debug_str = format!("{:?}", option);
445 assert!(debug_str.contains("RequestOption"));
446
447 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 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}