Skip to main content

sark_core/http/response/
header.rs

1use std::slice;
2
3use http::{HeaderName, HeaderValue};
4
5use super::HeaderNameRef;
6use crate::http::Field;
7
8#[derive(Clone, Default, PartialEq, Eq)]
9pub struct HeaderList {
10    entries: Vec<(HeaderName, HeaderValue)>,
11    wire_len: usize,
12}
13
14static EMPTY_HEADER_LIST: HeaderList = HeaderList {
15    entries: Vec::new(),
16    wire_len: 0,
17};
18
19impl std::fmt::Debug for HeaderList {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        let mut list = f.debug_list();
22        for (name, value) in self {
23            list.entry(&(name, value));
24        }
25        list.finish()
26    }
27}
28
29pub struct HeaderIter<'a> {
30    inner: slice::Iter<'a, (HeaderName, HeaderValue)>,
31}
32
33impl<'a> Iterator for HeaderIter<'a> {
34    type Item = (&'a HeaderName, &'a HeaderValue);
35
36    fn next(&mut self) -> Option<Self::Item> {
37        self.inner.next().map(|(name, value)| (name, value))
38    }
39}
40
41impl HeaderList {
42    pub fn new() -> Self {
43        Self {
44            entries: Vec::new(),
45            wire_len: 0,
46        }
47    }
48
49    pub(super) fn empty_static() -> &'static Self {
50        &EMPTY_HEADER_LIST
51    }
52
53    pub fn with_capacity(capacity: usize) -> Self {
54        Self {
55            entries: Vec::with_capacity(capacity),
56            wire_len: 0,
57        }
58    }
59
60    pub fn is_empty(&self) -> bool {
61        self.entries.is_empty()
62    }
63
64    pub fn len(&self) -> usize {
65        self.entries.len()
66    }
67
68    pub fn iter(&self) -> HeaderIter<'_> {
69        HeaderIter {
70            inner: self.entries.iter(),
71        }
72    }
73
74    pub(crate) fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> + '_ {
75        self.entries
76            .iter()
77            .map(|(name, value)| Field::new(name.as_str().as_bytes(), value.as_bytes()))
78    }
79
80    pub fn wire_len(&self) -> usize {
81        self.wire_len
82    }
83
84    pub fn get<K>(&self, name: K) -> Option<&HeaderValue>
85    where
86        K: HeaderNameRef,
87    {
88        self.entries
89            .iter()
90            .find(|(n, _)| n.as_str().eq_ignore_ascii_case(name.as_header_name()))
91            .map(|(_, v)| v)
92    }
93
94    pub fn contains_key<K>(&self, name: K) -> bool
95    where
96        K: HeaderNameRef,
97    {
98        self.get(name).is_some()
99    }
100
101    pub fn insert(&mut self, name: HeaderName, value: HeaderValue) -> Option<HeaderValue> {
102        let added = header_wire_len(name.as_str(), value.as_bytes());
103        if let Some(index) = self.entries.iter().position(|(n, _)| *n == name) {
104            let removed_old = header_wire_len(
105                self.entries[index].0.as_str(),
106                self.entries[index].1.as_bytes(),
107            );
108            let old = std::mem::replace(&mut self.entries[index].1, value);
109            self.wire_len = self.wire_len + added - removed_old;
110            self.dedup_by_name(&name, index + 1);
111            return Some(old);
112        }
113        self.entries.push((name, value));
114        self.wire_len += added;
115        None
116    }
117
118    pub fn extend_trailers(
119        &mut self,
120        trailers: impl IntoIterator<Item = (HeaderName, HeaderValue)>,
121    ) {
122        for (name, value) in trailers {
123            if is_forbidden_trailer(&name) {
124                continue;
125            }
126            let _ = self.insert(name, value);
127        }
128    }
129
130    pub fn remove<K>(&mut self, name: K) -> Option<HeaderValue>
131    where
132        K: HeaderNameRef,
133    {
134        let index = self
135            .entries
136            .iter()
137            .position(|(n, _)| n.as_str().eq_ignore_ascii_case(name.as_header_name()))?;
138        let (removed_name, removed_value) = self.entries.remove(index);
139        self.wire_len -= header_wire_len(removed_name.as_str(), removed_value.as_bytes());
140        self.dedup_by_name(&removed_name, 0);
141        Some(removed_value)
142    }
143
144    fn dedup_by_name(&mut self, name: &HeaderName, start: usize) {
145        let mut scan = start;
146        while scan < self.entries.len() {
147            if self.entries[scan].0 == *name {
148                self.wire_len -= header_wire_len(
149                    self.entries[scan].0.as_str(),
150                    self.entries[scan].1.as_bytes(),
151                );
152                self.entries.remove(scan);
153            } else {
154                scan += 1;
155            }
156        }
157    }
158}
159
160fn is_forbidden_trailer(name: &HeaderName) -> bool {
161    matches!(
162        name.as_str(),
163        "content-length"
164            | "transfer-encoding"
165            | "host"
166            | "trailer"
167            | "connection"
168            | "keep-alive"
169            | "te"
170            | "upgrade"
171            | "proxy-authenticate"
172            | "proxy-authorization"
173    )
174}
175
176fn header_wire_len(name: &str, value: &[u8]) -> usize {
177    name.len() + 2 + value.len() + 2
178}
179
180impl From<Vec<(HeaderName, HeaderValue)>> for HeaderList {
181    fn from(value: Vec<(HeaderName, HeaderValue)>) -> Self {
182        let mut headers = Self::with_capacity(value.len());
183        for (name, value) in value {
184            let _ = headers.insert(name, value);
185        }
186        headers
187    }
188}
189
190impl<'a> IntoIterator for &'a HeaderList {
191    type Item = (&'a HeaderName, &'a HeaderValue);
192    type IntoIter = HeaderIter<'a>;
193
194    fn into_iter(self) -> Self::IntoIter {
195        self.iter()
196    }
197}