1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct CorsConfiguration {
10 pub rules: Vec<CorsRule>,
12}
13
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16#[serde(rename_all = "camelCase")]
17pub struct CorsRule {
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub id: Option<String>,
21
22 pub allowed_origins: Vec<String>,
24
25 pub allowed_methods: Vec<String>,
27
28 #[serde(skip_serializing_if = "Option::is_none")]
30 pub allowed_headers: Option<Vec<String>>,
31
32 #[serde(skip_serializing_if = "Option::is_none")]
34 pub expose_headers: Option<Vec<String>>,
35
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub max_age_seconds: Option<i32>,
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn test_cors_rule_serialization() {
47 let rule = CorsRule {
48 id: Some("web-app".to_string()),
49 allowed_origins: vec!["https://app.example.com".to_string()],
50 allowed_methods: vec!["GET".to_string(), "PUT".to_string()],
51 allowed_headers: Some(vec![
52 "Authorization".to_string(),
53 "Content-Type".to_string(),
54 ]),
55 expose_headers: Some(vec!["ETag".to_string()]),
56 max_age_seconds: Some(600),
57 };
58
59 let json = serde_json::to_string(&rule).expect("serialize rule");
60 assert!(json.contains("allowedOrigins"));
61 assert!(json.contains("maxAgeSeconds"));
62
63 let decoded: CorsRule = serde_json::from_str(&json).expect("deserialize rule");
64 assert_eq!(decoded.id.as_deref(), Some("web-app"));
65 assert_eq!(
66 decoded.allowed_origins,
67 vec!["https://app.example.com".to_string()]
68 );
69 assert_eq!(
70 decoded.allowed_methods,
71 vec!["GET".to_string(), "PUT".to_string()]
72 );
73 assert_eq!(decoded.max_age_seconds, Some(600));
74 }
75
76 #[test]
77 fn test_cors_configuration_serialization() {
78 let config = CorsConfiguration {
79 rules: vec![CorsRule {
80 id: None,
81 allowed_origins: vec!["*".to_string()],
82 allowed_methods: vec!["GET".to_string()],
83 allowed_headers: None,
84 expose_headers: None,
85 max_age_seconds: None,
86 }],
87 };
88
89 let json = serde_json::to_string_pretty(&config).expect("serialize config");
90 let decoded: CorsConfiguration = serde_json::from_str(&json).expect("deserialize config");
91 assert_eq!(decoded.rules.len(), 1);
92 assert_eq!(decoded.rules[0].allowed_origins, vec!["*".to_string()]);
93 assert_eq!(decoded.rules[0].allowed_methods, vec!["GET".to_string()]);
94 }
95}