From 3a86b3a2b25be1c088cf7d39bb431b2e624d4191 Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Thu, 30 Jun 2016 22:59:57 -0700 Subject: [PATCH] feat(headers): Add Referrer-Policy header --- src/header/common/mod.rs | 2 + src/header/common/referrer_policy.rs | 92 ++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/header/common/referrer_policy.rs diff --git a/src/header/common/mod.rs b/src/header/common/mod.rs index bb2e31507d..7e6685a347 100644 --- a/src/header/common/mod.rs +++ b/src/header/common/mod.rs @@ -48,6 +48,7 @@ pub use self::prefer::{Prefer, Preference}; pub use self::preference_applied::PreferenceApplied; pub use self::range::{Range, ByteRangeSpec}; pub use self::referer::Referer; +pub use self::referrer_policy::ReferrerPolicy; pub use self::server::Server; pub use self::set_cookie::SetCookie; pub use self::strict_transport_security::StrictTransportSecurity; @@ -406,6 +407,7 @@ mod prefer; mod preference_applied; mod range; mod referer; +mod referrer_policy; mod server; mod set_cookie; mod strict_transport_security; diff --git a/src/header/common/referrer_policy.rs b/src/header/common/referrer_policy.rs new file mode 100644 index 0000000000..7bce9a11f0 --- /dev/null +++ b/src/header/common/referrer_policy.rs @@ -0,0 +1,92 @@ +use std::fmt; +use std::ascii::AsciiExt; + +use header::{Header, parsing}; + +/// `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 +/// ```plain +/// 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 +/// ``` +/// use hyper::header::{Headers, ReferrerPolicy}; +/// +/// let mut headers = Headers::new(); +/// headers.set(ReferrerPolicy::NoReferrer); +/// ``` +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum ReferrerPolicy { + /// `no-referrer` + NoReferrer, + /// `no-referrer-when-downgrade` + NoReferrerWhenDowngrade, + /// `same-origin` + SameOrigin, + /// `origin` + Origin, + /// `origin-when-cross-origin` + OriginWhenCrossOrigin, + /// `unsafe-url` + UnsafeUrl, +} + +impl Header for ReferrerPolicy { + fn header_name() -> &'static str { + static NAME: &'static str = "Referrer-Policy"; + NAME + } + + fn parse_header(raw: &[Vec]) -> ::Result { + use self::ReferrerPolicy::*; + parsing::from_one_raw_str(raw).and_then(|s: String| { + let slice = &s.to_ascii_lowercase()[..]; + // See https://www.w3.org/TR/referrer-policy/#determine-policy-for-token + match slice { + "no-referrer" | "never" => Ok(NoReferrer), + "no-referrer-when-downgrade" | "default" => Ok(NoReferrerWhenDowngrade), + "same-origin" => Ok(SameOrigin), + "origin" => Ok(Origin), + "origin-when-cross-origin" => Ok(OriginWhenCrossOrigin), + "unsafe-url" | "always" => Ok(UnsafeUrl), + _ => Err(::Error::Header), + } + }) + } + + fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::ReferrerPolicy::*; + f.write_str(match *self { + NoReferrer => "no-referrer", + NoReferrerWhenDowngrade => "no-referrer-when-downgrade", + SameOrigin => "same-origin", + Origin => "origin", + OriginWhenCrossOrigin => "origin-when-cross-origin", + UnsafeUrl => "unsafe-url", + }) + } +} + +#[test] +fn test_parse_header() { + let a: ReferrerPolicy = Header::parse_header([b"origin".to_vec()].as_ref()).unwrap(); + let b = ReferrerPolicy::Origin; + assert_eq!(a, b); + let e: ::Result = Header::parse_header([b"foobar".to_vec()].as_ref()); + assert!(e.is_err()); +}