rama_http_headers/forwarded/
std.rs1use 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))]
14pub 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 #[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}