Skip to main content

rama_http_headers/forwarded/
std.rs

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