rama_http_headers/forwarded/
std.rs

1use std::ops::{Deref, DerefMut};
2
3use rama_http_types::{HeaderName, HeaderValue, header::FORWARDED};
4use rama_net::forwarded::ForwardedElement;
5
6use crate::{Error, Header};
7
8use super::ForwardHeader;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11/// typed [`Header`] wrapper for [`rama_net::forwarded::Forwarded`];
12pub struct Forwarded(rama_net::forwarded::Forwarded);
13
14impl Deref for Forwarded {
15    type Target = rama_net::forwarded::Forwarded;
16
17    fn deref(&self) -> &Self::Target {
18        &self.0
19    }
20}
21
22impl DerefMut for Forwarded {
23    fn deref_mut(&mut self) -> &mut Self::Target {
24        &mut self.0
25    }
26}
27
28impl Forwarded {
29    #[inline]
30    /// Return the inner [`Forwarded`].
31    ///
32    /// [`Forwarded`]: rama_net::forwarded::Forwarded
33    pub fn into_inner(self) -> rama_net::forwarded::Forwarded {
34        self.0
35    }
36}
37
38impl From<rama_net::forwarded::Forwarded> for Forwarded {
39    fn from(value: rama_net::forwarded::Forwarded) -> Self {
40        Self(value)
41    }
42}
43
44impl From<Forwarded> for rama_net::forwarded::Forwarded {
45    fn from(value: Forwarded) -> Self {
46        value.0
47    }
48}
49
50impl Header for Forwarded {
51    fn name() -> &'static HeaderName {
52        &FORWARDED
53    }
54
55    fn decode<'i, I>(values: &mut I) -> Result<Self, Error>
56    where
57        Self: Sized,
58        I: Iterator<Item = &'i HeaderValue>,
59    {
60        let first_header = values.next().ok_or_else(Error::invalid)?;
61
62        let mut forwarded: rama_net::forwarded::Forwarded = match first_header.as_bytes().try_into()
63        {
64            Ok(f) => f,
65            Err(err) => {
66                tracing::trace!(err = %err, "failed to turn header into Forwarded extension");
67                return Err(Error::invalid());
68            }
69        };
70
71        for header in values {
72            let other: rama_net::forwarded::Forwarded = match header.as_bytes().try_into() {
73                Ok(f) => f,
74                Err(err) => {
75                    tracing::trace!(err = %err, "failed to turn header into Forwarded extension");
76                    return Err(Error::invalid());
77                }
78            };
79            forwarded.extend(other);
80        }
81
82        Ok(Self(forwarded))
83    }
84
85    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
86        let s = self.0.to_string();
87
88        let value = HeaderValue::from_str(&s)
89            .expect("Forwarded extension should always result in a valid header value");
90
91        values.extend(std::iter::once(value));
92    }
93}
94
95impl IntoIterator for Forwarded {
96    type Item = <rama_net::forwarded::Forwarded as IntoIterator>::Item;
97    type IntoIter = <rama_net::forwarded::Forwarded as IntoIterator>::IntoIter;
98
99    #[inline]
100    fn into_iter(self) -> Self::IntoIter {
101        self.0.into_iter()
102    }
103}
104
105impl ForwardHeader for Forwarded {
106    fn try_from_forwarded<'a, I>(input: I) -> Option<Self>
107    where
108        I: IntoIterator<Item = &'a ForwardedElement>,
109    {
110        let mut it = input.into_iter();
111        let mut forwarded = rama_net::forwarded::Forwarded::new(it.next()?.clone());
112        forwarded.extend(it.cloned());
113        Some(Self(forwarded))
114    }
115}