use HeaderValue;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ReferrerPolicy(Policy);
derive_header! {
ReferrerPolicy(_),
name: REFERRER_POLICY
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
enum Policy {
NoReferrer,
NoReferrerWhenDowngrade,
SameOrigin,
Origin,
OriginWhenCrossOrigin,
UnsafeUrl,
StrictOrigin,
StrictOriginWhenCrossOrigin,
}
impl ReferrerPolicy {
pub const NO_REFERRER: Self = ReferrerPolicy(Policy::NoReferrer);
pub const NO_REFERRER_WHEN_DOWNGRADE: Self = ReferrerPolicy(Policy::NoReferrerWhenDowngrade);
pub const SAME_ORIGIN: Self = ReferrerPolicy(Policy::SameOrigin);
pub const ORIGIN: Self = ReferrerPolicy(Policy::Origin);
pub const ORIGIN_WHEN_CROSS_ORIGIN: Self = ReferrerPolicy(Policy::OriginWhenCrossOrigin);
pub const UNSAFE_URL: Self = ReferrerPolicy(Policy::UnsafeUrl);
pub const STRICT_ORIGIN: Self = ReferrerPolicy(Policy::StrictOrigin);
pub const STRICT_ORIGIN_WHEN_CROSS_ORIGIN: Self =
ReferrerPolicy(Policy::StrictOriginWhenCrossOrigin);
}
impl ::util::TryFromValues for Policy {
fn try_from_values<'i, I>(values: &mut I) -> Result<Self, ::Error>
where
I: Iterator<Item = &'i HeaderValue>,
{
let mut known = None;
for s in csv(values) {
known = Some(match s {
"no-referrer" | "never" => Policy::NoReferrer,
"no-referrer-when-downgrade" | "default" => Policy::NoReferrerWhenDowngrade,
"same-origin" => Policy::SameOrigin,
"origin" => Policy::Origin,
"origin-when-cross-origin" => Policy::OriginWhenCrossOrigin,
"strict-origin" => Policy::StrictOrigin,
"strict-origin-when-cross-origin" => Policy::StrictOriginWhenCrossOrigin,
"unsafe-url" | "always" => Policy::UnsafeUrl,
_ => continue,
});
}
known.ok_or_else(::Error::invalid)
}
}
impl<'a> From<&'a Policy> for HeaderValue {
fn from(policy: &'a Policy) -> HeaderValue {
HeaderValue::from_static(match *policy {
Policy::NoReferrer => "no-referrer",
Policy::NoReferrerWhenDowngrade => "no-referrer-when-downgrade",
Policy::SameOrigin => "same-origin",
Policy::Origin => "origin",
Policy::OriginWhenCrossOrigin => "origin-when-cross-origin",
Policy::StrictOrigin => "strict-origin",
Policy::StrictOriginWhenCrossOrigin => "strict-origin-when-cross-origin",
Policy::UnsafeUrl => "unsafe-url",
})
}
}
fn csv<'i, I>(values: I) -> impl Iterator<Item = &'i str>
where
I: Iterator<Item = &'i HeaderValue>,
{
values.flat_map(|value| {
value.to_str().into_iter().flat_map(|string| {
string.split(',').filter_map(|x| match x.trim() {
"" => None,
y => Some(y),
})
})
})
}
#[cfg(test)]
mod tests {
use super::super::test_decode;
use super::ReferrerPolicy;
#[test]
fn decode_as_last_policy() {
assert_eq!(
test_decode::<ReferrerPolicy>(&["same-origin, origin"]),
Some(ReferrerPolicy::ORIGIN),
);
assert_eq!(
test_decode::<ReferrerPolicy>(&["origin", "same-origin"]),
Some(ReferrerPolicy::SAME_ORIGIN),
);
}
#[test]
fn decode_as_last_known() {
assert_eq!(
test_decode::<ReferrerPolicy>(&["origin, nope, nope, nope"]),
Some(ReferrerPolicy::ORIGIN),
);
assert_eq!(
test_decode::<ReferrerPolicy>(&["nope, origin, nope, nope"]),
Some(ReferrerPolicy::ORIGIN),
);
assert_eq!(
test_decode::<ReferrerPolicy>(&["nope, origin", "nope, nope"]),
Some(ReferrerPolicy::ORIGIN),
);
assert_eq!(
test_decode::<ReferrerPolicy>(&["nope", "origin", "nope, nope"]),
Some(ReferrerPolicy::ORIGIN),
);
}
#[test]
fn decode_unknown() {
assert_eq!(test_decode::<ReferrerPolicy>(&["nope"]), None,);
}
#[test]
fn matching() {
let rp = ReferrerPolicy::ORIGIN;
match rp {
ReferrerPolicy::ORIGIN => (),
_ => panic!("matched wrong"),
}
}
}