1use alloc::string::String;
7
8pub const REQUEST_API_KEY: &str = "OMG-DDS-API-Key";
10
11#[derive(Debug, Clone, Default, PartialEq, Eq)]
13pub struct RequestHeaders {
14 pub accept: Option<String>,
16 pub content_type: Option<String>,
18 pub content_length: Option<u64>,
20 pub cache_control: Option<String>,
22 pub api_key: Option<String>,
24}
25
26impl RequestHeaders {
27 pub fn validate_required(&self) -> Result<(), MissingHeader> {
34 if self.api_key.is_none() {
35 return Err(MissingHeader::ApiKey);
36 }
37 if self.accept.is_none() {
38 return Err(MissingHeader::Accept);
39 }
40 if self.cache_control.is_none() {
41 return Err(MissingHeader::CacheControl);
42 }
43 Ok(())
44 }
45}
46
47#[derive(Debug, Clone, Default, PartialEq, Eq)]
49pub struct ResponseHeaders {
50 pub authentication_info: Option<String>,
52 pub cache_control: Option<String>,
54 pub content_length: Option<u64>,
56 pub content_type: Option<String>,
58 pub date: Option<String>,
60 pub expires: Option<String>,
62 pub location: Option<String>,
64 pub last_modified: Option<String>,
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub enum MissingHeader {
71 ApiKey,
73 Accept,
75 CacheControl,
77}
78
79impl core::fmt::Display for MissingHeader {
80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81 match self {
82 Self::ApiKey => f.write_str("missing OMG-DDS-API-Key"),
83 Self::Accept => f.write_str("missing Accept"),
84 Self::CacheControl => f.write_str("missing Cache-Control"),
85 }
86 }
87}
88
89#[cfg(feature = "std")]
90impl std::error::Error for MissingHeader {}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn request_api_key_constant_matches_spec() {
98 assert_eq!(REQUEST_API_KEY, "OMG-DDS-API-Key");
99 }
100
101 #[test]
102 fn validate_required_passes_with_all_three_headers() {
103 let h = RequestHeaders {
104 accept: Some(String::from("application/zerodds-web+xml")),
105 cache_control: Some(String::from("no-cache")),
106 api_key: Some(String::from("secret-key-1234")),
107 ..Default::default()
108 };
109 assert_eq!(h.validate_required(), Ok(()));
110 }
111
112 #[test]
113 fn missing_api_key_rejected() {
114 let h = RequestHeaders {
115 accept: Some(String::from("application/zerodds-web+xml")),
116 cache_control: Some(String::from("no-cache")),
117 ..Default::default()
118 };
119 assert_eq!(h.validate_required(), Err(MissingHeader::ApiKey));
120 }
121
122 #[test]
123 fn missing_accept_rejected() {
124 let h = RequestHeaders {
125 cache_control: Some(String::from("no-cache")),
126 api_key: Some(String::from("k")),
127 ..Default::default()
128 };
129 assert_eq!(h.validate_required(), Err(MissingHeader::Accept));
130 }
131
132 #[test]
133 fn missing_cache_control_rejected() {
134 let h = RequestHeaders {
135 accept: Some(String::from("application/zerodds-web+xml")),
136 api_key: Some(String::from("k")),
137 ..Default::default()
138 };
139 assert_eq!(h.validate_required(), Err(MissingHeader::CacheControl));
140 }
141
142 #[test]
143 fn response_headers_default_is_empty() {
144 let r = ResponseHeaders::default();
145 assert!(r.cache_control.is_none());
146 assert!(r.content_type.is_none());
147 assert!(r.location.is_none());
148 }
149}