1use core::{marker, fmt};
4use core::net::IpAddr;
5
6const FORWARDED_SEP: char = ',';
10const ENTRY_SEP: char = ';';
11const PAIR_SEP: char = '=';
12
13#[derive(Clone, Copy, PartialEq, Eq, Debug)]
14pub enum ForwardedNode<'a> {
18 Ip(IpAddr),
20 Name(&'a str),
22 Unknown,
24}
25
26impl<'a> ForwardedNode<'a> {
27 #[inline(always)]
28 fn parse_name(name: &'a str) -> Self {
29 if let Ok(name) = name.parse() {
30 return Self::Ip(name);
31 } else {
32 return Self::Name(name)
33 }
34 }
35
36 #[inline(always)]
37 pub const fn ip(&self) -> Option<IpAddr> {
39 match self {
40 Self::Ip(ip) => Some(*ip),
41 _ => None
42 }
43 }
44
45 #[inline]
46 pub fn parse_x_node(mut node: &'a str) -> Self {
48 node = node.trim();
49 match node.parse() {
50 Ok(ip) => ForwardedNode::Ip(ip),
51 Err(_) => ForwardedNode::Name(node)
52 }
53 }
54
55 pub fn parse_node(mut node: &'a str) -> Self {
57 node = node.trim_matches('"');
58 if node.eq_ignore_ascii_case("unknown") {
59 return Self::Unknown;
60 }
61
62 if let Some(mut ipv6) = node.strip_prefix('[') {
63 if let Some(end_addr_idx) = ipv6.find(']') {
64 ipv6 = &ipv6[..end_addr_idx];
65 return Self::parse_name(ipv6);
66 } else {
67 return Self::Name(ipv6);
68 }
69 }
70
71 let mut node = node.rsplit(':');
72 let port_or_ip = node.next().unwrap();
73 let ip = if let Some(ip) = node.next() {
74 ip
75 } else {
76 port_or_ip
77 };
78
79 ForwardedNode::parse_name(ip)
80 }
81}
82
83impl fmt::Display for ForwardedNode<'_> {
84 #[inline(always)]
85 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
86 match self {
87 Self::Ip(ip) => fmt::Display::fmt(&ip, fmt),
88 Self::Name(ip) => fmt.write_str(&ip),
89 Self::Unknown => fmt.write_str("-"),
90 }
91 }
92}
93
94#[derive(Copy, Clone, PartialEq, Eq, Debug)]
95pub enum ForwardedValue<'a> {
97 By(ForwardedNode<'a>),
101 For(ForwardedNode<'a>),
105 Host(&'a str),
107 Protocol(&'a str)
111}
112
113pub struct ForwardedEntryIter<'a> {
115 components: core::str::Split<'a, char>,
116}
117
118impl<'a> ForwardedEntryIter<'a> {
119 pub fn parse_entry(value: &'a str) -> Self {
127 Self {
128 components: value.split(ENTRY_SEP)
129 }
130 }
131}
132
133impl<'a> Iterator for ForwardedEntryIter<'a> {
134 type Item = ForwardedValue<'a>;
135
136 fn next(&mut self) -> Option<Self::Item> {
137 while let Some(value) = self.components.next() {
138 let mut pairs = value.splitn(2, PAIR_SEP);
139 let key = pairs.next().unwrap();
140 if key.eq_ignore_ascii_case("for") {
141 if let Some(node) = pairs.next() {
142 return Some(ForwardedValue::For(ForwardedNode::parse_node(node)))
143 }
144 } else if key.eq_ignore_ascii_case("by") {
145 if let Some(node) = pairs.next() {
146 return Some(ForwardedValue::By(ForwardedNode::parse_node(node)))
147 }
148 } else if key.eq_ignore_ascii_case("proto") {
149 if let Some(proto) = pairs.next() {
150 return Some(ForwardedValue::Protocol(proto))
151 }
152 } else if key.eq_ignore_ascii_case("host") {
153 if let Some(host) = pairs.next() {
154 return Some(ForwardedValue::Host(host))
155 }
156 }
157 }
158
159 None
160 }
161}
162
163pub struct ForwardedIter<'a, I> {
165 components: I,
166 _lifetime: marker::PhantomData<&'a I>,
167}
168
169impl<'a, I: Iterator<Item = &'a str> + 'a> Iterator for ForwardedIter<'a, I> {
170 type Item = ForwardedEntryIter<'a>;
171
172 #[inline]
173 fn next(&mut self) -> Option<Self::Item> {
174 self.components.next().map(ForwardedEntryIter::parse_entry)
175 }
176}
177
178pub struct ForwardedForIter<'a, I> {
184 components: I,
185 _lifetime: marker::PhantomData<&'a I>,
186}
187
188impl<'a, I: Iterator<Item = &'a str> + 'a> Iterator for ForwardedForIter<'a, I> {
189 type Item = ForwardedNode<'a>;
190
191 #[inline]
192 fn next(&mut self) -> Option<Self::Item> {
193 while let Some(value) = self.components.next() {
194 let mut pairs = value.splitn(2, PAIR_SEP);
195 let key = pairs.next().unwrap();
196 if key.eq_ignore_ascii_case("for") {
197 if let Some(node) = pairs.next() {
198 return Some(ForwardedNode::parse_node(node))
199 }
200 }
201 }
202
203 None
204 }
205}
206
207pub struct XForwardedForIter<'a, I> {
211 components: I,
212 _lifetime: marker::PhantomData<&'a I>,
213}
214
215impl<'a, I: Iterator<Item = &'a str> + 'a> Iterator for XForwardedForIter<'a, I> {
216 type Item = ForwardedNode<'a>;
217
218 #[inline]
219 fn next(&mut self) -> Option<Self::Item> {
220 self.components.next().map(ForwardedNode::parse_x_node)
221 }
222}
223
224#[inline(always)]
225pub fn parse_forwarded<'a>(value: &'a str) -> ForwardedIter<'a, impl Iterator<Item = &'a str>> {
233 ForwardedIter {
234 components: value.split(FORWARDED_SEP),
235 _lifetime: marker::PhantomData,
236 }
237}
238
239#[inline(always)]
240pub fn parse_forwarded_rev<'a>(value: &'a str) -> ForwardedIter<'a, impl Iterator<Item = &'a str>> {
242 ForwardedIter {
243 components: value.rsplit(FORWARDED_SEP),
244 _lifetime: marker::PhantomData,
245 }
246}
247
248#[inline(always)]
249pub fn parse_forwarded_for<'a>(value: &'a str) -> ForwardedForIter<'a, impl Iterator<Item = &'a str>> {
251 ForwardedForIter {
252 components: value.split([FORWARDED_SEP, ENTRY_SEP]),
253 _lifetime: marker::PhantomData,
254 }
255}
256
257#[inline(always)]
258pub fn parse_forwarded_for_rev<'a>(value: &'a str) -> ForwardedForIter<'a, impl Iterator<Item = &'a str>> {
260 ForwardedForIter {
261 components: value.rsplit([FORWARDED_SEP, ENTRY_SEP]),
262 _lifetime: marker::PhantomData,
263 }
264}
265
266#[inline(always)]
267pub fn parse_x_forwarded_for<'a>(value: &'a str) -> XForwardedForIter<'a, impl Iterator<Item = &'a str>> {
269 XForwardedForIter {
270 components: value.split(FORWARDED_SEP),
271 _lifetime: marker::PhantomData,
272 }
273}
274
275#[inline(always)]
276pub fn parse_x_forwarded_for_rev<'a>(value: &'a str) -> XForwardedForIter<'a, impl Iterator<Item = &'a str>> {
278 XForwardedForIter {
279 components: value.rsplit(FORWARDED_SEP),
280 _lifetime: marker::PhantomData,
281 }
282}