ntex_http/
map.rs

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