1use crate::responses::ResponsesTypes;
18use crate::responses::{
19 ResponsesClientCodes, ResponsesCrawlerCodes, ResponsesInformationalCodes,
20 ResponsesLocalApiCodes, ResponsesRedirectionCodes, ResponsesServerCodes, ResponsesServiceCodes,
21 ResponsesSuccessCodes,
22};
23use crate::traits::get_description_trait::GetDescription;
25use crate::utils::populate_metadata::populate_metadata;
26use serde_json::{json, Value};
27use std::collections::HashMap;
28use std::time::Duration;
29use std::time::SystemTime;
30use strum::IntoEnumIterator;
31
32pub fn get_response_get_description(response: ResponsesTypes) -> (u16, &'static str) {
34 let code = response.get_code();
35 let description = response.get_description_field("Description").unwrap_or("No description");
36 (code, description)
37}
38
39pub fn get_advance_response_get_description(response: ResponsesTypes) -> (u16, &'static str) {
41 if let Some(normalized_response) = get_response_by_type(&response) {
42 (normalized_response.get_code(), normalized_response.get_description())
43 } else {
44 (response.get_code(), response.get_description())
45 };
46
47 let timestamp = SystemTime::now();
48
49 log::info!(
51 "Fetching description for code: {}, timestamp: {:?}",
52 response.get_code(),
53 timestamp
54 );
55
56 if let Ok(origin) = std::env::var("ALLOWED_ORIGIN") {
58 log::debug!("Applying CORS check for origin: {}", origin);
59 } else {
60 log::warn!("No ALLOWED_ORIGIN set; defaulting to open.");
61 }
62
63 let code = response.get_code();
65 let description = response.get_description_field("Description").unwrap_or("No description");
66
67 (code, description)
68}
69
70pub fn get_response_by_code(code: u16) -> Option<ResponsesTypes> {
72 ResponsesTypes::from_u16(code)
73}
74
75pub fn get_response_by_type(rtype: &ResponsesTypes) -> Option<ResponsesTypes> {
82 let (code, _) = get_response_get_description(*rtype);
83 get_response_by_code(code)
84}
85
86pub fn get_description_by_code(code: u16) -> Option<&'static str> {
88 get_response_by_code(code).and_then(|r| r.get_description().into())
89}
90
91pub fn get_advance_description_by_code(code: u16) -> Option<&'static str> {
93 log::info!("Fetching description for code: {}", code);
94
95 let fetched_description = get_response_by_code(code).map(|response_type| {
96 let description = GetDescription::get_description_field(&response_type, "Description")
97 .unwrap_or("No description");
98 log::debug!("Code {} corresponds to description: {}", code, description);
99 description
100 });
101
102 if fetched_description.is_none() {
103 log::warn!("No response type found for code: {}", code);
104 }
105
106 fetched_description
107}
108
109pub fn transform_to_json_short(response: ResponsesTypes) -> String {
111 let (code, description) = get_response_get_description(response);
112 json!({
113 "code": code,
114 "description": description
115 })
116 .to_string()
117}
118
119pub fn transform_to_json(response: ResponsesTypes) -> String {
121 let code = response.get_code();
122 let description = response.get_description();
123 json!({
124 "code": code,
125 "description": description
126 })
127 .to_string()
128}
129pub fn transform_to_json_filtered(response: ResponsesTypes) -> Option<String> {
131 let (code, description) = get_response_get_description(response);
132 if !(100..=599).contains(&code) {
133 None
134 } else {
135 Some(
136 json!({
137 "code": code,
138 "description": description,
139 "is_standard_code": true
140 })
141 .to_string(),
142 )
143 }
144}
145
146pub fn transform_to_json_with_metadata(response: ResponsesTypes) -> String {
148 let (code, description) = get_response_get_description(response);
149 let timestamp = chrono::Utc::now();
150 let metadata = json!({
151 "requested_at": timestamp.to_rfc3339(),
152 "status_family": match code {
153 100..=199 => "Informational",
154 200..=299 => "Success",
155 300..=399 => "Redirection",
156 400..=499 => "Client Error",
157 500..=599 => "Server Error",
158 600..=699 => "Service Error",
159 700..=799 => "Crawler Error",
160 900..=999 => "Local API Error",
161 _ => "Unknown",
162 },
163 "is_error": code >= 400,
164 });
165
166 json!({
167 "code": code,
168 "description": description,
169 "metadata": metadata
170 })
171 .to_string()
172}
173
174pub fn transform_to_xml_short(response: ResponsesTypes) -> String {
176 let (code, description) = get_response_get_description(response);
177 format!(
178 r#"<response><code>{}</code><description>{}</description></response>"#,
179 code, description
180 )
181}
182
183pub fn transform_to_xml(response: ResponsesTypes) -> String {
185 let code = response.get_code();
186 let description = response.get_description();
187 format!("<response><code>{}</code><description>{}</description></response>", code, description)
188}
189
190pub fn transform_to_xml_filtered(response: ResponsesTypes) -> Option<String> {
192 let (code, description) = get_response_get_description(response);
193 if !(100..=599).contains(&code) {
194 None
195 } else {
196 Some(format!(
197 r#"<response><code>{}</code><description>{}</description><is_standard_code>true</is_standard_code></response>"#,
198 code, description
199 ))
200 }
201}
202
203pub fn transform_to_xml_with_metadata(response: ResponsesTypes) -> String {
205 let (code, description) = get_response_get_description(response);
206 let timestamp = chrono::Utc::now();
207 let status_family = match code {
208 100..=199 => "Informational",
209 200..=299 => "Success",
210 300..=399 => "Redirection",
211 400..=499 => "Client Error",
212 500..=599 => "Server Error",
213 600..=699 => "Service Error",
214 700..=799 => "Crawler Error",
215 900..=999 => "Local API Error",
216 _ => "Unknown",
217 };
218 let is_error = code >= 400;
219
220 format!(
221 r#"<response>
222 <code>{}</code>
223 <description>{}</description>
224 <metadata>
225 <requested_at>{}</requested_at>
226 <status_family>{}</status_family>
227 <is_error>{}</is_error>
228 </metadata>
229</response>"#,
230 code,
231 description,
232 timestamp.to_rfc3339(),
233 status_family,
234 is_error
235 )
236}
237
238pub fn filter_codes_by_range(start: u16, end: u16) -> Vec<(u16, &'static str)> {
240 let mut filtered_codes = Vec::new();
241
242 add_filtered_codes(
243 start,
244 end,
245 ResponsesInformationalCodes::iter().map(ResponsesTypes::Informational),
246 &mut filtered_codes,
247 );
248 add_filtered_codes(
249 start,
250 end,
251 ResponsesSuccessCodes::iter().map(ResponsesTypes::Success),
252 &mut filtered_codes,
253 );
254 add_filtered_codes(
255 start,
256 end,
257 ResponsesRedirectionCodes::iter().map(ResponsesTypes::Redirection),
258 &mut filtered_codes,
259 );
260 add_filtered_codes(
261 start,
262 end,
263 ResponsesClientCodes::iter().map(ResponsesTypes::ClientError),
264 &mut filtered_codes,
265 );
266 add_filtered_codes(
267 start,
268 end,
269 ResponsesServerCodes::iter().map(ResponsesTypes::ServerError),
270 &mut filtered_codes,
271 );
272 add_filtered_codes(
273 start,
274 end,
275 ResponsesServiceCodes::iter().map(ResponsesTypes::ServiceError),
276 &mut filtered_codes,
277 );
278 add_filtered_codes(
279 start,
280 end,
281 ResponsesCrawlerCodes::iter().map(ResponsesTypes::CrawlerError),
282 &mut filtered_codes,
283 );
284 add_filtered_codes(
285 start,
286 end,
287 ResponsesLocalApiCodes::iter().map(ResponsesTypes::LocalApiError),
288 &mut filtered_codes,
289 );
290
291 filtered_codes
292}
293
294fn add_filtered_codes<I>(
302 start: u16,
303 end: u16,
304 codes_iter: I,
305 filtered_codes: &mut Vec<(u16, &'static str)>,
306) where
307 I: Iterator<Item = ResponsesTypes>,
308{
309 for response in codes_iter {
310 let (code, description) = get_response_get_description(response);
311 if code >= start && code <= end && !filtered_codes.iter().any(|(c, _)| *c == code) {
312 filtered_codes.push((code, description));
313 }
314 }
315}
316
317pub type ResponseCodeWithMetadata = (u16, &'static str, HashMap<String, String>);
319pub type ResponseCodeIterator = Box<dyn Iterator<Item = ResponseCodeWithMetadata>>;
320pub type RequestMetadata = Option<HashMap<&'static str, &'static str>>;
321
322pub fn filter_codes_by_range_with_metadata(
324 start: u16,
325 end: u16,
326 request_metadata: RequestMetadata,
327) -> Vec<ResponseCodeWithMetadata> {
328 let iterators: Vec<ResponseCodeIterator> = vec![
329 Box::new(ResponsesInformationalCodes::iter().map({
330 let request_metadata = request_metadata.clone();
331 move |code| {
332 let rtype = ResponsesTypes::Informational(code);
333 create_tuple_with_metadata(rtype, &request_metadata)
334 }
335 })),
336 Box::new(ResponsesSuccessCodes::iter().map({
337 let request_metadata = request_metadata.clone();
338 move |code| {
339 let rtype = ResponsesTypes::Success(code);
340 create_tuple_with_metadata(rtype, &request_metadata)
341 }
342 })),
343 Box::new(ResponsesRedirectionCodes::iter().map({
344 let request_metadata = request_metadata.clone();
345 move |code| {
346 let rtype = ResponsesTypes::Redirection(code);
347 create_tuple_with_metadata(rtype, &request_metadata)
348 }
349 })),
350 Box::new(ResponsesClientCodes::iter().map({
351 let request_metadata = request_metadata.clone();
352 move |code| {
353 let rtype = ResponsesTypes::ClientError(code);
354 create_tuple_with_metadata(rtype, &request_metadata)
355 }
356 })),
357 Box::new(ResponsesServerCodes::iter().map({
358 let request_metadata = request_metadata.clone();
359 move |code| {
360 let rtype = ResponsesTypes::ServerError(code);
361 create_tuple_with_metadata(rtype, &request_metadata)
362 }
363 })),
364 Box::new(ResponsesServiceCodes::iter().map({
365 let request_metadata = request_metadata.clone();
366 move |code| {
367 let rtype = ResponsesTypes::ServiceError(code);
368 create_tuple_with_metadata(rtype, &request_metadata)
369 }
370 })),
371 Box::new(ResponsesCrawlerCodes::iter().map({
372 let request_metadata = request_metadata.clone();
373 move |code| {
374 let rtype = ResponsesTypes::CrawlerError(code);
375 create_tuple_with_metadata(rtype, &request_metadata)
376 }
377 })),
378 Box::new(ResponsesLocalApiCodes::iter().map({
379 let request_metadata = request_metadata.clone();
380 move |code| {
381 let rtype = ResponsesTypes::LocalApiError(code);
382 create_tuple_with_metadata(rtype, &request_metadata)
383 }
384 })),
385 ];
386
387 let mut results = Vec::new();
388 for iterator in iterators {
389 for (code_u16, desc, meta) in iterator {
390 if code_u16 >= start && code_u16 <= end {
391 results.push((code_u16, desc, meta));
392 }
393 }
394 }
395
396 results
397}
398
399fn create_tuple_with_metadata(
401 rtype: ResponsesTypes,
402 request_metadata: &RequestMetadata,
403) -> ResponseCodeWithMetadata {
404 let metadata = request_metadata.clone().map_or_else(HashMap::new, |meta| {
405 meta.into_iter().map(|(k, v)| (k.to_string(), v.to_string())).collect()
406 });
407
408 (rtype.get_code(), rtype.get_description(), metadata)
409}
410
411pub fn list_codes_and_descriptions_short(family: &str) -> Vec<(u16, &'static str)> {
413 #[allow(clippy::type_complexity)]
414 let iterator: Box<dyn Iterator<Item = (u16, &'static str)>> = match family {
415 "Informational" => Box::new(
416 ResponsesInformationalCodes::iter()
417 .map(|c: ResponsesInformationalCodes| (c.get_code(), c.get_description())),
418 ),
419 "Success" => Box::new(
420 ResponsesSuccessCodes::iter()
421 .map(|c: ResponsesSuccessCodes| (c.get_code(), c.get_description())),
422 ),
423 "Redirection" => Box::new(
424 ResponsesRedirectionCodes::iter()
425 .map(|c: ResponsesRedirectionCodes| (c.get_code(), c.get_description())),
426 ),
427 "ClientError" => Box::new(
428 ResponsesClientCodes::iter()
429 .map(|c: ResponsesClientCodes| (c.get_code(), c.get_description())),
430 ),
431 "ServerError" => Box::new(
432 ResponsesServerCodes::iter()
433 .map(|c: ResponsesServerCodes| (c.get_code(), c.get_description())),
434 ),
435 "Service" => Box::new(
436 ResponsesServiceCodes::iter()
437 .map(|c: ResponsesServiceCodes| (c.get_code(), c.get_description())),
438 ),
439 "Crawler" => Box::new(
440 ResponsesCrawlerCodes::iter()
441 .map(|c: ResponsesCrawlerCodes| (c.get_code(), c.get_description())),
442 ),
443 "LocalApi" => Box::new(
444 ResponsesLocalApiCodes::iter()
445 .map(|c: ResponsesLocalApiCodes| (c.get_code(), c.get_description())),
446 ),
447 _ => Box::new(std::iter::empty()),
448 };
449
450 iterator.collect()
451}
452pub fn list_codes_and_descriptions_with_metadata(
454 family: &str,
455 request_metadata: Option<HashMap<&str, &str>>,
456) -> Vec<ResponseCodeWithMetadata> {
457 let iterator: Box<dyn Iterator<Item = (u16, &'static str)>> = match family {
458 "Informational" => Box::new(ResponsesInformationalCodes::iter().map(|c| {
459 (c.get_code(), c.get_description_field("Description").unwrap_or("No description"))
460 })),
461 "Success" => Box::new(ResponsesSuccessCodes::iter().map(|c| {
462 (c.get_code(), c.get_description_field("Description").unwrap_or("No description"))
463 })),
464 "Redirection" => Box::new(ResponsesRedirectionCodes::iter().map(|c| {
465 (c.get_code(), c.get_description_field("Description").unwrap_or("No description"))
466 })),
467 "ClientError" => Box::new(ResponsesClientCodes::iter().map(|c| {
468 (c.get_code(), c.get_description_field("Description").unwrap_or("No description"))
469 })),
470 "ServerError" => Box::new(ResponsesServerCodes::iter().map(|c| {
471 (c.get_code(), c.get_description_field("Description").unwrap_or("No description"))
472 })),
473 "ServiceError" => Box::new(ResponsesServiceCodes::iter().map(|c| {
474 (c.get_code(), c.get_description_field("Description").unwrap_or("No description"))
475 })),
476 "CrawlerError" => Box::new(ResponsesCrawlerCodes::iter().map(|c| {
477 (c.get_code(), c.get_description_field("Description").unwrap_or("No description"))
478 })),
479 "LocalApiError" => Box::new(ResponsesLocalApiCodes::iter().map(|c| {
480 (c.get_code(), c.get_description_field("Description").unwrap_or("No description"))
481 })),
482 _ => return vec![],
483 };
484
485 iterator
486 .map(|(code, description)| {
487 let metadata = populate_metadata(code, description, request_metadata.clone());
488 (code, description, metadata)
489 })
490 .collect()
491}
492
493pub fn create_response(code: u16, description: &str, data: &str) -> String {
495 json!({
496 "code": code,
497 "description": description,
498 "data": serde_json::from_str::<Value>(data).unwrap_or(Value::Null)
499 })
500 .to_string()
501}
502
503pub fn create_response_xml(code: u16, description: &str, data: &str) -> String {
505 format!(
506 r#"<response><code>{}</code><description>{}</description><data>{}</data></response>"#,
507 code, description, data
508 )
509}
510
511pub fn convert_to_enum(code: u16) -> Option<ResponsesTypes> {
513 get_response_by_code(code)
514}
515
516pub fn create_response_with_types(
518 response_type: Option<ResponsesTypes>,
519 data: Option<&str>,
520) -> String {
521 let mut map = serde_json::Map::new();
522 if let Some(rt) = response_type {
523 map.insert("code".to_string(), json!(rt.get_code()));
524 let description = rt.get_description();
525 map.insert("description".to_string(), json!(description));
526 }
527 if let Some(d) = data {
528 let data_value: Value = serde_json::from_str(d).unwrap();
529 map.extend(data_value.as_object().unwrap().clone());
530 }
531 Value::Object(map).to_string()
532}
533
534pub fn get_enriched_response_with_metadata(
536 response: ResponsesTypes,
537 cors_origin: Option<&str>,
538 duration: Duration,
539) -> String {
540 let (code, description) = get_response_get_description(response);
541 let timestamp = chrono::Utc::now();
542
543 let cors_headers = match cors_origin {
545 Some(origin) => json!({ "Access-Control-Allow-Origin": origin }),
546 None => json!({ "Access-Control-Allow-Origin": "*" }),
547 };
548
549 let metadata = json!({
551 "requested_at": timestamp.to_rfc3339(),
552 "status_family": match code {
553 100..=199 => "Informational",
554 200..=299 => "Success",
555 300..=399 => "Redirection",
556 400..=499 => "Client Error",
557 500..=599 => "Server Error",
558 _ => "Unknown",
559 },
560 "is_error": code >= 400,
561 "processing_time_ms": duration.as_millis()
562 });
563
564 json!({
565 "code": code,
566 "description": description,
567 "headers": cors_headers,
568 "metadata": metadata
569 })
570 .to_string()
571}
572
573pub fn is_origin_allowed(origin: &str, allowed_origins: &[&str]) -> bool {
575 allowed_origins.contains(&origin)
576}
577
578#[cfg(test)]
579mod tests {
580 use super::*;
581 use crate::responses::{ResponsesSuccessCodes, ResponsesTypes};
582 use serde_json::json;
583
584 #[test]
585 fn test_get_response_by_code() {
586 let response = get_response_by_code(200);
587 assert!(response.is_some());
588 assert_eq!(response.unwrap().get_code(), 200);
589 }
590
591 #[test]
592 fn test_get_description_by_code() {
593 let description = get_description_by_code(200);
594 assert!(description.is_some());
595 assert_eq!(
596 description.unwrap(),
597 "Request processed successfully. Response will depend on the request method used, and the result will be either a representation of the requested resource or an empty response"
598 );
599 }
600
601 #[test]
602 fn test_transform_to_json() {
603 let response = ResponsesTypes::Success(ResponsesSuccessCodes::Ok);
604 let json_str = transform_to_json(response);
605 let expected_json = json!({
606 "code": 200,
607 "description": "Request processed successfully. Response will depend on the request method used, and the result will be either a representation of the requested resource or an empty response"
608 })
609 .to_string();
610 assert_eq!(json_str, expected_json);
611 }
612
613 #[test]
614 fn test_transform_to_json_with_metadata() {
615 let response = ResponsesTypes::Success(ResponsesSuccessCodes::Ok);
616 let json_str = transform_to_json_with_metadata(response);
617 assert!(json_str.contains("\"requested_at\""));
618 assert!(json_str.contains("\"status_family\":\"Success\""));
619 }
620
621 #[test]
622 fn test_transform_to_json_filtered() {
623 let response = ResponsesTypes::Success(ResponsesSuccessCodes::Ok);
624 let json_str = transform_to_json_filtered(response).unwrap();
625 assert!(json_str.contains("\"is_standard_code\":true"));
626 }
627
628 #[test]
629 fn test_transform_to_xml() {
630 let response = ResponsesTypes::Success(ResponsesSuccessCodes::Ok);
631 let xml_str = transform_to_xml(response);
632 let expected_xml = r#"<response><code>200</code><description>Request processed successfully. Response will depend on the request method used, and the result will be either a representation of the requested resource or an empty response</description></response>"#;
633 assert_eq!(xml_str, expected_xml);
634 }
635
636 #[test]
637 fn test_transform_to_xml_with_metadata() {
638 let response = ResponsesTypes::Success(ResponsesSuccessCodes::Ok);
639 let xml_str = transform_to_xml_with_metadata(response);
640 assert!(xml_str.contains("<requested_at>"));
641 assert!(xml_str.contains("<status_family>Success</status_family>"));
642 }
643
644 #[test]
645 fn test_transform_to_xml_filtered() {
646 let response = ResponsesTypes::Success(ResponsesSuccessCodes::Ok);
647 let xml_str = transform_to_xml_filtered(response).unwrap();
648 assert!(xml_str.contains("<is_standard_code>true</is_standard_code>"));
649 }
650
651 #[test]
652 fn test_get_response_by_code_unknown() {
653 let response = get_response_by_code(9999);
654 assert!(response.is_none());
655 }
656
657 #[test]
658 fn test_filter_codes_by_range() {
659 let codes = filter_codes_by_range(100, 103);
660 let expected_codes = vec![
661 (
662 100,
663 "The server has received the initial part of the request, the headers, and asks the client to continue request, proceed to send the body of the request, a POST request",
664 ),
665 (
666 101,
667 "The server is complying with a request to switch protocols, used in WebSocket connections",
668 ),
669 (
670 102,
671 "Indicates the server is processing the request but has not yet finished, used to prevent timeout errors in asynchronous operations, webdav RFC 2518",
672 ),
673 (
674 103,
675 "Experimental: The server provides preliminary hints to the client, such as preloading resources while the final response is being prepared",
676 ),
677 ];
678 assert_eq!(codes, expected_codes);
679 }
680
681 #[test]
682 fn test_filter_codes_by_range_with_metadata() {
683 let request_metadata = Some(std::collections::HashMap::from([("source", "test_case")]));
684 let codes = filter_codes_by_range_with_metadata(200, 299, request_metadata);
685 assert!(!codes.is_empty());
686 assert!(codes[0].2.contains_key("source"));
687 }
688
689 #[test]
690 fn test_filter_codes_by_range_by_length() {
691 let codes = filter_codes_by_range(200, 201);
692 assert_eq!(codes.len(), 2);
693 }
694
695 #[test]
696 fn test_list_codes_and_descriptions_with_metadata() {
697 let request_metadata = Some(std::collections::HashMap::from([("source", "unit_test")]));
698 let descriptions = list_codes_and_descriptions_with_metadata("Success", request_metadata);
699 assert!(!descriptions.is_empty());
700 assert!(descriptions[0].2.contains_key("source"));
701 }
702
703 #[test]
704 fn test_list_codes_and_descriptions_short() {
705 let informational = list_codes_and_descriptions_short("Informational");
706 assert!(!informational.is_empty());
707 assert_eq!(informational[0].0, 100);
708
709 let success = list_codes_and_descriptions_short("Success");
710 assert!(!success.is_empty());
711 assert_eq!(success[0].0, 200);
712
713 let unknown = list_codes_and_descriptions_short("UnknownFamily");
714 assert!(unknown.is_empty());
715 }
716
717 #[test]
718 fn test_create_response_with_types() {
719 let response = Some(ResponsesTypes::Success(ResponsesSuccessCodes::Ok));
720 let json_response = create_response_with_types(response, Some(r#"{"key": "value"}"#));
721 println!("JSON Response: {}", json_response);
722 assert!(json_response.contains("\"description\":\"Request processed successfully. Response will depend on the request method used, and the result will be either a representation of the requested resource or an empty response\""));
723 assert!(json_response.contains("\"key\":\"value\""));
724 }
725
726 #[test]
727 fn test_create_response() {
728 let code = 200;
729 let description = "OK";
730 let data = r#"{"message": "Success"}"#;
731 let response = create_response(code, description, data);
732 let expected_response = json!({
733 "code": 200,
734 "description": "OK",
735 "data": {
736 "message": "Success"
737 }
738 })
739 .to_string();
740 assert_eq!(response, expected_response);
741 }
742
743 #[test]
744 fn test_create_response_without_json() {
745 let code = 200;
746 let description = "OK";
747 let data = r#"{"message": "Success"}"#;
748 let response = create_response(code, description, data);
749 assert!(response.contains("\"code\":200"));
750 assert!(response.contains("\"description\":\"OK\""));
751 assert!(response.contains("\"message\":\"Success\""));
752 }
753
754 #[test]
755 fn test_create_response_xml() {
756 let code = 200;
757 let description = "OK";
758 let data = "<message>Success</message>";
759 let response = create_response_xml(code, description, data);
760 let expected_response = format!(
761 r#"<response><code>{}</code><description>{}</description><data>{}</data></response>"#,
762 code, description, data
763 );
764 assert_eq!(response, expected_response);
765 }
766
767 #[test]
768 fn test_convert_to_enum() {
769 let code = 200;
770 let response_type = convert_to_enum(code);
771 assert!(response_type.is_some());
772 assert_eq!(response_type.unwrap().get_code(), 200);
773 }
774
775 #[test]
776 fn test_get_enriched_response_with_metadata() {
777 let response = ResponsesTypes::Success(ResponsesSuccessCodes::Ok);
778 let enriched_response = get_enriched_response_with_metadata(
779 response,
780 Some("https://example.com"),
781 Duration::from_millis(150),
782 );
783 assert!(enriched_response.contains("\"code\":200"));
784 assert!(
785 enriched_response.contains("\"Access-Control-Allow-Origin\":\"https://example.com\"")
786 );
787 }
788
789 #[test]
790 fn test_is_origin_allowed() {
791 let allowed_origins = vec!["https://example.com", "https://localhost"];
792 assert!(is_origin_allowed("https://example.com", &allowed_origins));
793 assert!(!is_origin_allowed("https://unauthorized.com", &allowed_origins));
794 }
795
796 #[test]
797 fn test_get_response_by_type() {
798 let client_error = ResponsesTypes::ClientError(ResponsesClientCodes::BadRequest);
799 let result = get_response_by_type(&client_error);
800 let _unknown_response = ResponsesTypes::from_u16(9999);
801
802 assert!(result.is_some());
803 assert_eq!(result.unwrap().get_code(), 400);
804 }
805}