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        if let Some(index) = self.entries.iter().position(|(n, _)| *n == name) {
103            let old = std::mem::replace(&mut self.entries[index].1, value);
104            self.dedup_by_name(&name, index + 1);
105            self.refresh_wire_len();
106            return Some(old);
107        }
108        self.entries.push((name, value));
109        self.refresh_wire_len();
110        None
111    }
112
113    pub fn extend_trailers(
114        &mut self,
115        trailers: impl IntoIterator<Item = (HeaderName, HeaderValue)>,
116    ) {
117        for (name, value) in trailers {
118            if is_forbidden_trailer(&name) {
119                continue;
120            }
121            let _ = self.insert(name, value);
122        }
123    }
124
125    pub fn remove<K>(&mut self, name: K) -> Option<HeaderValue>
126    where
127        K: HeaderNameRef,
128    {
129        let index = self
130            .entries
131            .iter()
132            .position(|(n, _)| n.as_str().eq_ignore_ascii_case(name.as_header_name()))?;
133        let (removed_name, removed_value) = self.entries.remove(index);
134        self.dedup_by_name(&removed_name, 0);
135        self.refresh_wire_len();
136        Some(removed_value)
137    }
138
139    fn dedup_by_name(&mut self, name: &HeaderName, start: usize) {
140        let mut scan = start;
141        while scan < self.entries.len() {
142            if self.entries[scan].0 == *name {
143                self.entries.remove(scan);
144            } else {
145                scan += 1;
146            }
147        }
148    }
149
150    fn refresh_wire_len(&mut self) {
151        self.wire_len = self.entries.iter().fold(0usize, |total, (name, value)| {
152            total.saturating_add(header_wire_len(name.as_str(), value.as_bytes()))
153        });
154    }
155}
156
157fn is_forbidden_trailer(name: &HeaderName) -> bool {
158    matches!(
159        name.as_str(),
160        "content-length"
161            | "transfer-encoding"
162            | "host"
163            | "trailer"
164            | "connection"
165            | "keep-alive"
166            | "te"
167            | "upgrade"
168            | "proxy-authenticate"
169            | "proxy-authorization"
170    )
171}
172
173fn header_wire_len(name: &str, value: &[u8]) -> usize {
174    name.len()
175        .saturating_add(2)
176        .saturating_add(value.len())
177        .saturating_add(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}