summaryrefslogtreecommitdiffstats
path: root/third_party/rust/headers/src/common/referrer_policy.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/headers/src/common/referrer_policy.rs')
-rw-r--r--third_party/rust/headers/src/common/referrer_policy.rs190
1 files changed, 190 insertions, 0 deletions
diff --git a/third_party/rust/headers/src/common/referrer_policy.rs b/third_party/rust/headers/src/common/referrer_policy.rs
new file mode 100644
index 0000000000..95bc36c056
--- /dev/null
+++ b/third_party/rust/headers/src/common/referrer_policy.rs
@@ -0,0 +1,190 @@
+use HeaderValue;
+
+/// `Referrer-Policy` header, part of
+/// [Referrer Policy](https://www.w3.org/TR/referrer-policy/#referrer-policy-header)
+///
+/// The `Referrer-Policy` HTTP header specifies the referrer
+/// policy that the user agent applies when determining what
+/// referrer information should be included with requests made,
+/// and with browsing contexts created from the context of the
+/// protected resource.
+///
+/// # ABNF
+///
+/// ```text
+/// Referrer-Policy: 1#policy-token
+/// policy-token = "no-referrer" / "no-referrer-when-downgrade"
+/// / "same-origin" / "origin"
+/// / "origin-when-cross-origin" / "unsafe-url"
+/// ```
+///
+/// # Example values
+///
+/// * `no-referrer`
+///
+/// # Example
+///
+/// ```
+/// # extern crate headers;
+/// use headers::ReferrerPolicy;
+///
+/// let rp = ReferrerPolicy::NO_REFERRER;
+/// ```
+#[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 {
+ /// `no-referrer`
+ pub const NO_REFERRER: Self = ReferrerPolicy(Policy::NoReferrer);
+
+ /// `no-referrer-when-downgrade`
+ pub const NO_REFERRER_WHEN_DOWNGRADE: Self = ReferrerPolicy(Policy::NoReferrerWhenDowngrade);
+
+ /// `same-origin`
+ pub const SAME_ORIGIN: Self = ReferrerPolicy(Policy::SameOrigin);
+
+ /// `origin`
+ pub const ORIGIN: Self = ReferrerPolicy(Policy::Origin);
+
+ /// `origin-when-cross-origin`
+ pub const ORIGIN_WHEN_CROSS_ORIGIN: Self = ReferrerPolicy(Policy::OriginWhenCrossOrigin);
+
+ /// `unsafe-url`
+ pub const UNSAFE_URL: Self = ReferrerPolicy(Policy::UnsafeUrl);
+
+ /// `strict-origin`
+ pub const STRICT_ORIGIN: Self = ReferrerPolicy(Policy::StrictOrigin);
+
+ ///`strict-origin-when-cross-origin`
+ 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>,
+ {
+ // See https://www.w3.org/TR/referrer-policy/#determine-policy-for-token
+ // tl;dr - Pick *last* known policy in the list
+ 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"),
+ }
+ }
+}