rama_http/headers/forwarded/
x_forwarded_proto.rsuse crate::headers::{self, Header};
use crate::{HeaderName, HeaderValue};
use rama_net::forwarded::{ForwardedElement, ForwardedProtocol};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct XForwardedProto(ForwardedProtocol);
impl Header for XForwardedProto {
fn name() -> &'static HeaderName {
&crate::header::X_FORWARDED_PROTO
}
fn decode<'i, I: Iterator<Item = &'i HeaderValue>>(
values: &mut I,
) -> Result<Self, headers::Error> {
Ok(XForwardedProto(
values
.next()
.and_then(|value| value.to_str().ok().and_then(|s| s.parse().ok()))
.ok_or_else(crate::headers::Error::invalid)?,
))
}
fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
let s = self.0.to_string();
values.extend(Some(HeaderValue::from_str(&s).unwrap()))
}
}
impl XForwardedProto {
pub fn protocol(&self) -> &ForwardedProtocol {
&self.0
}
pub fn into_protocol(self) -> ForwardedProtocol {
self.0
}
}
impl IntoIterator for XForwardedProto {
type Item = ForwardedElement;
type IntoIter = XForwardedProtoIterator;
fn into_iter(self) -> Self::IntoIter {
XForwardedProtoIterator(Some(self.0))
}
}
impl super::ForwardHeader for XForwardedProto {
fn try_from_forwarded<'a, I>(input: I) -> Option<Self>
where
I: IntoIterator<Item = &'a ForwardedElement>,
{
let proto = input.into_iter().next()?.ref_forwarded_proto()?;
Some(XForwardedProto(proto))
}
}
#[derive(Debug, Clone)]
pub struct XForwardedProtoIterator(Option<ForwardedProtocol>);
impl Iterator for XForwardedProtoIterator {
type Item = ForwardedElement;
fn next(&mut self) -> Option<Self::Item> {
self.0.take().map(ForwardedElement::forwarded_proto)
}
}
#[cfg(test)]
mod tests {
use super::*;
use rama_http_types::HeaderValue;
macro_rules! test_header {
($name: ident, $input: expr, $expected: expr) => {
#[test]
fn $name() {
assert_eq!(
XForwardedProto::decode(
&mut $input
.into_iter()
.map(|s| HeaderValue::from_bytes(s.as_bytes()).unwrap())
.collect::<Vec<_>>()
.iter()
)
.ok(),
$expected,
);
}
};
}
test_header!(
test1,
vec!["https"],
Some(XForwardedProto(ForwardedProtocol::HTTPS))
);
test_header!(
test2,
vec!["https", "http"],
Some(XForwardedProto(ForwardedProtocol::HTTPS))
);
test_header!(
test3,
vec!["http"],
Some(XForwardedProto(ForwardedProtocol::HTTP))
);
#[test]
fn test_x_forwarded_proto_symmetric_encoder() {
for input in [ForwardedProtocol::HTTP, ForwardedProtocol::HTTPS] {
let input = XForwardedProto(input);
let mut values = Vec::new();
input.encode(&mut values);
let output = XForwardedProto::decode(&mut values.iter()).unwrap();
assert_eq!(input, output);
}
}
}