Skip to main content

ntex_http/
map.rs

1use std::collections::{self, VecDeque, hash_map, hash_map::Entry};
2use std::fmt;
3
4use foldhash::fast::RandomState;
5
6use crate::{HeaderName, HeaderValue};
7
8type HashMap<K, V> = collections::HashMap<K, V, RandomState>;
9
10/// Combines two different futures, streams, or sinks having the same associated types into a single
11/// type.
12#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
13pub enum Either<A, B> {
14    /// First branch of the type
15    Left(A),
16    /// Second branch of the type
17    Right(B),
18}
19
20/// A set of HTTP headers
21///
22/// `HeaderMap` is an multimap of [`HeaderName`] to values.
23///
24/// [`HeaderName`]: struct.HeaderName.html
25#[derive(Clone, PartialEq, Eq)]
26pub struct HeaderMap {
27    pub(crate) inner: HashMap<HeaderName, Value>,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub enum Value {
32    One(HeaderValue),
33    Multi(VecDeque<HeaderValue>),
34}
35
36impl Value {
37    fn get(&self) -> &HeaderValue {
38        match self {
39            Value::One(val) => val,
40            Value::Multi(val) => &val[0],
41        }
42    }
43
44    fn get_mut(&mut self) -> &mut HeaderValue {
45        match self {
46            Value::One(val) => val,
47            Value::Multi(val) => &mut val[0],
48        }
49    }
50
51    pub(crate) fn append(&mut self, val: HeaderValue) {
52        match self {
53            Value::One(prev_val) => {
54                let prev_val = std::mem::replace(prev_val, val);
55                let mut val = VecDeque::new();
56                val.push_back(prev_val);
57                let data = std::mem::replace(self, Value::Multi(val));
58                match data {
59                    Value::One(val) => self.append(val),
60                    Value::Multi(_) => unreachable!(),
61                }
62            }
63            Value::Multi(vec) => vec.push_back(val),
64        }
65    }
66}
67
68#[derive(Debug)]
69pub struct ValueIntoIter {
70    value: Value,
71}
72
73impl Iterator for ValueIntoIter {
74    type Item = HeaderValue;
75
76    fn next(&mut self) -> Option<Self::Item> {
77        match &mut self.value {
78            Value::One(_) => {
79                let val = std::mem::replace(
80                    &mut self.value,
81                    Value::Multi(VecDeque::with_capacity(0)),
82                );
83                match val {
84                    Value::One(val) => Some(val),
85                    Value::Multi(_) => unreachable!(),
86                }
87            }
88            Value::Multi(vec) => vec.pop_front(),
89        }
90    }
91
92    fn size_hint(&self) -> (usize, Option<usize>) {
93        match self.value {
94            Value::One(_) => (1, None),
95            Value::Multi(ref v) => v.iter().size_hint(),
96        }
97    }
98}
99
100impl IntoIterator for Value {
101    type Item = HeaderValue;
102    type IntoIter = ValueIntoIter;
103
104    #[inline]
105    fn into_iter(self) -> Self::IntoIter {
106        ValueIntoIter { value: self }
107    }
108}
109
110impl Extend<HeaderValue> for Value {
111    #[inline]
112    fn extend<T>(&mut self, iter: T)
113    where
114        T: IntoIterator<Item = HeaderValue>,
115    {
116        for h in iter {
117            self.append(h);
118        }
119    }
120}
121
122impl From<HeaderValue> for Value {
123    #[inline]
124    fn from(hdr: HeaderValue) -> Value {
125        Value::One(hdr)
126    }
127}
128
129impl<'a> From<&'a HeaderValue> for Value {
130    #[inline]
131    fn from(hdr: &'a HeaderValue) -> Value {
132        Value::One(hdr.clone())
133    }
134}
135
136impl Default for HeaderMap {
137    #[inline]
138    fn default() -> Self {
139        Self::new()
140    }
141}
142
143impl HeaderMap {
144    /// Create an empty `HeaderMap`.
145    ///
146    /// The map will be created without any capacity. This function will not
147    /// allocate.
148    pub fn new() -> Self {
149        HeaderMap {
150            inner: HashMap::default(),
151        }
152    }
153
154    /// Create an empty `HeaderMap` with the specified capacity.
155    ///
156    /// The returned map will allocate internal storage in order to hold about
157    /// `capacity` elements without reallocating. However, this is a "best
158    /// effort" as there are usage patterns that could cause additional
159    /// allocations before `capacity` headers are stored in the map.
160    ///
161    /// More capacity than requested may be allocated.
162    pub fn with_capacity(capacity: usize) -> HeaderMap {
163        HeaderMap {
164            inner: HashMap::with_capacity_and_hasher(capacity, RandomState::default()),
165        }
166    }
167
168    /// Returns the number of keys stored in the map.
169    ///
170    /// This number could be be less than or equal to actual headers stored in
171    /// the map.
172    pub fn len(&self) -> usize {
173        self.inner.len()
174    }
175
176    /// Returns true if the map contains no elements.
177    pub fn is_empty(&self) -> bool {
178        self.inner.len() == 0
179    }
180
181    /// Clears the map, removing all key-value pairs. Keeps the allocated memory
182    /// for reuse.
183    pub fn clear(&mut self) {
184        self.inner.clear();
185    }
186
187    /// Returns the number of headers the map can hold without reallocating.
188    ///
189    /// This number is an approximation as certain usage patterns could cause
190    /// additional allocations before the returned capacity is filled.
191    pub fn capacity(&self) -> usize {
192        self.inner.capacity()
193    }
194
195    /// Reserves capacity for at least `additional` more headers to be inserted
196    /// into the `HeaderMap`.
197    ///
198    /// The header map may reserve more space to avoid frequent reallocations.
199    /// Like with `with_capacity`, this will be a "best effort" to avoid
200    /// allocations until `additional` more headers are inserted. Certain usage
201    /// patterns could cause additional allocations before the number is
202    /// reached.
203    pub fn reserve(&mut self, additional: usize) {
204        self.inner.reserve(additional);
205    }
206
207    /// Returns a reference to the value associated with the key.
208    ///
209    /// If there are multiple values associated with the key, then the first one
210    /// is returned. Use `get_all` to get all values associated with a given
211    /// key. Returns `None` if there are no values associated with the key.
212    pub fn get<N: AsName>(&self, name: N) -> Option<&HeaderValue> {
213        self.get2(name).map(Value::get)
214    }
215
216    fn get2<N: AsName>(&self, name: N) -> Option<&Value> {
217        match name.as_name() {
218            Either::Left(name) => self.inner.get(name),
219            Either::Right(s) => {
220                if let Ok(name) = HeaderName::try_from(s) {
221                    self.inner.get(&name)
222                } else {
223                    None
224                }
225            }
226        }
227    }
228
229    /// Returns a view of all values associated with a key.
230    ///
231    /// The returned view does not incur any allocations and allows iterating
232    /// the values associated with the key.  See [`GetAll`] for more details.
233    /// Returns `None` if there are no values associated with the key.
234    ///
235    /// [`GetAll`]: struct.GetAll.html
236    pub fn get_all<N: AsName>(&self, name: N) -> GetAll<'_> {
237        GetAll {
238            idx: 0,
239            item: self.get2(name),
240        }
241    }
242
243    /// Returns a mutable reference to the value associated with the key.
244    ///
245    /// If there are multiple values associated with the key, then the first one
246    /// is returned. Use `entry` to get all values associated with a given
247    /// key. Returns `None` if there are no values associated with the key.
248    pub fn get_mut<N: AsName>(&mut self, name: N) -> Option<&mut HeaderValue> {
249        match name.as_name() {
250            Either::Left(name) => self.inner.get_mut(name).map(Value::get_mut),
251            Either::Right(s) => {
252                if let Ok(name) = HeaderName::try_from(s) {
253                    self.inner.get_mut(&name).map(Value::get_mut)
254                } else {
255                    None
256                }
257            }
258        }
259    }
260
261    /// Returns true if the map contains a value for the specified key.
262    pub fn contains_key<N: AsName>(&self, key: N) -> bool {
263        match key.as_name() {
264            Either::Left(name) => self.inner.contains_key(name),
265            Either::Right(s) => {
266                if let Ok(name) = HeaderName::try_from(s) {
267                    self.inner.contains_key(&name)
268                } else {
269                    false
270                }
271            }
272        }
273    }
274
275    /// An iterator visiting all key-value pairs.
276    ///
277    /// The iteration order is arbitrary, but consistent across platforms for
278    /// the same crate version. Each key will be yielded once per associated
279    /// value. So, if a key has 3 associated values, it will be yielded 3 times.
280    pub fn iter(&self) -> Iter<'_> {
281        Iter::new(self.inner.iter())
282    }
283
284    #[doc(hidden)]
285    pub fn iter_inner(&self) -> hash_map::Iter<'_, HeaderName, Value> {
286        self.inner.iter()
287    }
288
289    /// An iterator visiting all keys.
290    ///
291    /// The iteration order is arbitrary, but consistent across platforms for
292    /// the same crate version. Each key will be yielded only once even if it
293    /// has multiple associated values.
294    pub fn keys(&self) -> Keys<'_> {
295        Keys(self.inner.keys())
296    }
297
298    /// Inserts a key-value pair into the map.
299    ///
300    /// If the map did not previously have this key present, then `None` is
301    /// returned.
302    ///
303    /// If the map did have this key present, the new value is associated with
304    /// the key and all previous values are removed. **Note** that only a single
305    /// one of the previous values is returned. If there are multiple values
306    /// that have been previously associated with the key, then the first one is
307    /// returned. See `insert_mult` on `OccupiedEntry` for an API that returns
308    /// all values.
309    ///
310    /// The key is not updated, though; this matters for types that can be `==`
311    /// without being identical.
312    pub fn insert(&mut self, key: HeaderName, val: HeaderValue) {
313        let _ = self.inner.insert(key, Value::One(val));
314    }
315
316    /// Inserts a key-value pair into the map.
317    ///
318    /// If the map did not previously have this key present, then `false` is
319    /// returned.
320    ///
321    /// If the map did have this key present, the new value is pushed to the end
322    /// of the list of values currently associated with the key. The key is not
323    /// updated, though; this matters for types that can be `==` without being
324    /// identical.
325    pub fn append(&mut self, key: HeaderName, value: HeaderValue) {
326        match self.inner.entry(key) {
327            Entry::Occupied(mut entry) => entry.get_mut().append(value),
328            Entry::Vacant(entry) => {
329                entry.insert(Value::One(value));
330            }
331        }
332    }
333
334    /// Removes all headers for a particular header name from the map.
335    pub fn remove<N: AsName>(&mut self, key: N) {
336        match key.as_name() {
337            Either::Left(name) => {
338                let _ = self.inner.remove(name);
339            }
340            Either::Right(s) => {
341                if let Ok(name) = HeaderName::try_from(s) {
342                    let _ = self.inner.remove(&name);
343                }
344            }
345        }
346    }
347}
348
349#[doc(hidden)]
350pub trait AsName {
351    fn as_name(&self) -> Either<&HeaderName, &str>;
352}
353
354impl AsName for HeaderName {
355    fn as_name(&self) -> Either<&HeaderName, &str> {
356        Either::Left(self)
357    }
358}
359
360impl AsName for &HeaderName {
361    fn as_name(&self) -> Either<&HeaderName, &str> {
362        Either::Left(self)
363    }
364}
365
366impl AsName for &str {
367    fn as_name(&self) -> Either<&HeaderName, &str> {
368        Either::Right(self)
369    }
370}
371
372impl AsName for String {
373    fn as_name(&self) -> Either<&HeaderName, &str> {
374        Either::Right(self.as_str())
375    }
376}
377
378impl AsName for &String {
379    fn as_name(&self) -> Either<&HeaderName, &str> {
380        Either::Right(self.as_str())
381    }
382}
383
384impl<N: std::fmt::Display, V> FromIterator<(N, V)> for HeaderMap
385where
386    HeaderName: TryFrom<N>,
387    Value: TryFrom<V>,
388    V: std::fmt::Debug,
389{
390    #[inline]
391    #[allow(clippy::mutable_key_type)]
392    fn from_iter<T: IntoIterator<Item = (N, V)>>(iter: T) -> Self {
393        let map = iter
394            .into_iter()
395            .filter_map(|(n, v)| {
396                let name = format!("{n}");
397                match (HeaderName::try_from(n), Value::try_from(v)) {
398                    (Ok(n), Ok(v)) => Some((n, v)),
399                    (Ok(n), Err(_)) => {
400                        log::warn!("failed to parse `{n}` header value");
401                        None
402                    }
403                    (Err(_), Ok(_)) => {
404                        log::warn!("invalid HTTP header name: {name}");
405                        None
406                    }
407                    (Err(_), Err(_)) => {
408                        log::warn!("invalid HTTP header name `{name}` and value");
409                        None
410                    }
411                }
412            })
413            .fold(HashMap::default(), |mut map: HashMap<_, Value>, (n, v)| {
414                match map.entry(n) {
415                    Entry::Occupied(mut oc) => oc.get_mut().extend(v),
416                    Entry::Vacant(va) => {
417                        let _ = va.insert(v);
418                    }
419                }
420                map
421            });
422        HeaderMap { inner: map }
423    }
424}
425
426impl FromIterator<HeaderValue> for Value {
427    fn from_iter<T: IntoIterator<Item = HeaderValue>>(iter: T) -> Self {
428        let mut iter = iter.into_iter();
429        let value = iter.next().map(Value::One);
430        let mut value = match value {
431            Some(v) => v,
432            _ => Value::One(HeaderValue::from_static("")),
433        };
434        value.extend(iter);
435        value
436    }
437}
438
439impl TryFrom<&str> for Value {
440    type Error = crate::header::InvalidHeaderValue;
441    fn try_from(value: &str) -> Result<Self, Self::Error> {
442        Ok(value
443            .split(',')
444            .filter(|v| !v.is_empty())
445            .map(str::trim)
446            .filter_map(|v| HeaderValue::from_str(v).ok())
447            .collect::<Value>())
448    }
449}
450
451#[derive(Debug)]
452pub struct GetAll<'a> {
453    idx: usize,
454    item: Option<&'a Value>,
455}
456
457impl<'a> Iterator for GetAll<'a> {
458    type Item = &'a HeaderValue;
459
460    #[inline]
461    fn next(&mut self) -> Option<&'a HeaderValue> {
462        if let Some(ref val) = self.item {
463            match val {
464                Value::One(val) => {
465                    self.item.take();
466                    Some(val)
467                }
468                Value::Multi(vec) => {
469                    if self.idx < vec.len() {
470                        let item = Some(&vec[self.idx]);
471                        self.idx += 1;
472                        item
473                    } else {
474                        self.item.take();
475                        None
476                    }
477                }
478            }
479        } else {
480            None
481        }
482    }
483}
484
485#[derive(Debug)]
486pub struct Keys<'a>(hash_map::Keys<'a, HeaderName, Value>);
487
488impl<'a> Iterator for Keys<'a> {
489    type Item = &'a HeaderName;
490
491    #[inline]
492    fn next(&mut self) -> Option<&'a HeaderName> {
493        self.0.next()
494    }
495}
496
497impl<'a> IntoIterator for &'a HeaderMap {
498    type Item = (&'a HeaderName, &'a HeaderValue);
499    type IntoIter = Iter<'a>;
500
501    fn into_iter(self) -> Self::IntoIter {
502        self.iter()
503    }
504}
505
506#[derive(Debug)]
507pub struct Iter<'a> {
508    idx: usize,
509    current: Option<(&'a HeaderName, &'a VecDeque<HeaderValue>)>,
510    inner: hash_map::Iter<'a, HeaderName, Value>,
511}
512
513impl<'a> Iter<'a> {
514    fn new(inner: hash_map::Iter<'a, HeaderName, Value>) -> Self {
515        Self {
516            inner,
517            idx: 0,
518            current: None,
519        }
520    }
521}
522
523impl<'a> Iterator for Iter<'a> {
524    type Item = (&'a HeaderName, &'a HeaderValue);
525
526    #[inline]
527    fn next(&mut self) -> Option<(&'a HeaderName, &'a HeaderValue)> {
528        if let Some(ref mut item) = self.current {
529            if self.idx < item.1.len() {
530                let item = (item.0, &item.1[self.idx]);
531                self.idx += 1;
532                return Some(item);
533            }
534            self.idx = 0;
535            self.current.take();
536        }
537        if let Some(item) = self.inner.next() {
538            match item.1 {
539                Value::One(value) => Some((item.0, value)),
540                Value::Multi(vec) => {
541                    self.current = Some((item.0, vec));
542                    self.next()
543                }
544            }
545        } else {
546            None
547        }
548    }
549}
550
551impl fmt::Debug for HeaderMap {
552    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553        let mut f = f.debug_map();
554
555        for (key, val) in &self.inner {
556            match val {
557                Value::One(val) => {
558                    let _ = f.entry(&key, &val);
559                }
560                Value::Multi(val) => {
561                    for v in val {
562                        f.entry(&key, &v);
563                    }
564                }
565            }
566        }
567        f.finish()
568    }
569}
570
571#[cfg(test)]
572mod tests {
573    use super::*;
574    use crate::header::{ACCEPT_ENCODING, CONTENT_TYPE};
575
576    #[test]
577    fn test_from_iter() {
578        let vec = vec![
579            ("Connection", "keep-alive"),
580            ("Accept", "text/html"),
581            (
582                "Accept",
583                "*/*, application/xhtml+xml, application/xml;q=0.9, image/webp,",
584            ),
585        ];
586        let map = HeaderMap::from_iter(vec);
587        assert_eq!(
588            map.get("Connection"),
589            Some(&HeaderValue::from_static("keep-alive"))
590        );
591        assert_eq!(
592            map.get_all("Accept").collect::<Vec<&HeaderValue>>(),
593            vec![
594                &HeaderValue::from_static("text/html"),
595                &HeaderValue::from_static("*/*"),
596                &HeaderValue::from_static("application/xhtml+xml"),
597                &HeaderValue::from_static("application/xml;q=0.9"),
598                &HeaderValue::from_static("image/webp"),
599            ]
600        );
601    }
602
603    #[test]
604    #[allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args)]
605    fn test_basics() {
606        let m = HeaderMap::default();
607        assert!(m.is_empty());
608        let mut m = HeaderMap::with_capacity(10);
609        assert!(m.is_empty());
610        assert!(m.capacity() >= 10);
611        m.reserve(20);
612        assert!(m.capacity() >= 20);
613
614        m.insert(CONTENT_TYPE, HeaderValue::from_static("text"));
615        assert!(m.contains_key(CONTENT_TYPE));
616        assert!(m.contains_key("content-type"));
617        assert!(m.contains_key("content-type".to_string()));
618        assert!(m.contains_key(&("content-type".to_string())));
619        assert_eq!(
620            *m.get_mut("content-type").unwrap(),
621            HeaderValue::from_static("text")
622        );
623        assert_eq!(
624            *m.get_mut(CONTENT_TYPE).unwrap(),
625            HeaderValue::from_static("text")
626        );
627        assert!(format!("{m:?}").contains("content-type"));
628
629        assert!(m.keys().any(|x| x == CONTENT_TYPE));
630        m.remove("content-type");
631        assert!(m.is_empty());
632    }
633
634    #[test]
635    fn test_append() {
636        let mut map = HeaderMap::new();
637
638        map.append(ACCEPT_ENCODING, HeaderValue::from_static("gzip"));
639        assert_eq!(
640            map.get_all(ACCEPT_ENCODING).collect::<Vec<_>>(),
641            vec![&HeaderValue::from_static("gzip"),]
642        );
643
644        map.append(ACCEPT_ENCODING, HeaderValue::from_static("br"));
645        map.append(ACCEPT_ENCODING, HeaderValue::from_static("deflate"));
646        assert_eq!(
647            map.get_all(ACCEPT_ENCODING).collect::<Vec<_>>(),
648            vec![
649                &HeaderValue::from_static("gzip"),
650                &HeaderValue::from_static("br"),
651                &HeaderValue::from_static("deflate"),
652            ]
653        );
654        assert_eq!(
655            map.get(ACCEPT_ENCODING),
656            Some(&HeaderValue::from_static("gzip"))
657        );
658        assert_eq!(
659            map.get_mut(ACCEPT_ENCODING),
660            Some(&mut HeaderValue::from_static("gzip"))
661        );
662
663        map.remove(ACCEPT_ENCODING);
664        assert_eq!(map.get(ACCEPT_ENCODING), None);
665    }
666
667    #[test]
668    fn test_from_http() {
669        let mut map = http::HeaderMap::new();
670        map.append(ACCEPT_ENCODING, http::HeaderValue::from_static("gzip"));
671
672        let map2 = HeaderMap::from(map);
673        assert_eq!(
674            map2.get(ACCEPT_ENCODING),
675            Some(&HeaderValue::from_static("gzip"))
676        );
677    }
678}