Skip to main content

trillium_http/
headers.rs

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