elif_http/response/
headers.rs1use crate::errors::ParseError;
4use std::collections::HashMap;
5use std::fmt;
6use std::str::FromStr;
7
8#[repr(transparent)]
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct ElifHeaderName(axum::http::HeaderName);
12
13impl ElifHeaderName {
14 pub fn from_str(name: &str) -> Result<Self, ParseError> {
16 axum::http::HeaderName::from_str(name)
17 .map(Self)
18 .map_err(ParseError::from)
19 }
20
21 pub fn as_str(&self) -> &str {
23 self.0.as_str()
24 }
25
26 pub(crate) fn to_axum(&self) -> &axum::http::HeaderName {
28 &self.0
29 }
30
31 }
36
37impl FromStr for ElifHeaderName {
38 type Err = ParseError;
39
40 fn from_str(s: &str) -> Result<Self, Self::Err> {
41 <ElifHeaderName>::from_str(s)
43 }
44}
45
46impl fmt::Display for ElifHeaderName {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 write!(f, "{}", self.0)
49 }
50}
51
52#[repr(transparent)]
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct ElifHeaderValue(axum::http::HeaderValue);
56
57impl ElifHeaderValue {
58 pub fn from_str(value: &str) -> Result<Self, ParseError> {
60 axum::http::HeaderValue::from_str(value)
61 .map(Self)
62 .map_err(ParseError::from)
63 }
64
65 pub fn from_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
67 axum::http::HeaderValue::from_bytes(bytes)
68 .map(Self)
69 .map_err(ParseError::from)
70 }
71
72 pub fn from_static(value: &'static str) -> Self {
74 Self(axum::http::HeaderValue::from_static(value))
75 }
76
77 pub fn to_str(&self) -> Result<&str, ParseError> {
79 self.0.to_str().map_err(ParseError::from)
80 }
81
82 pub fn as_bytes(&self) -> &[u8] {
84 self.0.as_bytes()
85 }
86
87 pub(crate) fn to_axum(&self) -> &axum::http::HeaderValue {
89 &self.0
90 }
91
92 }
97
98impl FromStr for ElifHeaderValue {
99 type Err = ParseError;
100
101 fn from_str(s: &str) -> Result<Self, Self::Err> {
102 <ElifHeaderValue>::from_str(s)
104 }
105}
106
107impl fmt::Display for ElifHeaderValue {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 match self.to_str() {
110 Ok(s) => write!(f, "{}", s),
111 Err(_) => write!(f, "<invalid UTF-8>"),
112 }
113 }
114}
115
116#[derive(Debug, Clone)]
118pub struct ElifHeaderMap(axum::http::HeaderMap);
119
120impl ElifHeaderMap {
121 pub fn new() -> Self {
123 Self(axum::http::HeaderMap::new())
124 }
125
126 pub fn insert(
128 &mut self,
129 name: ElifHeaderName,
130 value: ElifHeaderValue,
131 ) -> Option<ElifHeaderValue> {
132 self.0.insert(name.0, value.0).map(ElifHeaderValue)
133 }
134
135 pub fn append(&mut self, name: ElifHeaderName, value: ElifHeaderValue) -> bool {
137 self.0.append(name.0, value.0)
138 }
139
140 pub fn get(&self, name: &ElifHeaderName) -> Option<&ElifHeaderValue> {
142 unsafe { std::mem::transmute(self.0.get(&name.0)) }
144 }
145
146 pub fn get_str(&self, name: &str) -> Option<&ElifHeaderValue> {
148 if let Ok(header_name) = ElifHeaderName::from_str(name) {
149 self.get(&header_name)
150 } else {
151 None
152 }
153 }
154
155 pub fn remove(&mut self, name: &ElifHeaderName) -> Option<ElifHeaderValue> {
157 self.0.remove(&name.0).map(ElifHeaderValue)
158 }
159
160 pub fn contains_key(&self, name: &ElifHeaderName) -> bool {
162 self.0.contains_key(&name.0)
163 }
164
165 pub fn contains_key_str(&self, name: &str) -> bool {
167 if let Ok(header_name) = ElifHeaderName::from_str(name) {
168 self.contains_key(&header_name)
169 } else {
170 false
171 }
172 }
173
174 pub fn len(&self) -> usize {
176 self.0.len()
177 }
178
179 pub fn is_empty(&self) -> bool {
181 self.0.is_empty()
182 }
183
184 pub fn clear(&mut self) {
186 self.0.clear();
187 }
188
189 pub fn iter(&self) -> impl Iterator<Item = (&ElifHeaderName, &ElifHeaderValue)> {
191 self.0.iter().map(|(k, v)| {
192 unsafe { (std::mem::transmute(k), std::mem::transmute(v)) }
194 })
195 }
196
197 pub fn keys(&self) -> impl Iterator<Item = &ElifHeaderName> {
199 self.0.keys().map(|k| {
200 unsafe { std::mem::transmute(k) }
202 })
203 }
204
205 pub fn values(&self) -> impl Iterator<Item = &ElifHeaderValue> {
207 self.0.values().map(|v| {
208 unsafe { std::mem::transmute(v) }
210 })
211 }
212
213 pub fn add_header(&mut self, name: &str, value: &str) -> Result<(), String> {
215 if let Ok(header_name) = ElifHeaderName::from_str(name) {
216 if let Ok(header_value) = ElifHeaderValue::from_str(value) {
217 self.insert(header_name, header_value);
218 Ok(())
219 } else {
220 Err("Invalid header value".to_string())
221 }
222 } else {
223 Err("Invalid header name".to_string())
224 }
225 }
226
227 pub fn remove_header(&mut self, name: &str) -> Option<ElifHeaderValue> {
229 if let Ok(header_name) = ElifHeaderName::from_str(name) {
230 self.remove(&header_name)
231 } else {
232 None
233 }
234 }
235
236 pub fn to_hash_map(&self) -> HashMap<String, String> {
238 self.0
239 .iter()
240 .filter_map(|(k, v)| {
241 v.to_str()
242 .ok()
243 .map(|v| (k.as_str().to_string(), v.to_string()))
244 })
245 .collect()
246 }
247
248 pub(crate) fn from_axum(headers: axum::http::HeaderMap) -> Self {
255 Self(headers)
256 }
257}
258
259impl Default for ElifHeaderMap {
260 fn default() -> Self {
261 Self::new()
262 }
263}
264
265impl From<axum::http::HeaderMap> for ElifHeaderMap {
266 fn from(headers: axum::http::HeaderMap) -> Self {
267 Self::from_axum(headers)
268 }
269}
270
271pub mod header_names {
273 use super::ElifHeaderName;
274 use axum::http::header;
275
276 pub const AUTHORIZATION: ElifHeaderName = ElifHeaderName(header::AUTHORIZATION);
279 pub const CONTENT_TYPE: ElifHeaderName = ElifHeaderName(header::CONTENT_TYPE);
280 pub const CONTENT_LENGTH: ElifHeaderName = ElifHeaderName(header::CONTENT_LENGTH);
281 pub const ACCEPT: ElifHeaderName = ElifHeaderName(header::ACCEPT);
282 pub const CACHE_CONTROL: ElifHeaderName = ElifHeaderName(header::CACHE_CONTROL);
283 pub const ETAG: ElifHeaderName = ElifHeaderName(header::ETAG);
284 pub const IF_NONE_MATCH: ElifHeaderName = ElifHeaderName(header::IF_NONE_MATCH);
285 pub const LOCATION: ElifHeaderName = ElifHeaderName(header::LOCATION);
286 pub const SET_COOKIE: ElifHeaderName = ElifHeaderName(header::SET_COOKIE);
287 pub const COOKIE: ElifHeaderName = ElifHeaderName(header::COOKIE);
288 pub const USER_AGENT: ElifHeaderName = ElifHeaderName(header::USER_AGENT);
289 pub const REFERER: ElifHeaderName = ElifHeaderName(header::REFERER);
290 pub const ORIGIN: ElifHeaderName = ElifHeaderName(header::ORIGIN);
291 pub const ACCESS_CONTROL_ALLOW_ORIGIN: ElifHeaderName =
292 ElifHeaderName(header::ACCESS_CONTROL_ALLOW_ORIGIN);
293 pub const ACCESS_CONTROL_ALLOW_METHODS: ElifHeaderName =
294 ElifHeaderName(header::ACCESS_CONTROL_ALLOW_METHODS);
295 pub const ACCESS_CONTROL_ALLOW_HEADERS: ElifHeaderName =
296 ElifHeaderName(header::ACCESS_CONTROL_ALLOW_HEADERS);
297 pub const ACCESS_CONTROL_EXPOSE_HEADERS: ElifHeaderName =
298 ElifHeaderName(header::ACCESS_CONTROL_EXPOSE_HEADERS);
299 pub const ACCESS_CONTROL_ALLOW_CREDENTIALS: ElifHeaderName =
300 ElifHeaderName(header::ACCESS_CONTROL_ALLOW_CREDENTIALS);
301 pub const ACCESS_CONTROL_MAX_AGE: ElifHeaderName =
302 ElifHeaderName(header::ACCESS_CONTROL_MAX_AGE);
303 pub const CONTENT_SECURITY_POLICY: ElifHeaderName =
304 ElifHeaderName(header::CONTENT_SECURITY_POLICY);
305 pub const STRICT_TRANSPORT_SECURITY: ElifHeaderName =
306 ElifHeaderName(header::STRICT_TRANSPORT_SECURITY);
307 pub const X_FRAME_OPTIONS: ElifHeaderName = ElifHeaderName(header::X_FRAME_OPTIONS);
308 pub const X_CONTENT_TYPE_OPTIONS: ElifHeaderName =
309 ElifHeaderName(header::X_CONTENT_TYPE_OPTIONS);
310 pub const X_XSS_PROTECTION: ElifHeaderName = ElifHeaderName(header::X_XSS_PROTECTION);
311 pub const REFERRER_POLICY: ElifHeaderName = ElifHeaderName(header::REFERRER_POLICY);
312}