Skip to main content

trillium_http/
headers.rs

1//! Header types
2pub(crate) mod compression_error;
3mod entry;
4mod entry_name;
5mod field_section;
6mod header_name;
7pub(crate) mod header_observer;
8mod header_value;
9mod header_values;
10#[cfg(feature = "unstable")]
11pub mod hpack;
12#[cfg(not(feature = "unstable"))]
13pub(crate) mod hpack;
14pub(crate) mod huffman;
15mod integer_prefix;
16mod known_header_name;
17pub(in crate::headers) mod recent_pairs;
18mod static_hit;
19mod unknown_header_name;
20
21#[cfg(feature = "unstable")]
22pub mod qpack;
23
24#[cfg(not(feature = "unstable"))]
25pub(crate) mod qpack;
26
27use crate::headers::entry::{OccupiedEntryInner, VacantEntryInner};
28pub use entry::{Entry, OccupiedEntry, VacantEntry};
29use hashbrown::{
30    HashMap,
31    hash_map::{self, Entry as HashbrownEntry},
32};
33pub use header_name::HeaderName;
34use header_name::HeaderNameInner;
35pub use header_value::HeaderValue;
36pub use header_values::HeaderValues;
37pub use known_header_name::KnownHeaderName;
38use std::{
39    collections::{
40        BTreeMap,
41        btree_map::{self, Entry as BTreeEntry},
42    },
43    fmt::{self, Debug, Display, Formatter},
44};
45use unknown_header_name::UnknownHeaderName;
46
47/// Trillium's header map type
48#[derive(Debug, Clone, PartialEq, Eq, Default)]
49#[must_use]
50pub struct Headers {
51    pub(crate) known: BTreeMap<KnownHeaderName, HeaderValues>,
52    pub(crate) unknown: HashMap<UnknownHeaderName<'static>, HeaderValues>,
53}
54
55/// Default Server header
56pub const SERVER_HEADER: HeaderValue =
57    HeaderValue::const_new(concat!("trillium-http/", env!("CARGO_PKG_VERSION")));
58
59#[cfg(feature = "serde")]
60impl serde::Serialize for Headers {
61    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
62    where
63        S: serde::Serializer,
64    {
65        use serde::ser::SerializeMap;
66        let mut map = serializer.serialize_map(Some(self.len()))?;
67        for (key, values) in self {
68            map.serialize_entry(&key, values)?;
69        }
70        map.end()
71    }
72}
73
74impl Display for Headers {
75    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
76        // Sorted+allocated so test snapshots are deterministic.
77        // HTTP/1.x has no stable-order requirement, so wire emission iterates directly.
78        let mut data = self.iter().collect::<Vec<_>>();
79        data.sort_by(|(a, _), (b, _)| a.cmp(b));
80        for (n, v) in data {
81            for v in v {
82                f.write_fmt(format_args!("{n}: {v}\r\n"))?;
83            }
84        }
85        Ok(())
86    }
87}
88
89#[cfg(feature = "parse")]
90impl Headers {
91    #[doc(hidden)]
92    pub fn extend_parse(&mut self, bytes: &[u8]) -> Result<usize, crate::Error> {
93        use memchr::memmem::Finder;
94
95        let mut new_header_count = 0;
96        let mut last_line = 0;
97        for newline in Finder::new(b"\r\n").find_iter(bytes) {
98            if newline == last_line {
99                continue;
100            }
101
102            let line = &bytes[last_line..newline];
103            let colon = memchr::memchr(b':', line).ok_or(crate::Error::InvalidHead)?;
104
105            let header_name = HeaderName::parse(&line[..colon])?.to_owned();
106
107            let token_end = last_line + colon;
108
109            let mut value_start = token_end + 1;
110
111            while bytes
112                .get(value_start)
113                .is_some_and(|b| matches!(b, b'\t' | b' '))
114            {
115                value_start += 1;
116            }
117
118            let header_value = HeaderValue::parse(bytes[value_start..newline].trim_ascii_end());
119            self.append(header_name, header_value);
120            new_header_count += 1;
121            last_line = newline + 2;
122        }
123        Ok(new_header_count)
124    }
125
126    #[doc(hidden)]
127    pub fn parse(bytes: &[u8]) -> Result<Self, crate::Error> {
128        let mut headers = Headers::new();
129        headers.extend_parse(bytes)?;
130        Ok(headers)
131    }
132}
133
134impl Headers {
135    /// Construct a new headers with a default capacity
136    pub fn new() -> Self {
137        Self::default()
138    }
139
140    /// Return an iterator over borrowed header names and header
141    /// values. First yields the known headers and then the unknown
142    /// headers, if any.
143    pub fn iter(&self) -> Iter<'_> {
144        self.into()
145    }
146
147    /// Are there zero headers?
148    pub fn is_empty(&self) -> bool {
149        self.known.is_empty() && self.unknown.is_empty()
150    }
151
152    /// How many unique [`HeaderName`] have been added to these [`Headers`]?
153    /// Note that each header name may have more than one [`HeaderValue`].
154    pub fn len(&self) -> usize {
155        self.known.len() + self.unknown.len()
156    }
157
158    /// add the header value or header values into this header map. If
159    /// there is already a header with the same name, the new values
160    /// will be added to the existing ones. To replace any existing
161    /// values, use [`Headers::insert`]
162    ///
163    /// Identical to [`headers.entry(name).append(values)`][Entry::append]
164    pub fn append(
165        &mut self,
166        name: impl Into<HeaderName<'static>>,
167        values: impl Into<HeaderValues>,
168    ) -> &mut HeaderValues {
169        self.entry(name).append(values)
170    }
171
172    /// A slightly more efficient way to combine two [`Headers`] than
173    /// using [`Extend`]
174    pub fn append_all(&mut self, other: Headers) {
175        for (name, value) in other.known {
176            match self.known.entry(name) {
177                BTreeEntry::Occupied(mut entry) => {
178                    entry.get_mut().extend(value);
179                }
180                BTreeEntry::Vacant(entry) => {
181                    entry.insert(value);
182                }
183            }
184        }
185
186        for (name, value) in other.unknown {
187            match self.unknown.entry(name) {
188                HashbrownEntry::Occupied(mut entry) => {
189                    entry.get_mut().extend(value);
190                }
191                HashbrownEntry::Vacant(entry) => {
192                    entry.insert(value);
193                }
194            }
195        }
196    }
197
198    /// Combine two [`Headers`], replacing any existing header values
199    pub fn insert_all(&mut self, other: Headers) {
200        for (name, value) in other.known {
201            self.known.insert(name, value);
202        }
203
204        for (name, value) in other.unknown {
205            self.unknown.insert(name, value);
206        }
207    }
208
209    /// Add a header value or header values into this header map. If a
210    /// header already exists with the same name, it will be
211    /// replaced. To combine, see [`Headers::append`]
212    pub fn insert(
213        &mut self,
214        name: impl Into<HeaderName<'static>>,
215        values: impl Into<HeaderValues>,
216    ) -> &mut Self {
217        self.entry(name).insert(values);
218        self
219    }
220
221    /// Add a header value or header values into this header map if
222    /// and only if there is not already a header with the same name.
223    ///
224    /// Identical to [`headers.entry(name).or_insert(default)`][Entry::or_insert]
225    pub fn try_insert(
226        &mut self,
227        name: impl Into<HeaderName<'static>>,
228        values: impl Into<HeaderValues>,
229    ) -> &mut Self {
230        self.entry(name).or_insert(values);
231        self
232    }
233
234    /// if a key does not exist already, execute the provided function and insert a value
235    ///
236    /// Identical to
237    /// [`headers.entry(name).or_insert_with(values)`][Entry::or_insert_with]
238    pub fn try_insert_with<V>(
239        &mut self,
240        name: impl Into<HeaderName<'static>>,
241        values: impl FnOnce() -> V,
242    ) -> &mut HeaderValues
243    where
244        V: Into<HeaderValues>,
245    {
246        self.entry(name).or_insert_with(values)
247    }
248
249    /// Return a view into the entry for this header name, whether or not it is populated.
250    ///
251    /// See also [`Entry`]
252    pub fn entry(&mut self, name: impl Into<HeaderName<'static>>) -> Entry<'_> {
253        match name.into().0 {
254            HeaderNameInner::KnownHeader(known) => match self.known.entry(known) {
255                BTreeEntry::Vacant(vacant) => {
256                    Entry::Vacant(VacantEntry(VacantEntryInner::Known(vacant)))
257                }
258                BTreeEntry::Occupied(occupied) => {
259                    Entry::Occupied(OccupiedEntry(OccupiedEntryInner::Known(occupied)))
260                }
261            },
262
263            HeaderNameInner::UnknownHeader(unknown) => match self.unknown.entry(unknown) {
264                HashbrownEntry::Occupied(occupied) => {
265                    Entry::Occupied(OccupiedEntry(OccupiedEntryInner::Unknown(occupied)))
266                }
267
268                HashbrownEntry::Vacant(vacant) => {
269                    Entry::Vacant(VacantEntry(VacantEntryInner::Unknown(vacant)))
270                }
271            },
272        }
273    }
274
275    /// Retrieves a &str header value if there is at least one header
276    /// in the map with this name. If there are several headers with
277    /// the same name, this follows the behavior defined at
278    /// [`HeaderValues::one`]. Returns None if there is no header with
279    /// the provided header name.
280    pub fn get_str<'a>(&self, name: impl Into<HeaderName<'a>>) -> Option<&str> {
281        self.get_values(name).and_then(HeaderValues::as_str)
282    }
283
284    /// Retrieves a singular header value from this header map. If there are several headers with
285    /// the same name, this follows the behavior defined at [`HeaderValues::one`]. Returns None if
286    /// there is no header with the provided header name
287    pub fn get<'a>(&self, name: impl Into<HeaderName<'a>>) -> Option<&HeaderValue> {
288        self.get_values(name).and_then(HeaderValues::one)
289    }
290
291    /// Takes all headers with the provided header name out of this header map and returns
292    /// them. Returns None if the header did not have an entry in this map.
293    pub fn remove<'a>(&mut self, name: impl Into<HeaderName<'a>>) -> Option<HeaderValues> {
294        match name.into().0 {
295            HeaderNameInner::KnownHeader(known) => self.known.remove(&known),
296            HeaderNameInner::UnknownHeader(unknown) => self.unknown.remove(&&unknown),
297        }
298    }
299
300    /// Retrieves a reference to all header values with the provided
301    /// header name. If you expect there to be only one value, use
302    /// [`Headers::get`].
303    pub fn get_values<'a>(&self, name: impl Into<HeaderName<'a>>) -> Option<&HeaderValues> {
304        match name.into().0 {
305            HeaderNameInner::KnownHeader(known) => self.known.get(&known),
306            HeaderNameInner::UnknownHeader(unknown) => self.unknown.get(&&unknown),
307        }
308    }
309
310    /// Predicate function to check whether this header map contains
311    /// the provided header name. If you are using this to
312    /// conditionally insert a value, consider using
313    /// [`Headers::try_insert`] instead.
314    pub fn has_header<'a>(&self, name: impl Into<HeaderName<'a>>) -> bool {
315        match name.into().0 {
316            HeaderNameInner::KnownHeader(known) => self.known.contains_key(&known),
317            HeaderNameInner::UnknownHeader(unknown) => self.unknown.contains_key(&unknown),
318        }
319    }
320
321    /// Convenience function to check whether the value contained in
322    /// this header map for the provided name is
323    /// ascii-case-insensitively equal to the provided comparison
324    /// &str. Returns false if there is no value for the name
325    pub fn eq_ignore_ascii_case<'a>(
326        &'a self,
327        name: impl Into<HeaderName<'a>>,
328        needle: &str,
329    ) -> bool {
330        self.get_str(name)
331            .is_some_and(|v| v.eq_ignore_ascii_case(needle))
332    }
333
334    /// Chainable method to insert a header
335    pub fn with_inserted_header(
336        mut self,
337        name: impl Into<HeaderName<'static>>,
338        values: impl Into<HeaderValues>,
339    ) -> Self {
340        self.insert(name, values);
341        self
342    }
343
344    /// Chainable method to append a header
345    pub fn with_appended_header(
346        mut self,
347        name: impl Into<HeaderName<'static>>,
348        values: impl Into<HeaderValues>,
349    ) -> Self {
350        self.append(name, values);
351        self
352    }
353
354    /// Chainable method to remove a header
355    pub fn without_header<'a>(mut self, name: impl Into<HeaderName<'a>>) -> Self {
356        self.remove(name);
357        self
358    }
359
360    /// Chainable method to remove multiple headers by name
361    pub fn without_headers<'a, I, H>(mut self, names: I) -> Self
362    where
363        I: IntoIterator<Item = H>,
364        H: Into<HeaderName<'a>>,
365    {
366        self.remove_all(names);
367        self
368    }
369
370    /// remove multiple headers by name
371    pub fn remove_all<'a, I, H>(&mut self, names: I)
372    where
373        I: IntoIterator<Item = H>,
374        H: Into<HeaderName<'a>>,
375    {
376        for name in names {
377            self.remove(name);
378        }
379    }
380}
381
382impl<HN, HV> Extend<(HN, HV)> for Headers
383where
384    HN: Into<HeaderName<'static>>,
385    HV: Into<HeaderValues>,
386{
387    fn extend<T: IntoIterator<Item = (HN, HV)>>(&mut self, iter: T) {
388        for (name, values) in iter {
389            self.append(name, values);
390        }
391    }
392}
393
394impl<HN, HV> FromIterator<(HN, HV)> for Headers
395where
396    HN: Into<HeaderName<'static>>,
397    HV: Into<HeaderValues>,
398{
399    fn from_iter<T: IntoIterator<Item = (HN, HV)>>(iter: T) -> Self {
400        let iter = iter.into_iter();
401        let mut headers = Self::new();
402        for (name, values) in iter {
403            headers.append(name, values);
404        }
405
406        headers
407    }
408}
409
410impl<'a> IntoIterator for &'a Headers {
411    type IntoIter = Iter<'a>;
412    type Item = (HeaderName<'a>, &'a HeaderValues);
413
414    fn into_iter(self) -> Self::IntoIter {
415        self.into()
416    }
417}
418
419/// An owned iterator for Headers
420#[derive(Debug)]
421pub struct IntoIter {
422    known: btree_map::IntoIter<KnownHeaderName, HeaderValues>,
423    unknown: hash_map::IntoIter<UnknownHeaderName<'static>, HeaderValues>,
424}
425
426impl Iterator for IntoIter {
427    type Item = (HeaderName<'static>, HeaderValues);
428
429    fn next(&mut self) -> Option<Self::Item> {
430        let IntoIter { known, unknown } = self;
431        known
432            .next()
433            .map(|(k, v)| (HeaderName::from(k), v))
434            .or_else(|| unknown.next().map(|(k, v)| (HeaderName::from(k), v)))
435    }
436}
437
438impl From<Headers> for IntoIter {
439    fn from(value: Headers) -> Self {
440        Self {
441            known: value.known.into_iter(),
442            unknown: value.unknown.into_iter(),
443        }
444    }
445}
446
447/// A borrowed iterator for Headers
448#[derive(Debug)]
449pub struct Iter<'a> {
450    known: btree_map::Iter<'a, KnownHeaderName, HeaderValues>,
451    unknown: hash_map::Iter<'a, UnknownHeaderName<'static>, HeaderValues>,
452}
453
454impl<'a> From<&'a Headers> for Iter<'a> {
455    fn from(value: &'a Headers) -> Self {
456        Iter {
457            known: value.known.iter(),
458            unknown: value.unknown.iter(),
459        }
460    }
461}
462
463impl<'a> Iterator for Iter<'a> {
464    type Item = (HeaderName<'a>, &'a HeaderValues);
465
466    fn next(&mut self) -> Option<Self::Item> {
467        let Iter { known, unknown } = self;
468        known
469            .next()
470            .map(|(k, v)| (HeaderName::from(*k), v))
471            .or_else(|| unknown.next().map(|(k, v)| (HeaderName::from(&**k), v)))
472    }
473}
474
475impl IntoIterator for Headers {
476    type IntoIter = IntoIter;
477    type Item = (HeaderName<'static>, HeaderValues);
478
479    fn into_iter(self) -> Self::IntoIter {
480        self.into()
481    }
482}