mco_http/header/common/
referrer_policy.rs

1use std::fmt;
2
3use crate::header::{Header, HeaderFormat, parsing};
4
5/// `Referrer-Policy` header, part of
6/// [Referrer Policy](https://www.w3.org/TR/referrer-policy/#referrer-policy-header)
7///
8/// The `Referrer-Policy` HTTP header specifies the referrer
9/// policy that the user agent applies when determining what
10/// referrer information should be included with requests made,
11/// and with browsing contexts created from the context of the
12/// protected resource.
13///
14/// # ABNF
15/// ```plain
16/// Referrer-Policy: 1#policy-token
17/// policy-token   = "no-referrer" / "no-referrer-when-downgrade"
18///                  / "same-origin" / "origin"
19///                  / "origin-when-cross-origin" / "unsafe-url"
20/// ```
21///
22/// # Example values
23/// * `no-referrer`
24///
25/// # Example
26/// ```
27/// use mco_http::header::{Headers, ReferrerPolicy};
28///
29/// let mut headers = Headers::new();
30/// headers.set(ReferrerPolicy::NoReferrer);
31/// ```
32#[derive(Clone, PartialEq, Eq, Debug)]
33pub enum ReferrerPolicy {
34    /// `no-referrer`
35    NoReferrer,
36    /// `no-referrer-when-downgrade`
37    NoReferrerWhenDowngrade,
38    /// `same-origin`
39    SameOrigin,
40    /// `origin`
41    Origin,
42    /// `origin-when-cross-origin`
43    OriginWhenCrossOrigin,
44    /// `unsafe-url`
45    UnsafeUrl,
46     /// `strict-origin`
47    StrictOrigin,
48    ///`strict-origin-when-cross-origin`
49    StrictOriginWhenCrossOrigin,
50}
51
52impl Header for ReferrerPolicy {
53    fn header_name() -> &'static str {
54        static NAME: &'static str = "Referrer-Policy";
55        NAME
56    }
57
58    fn parse_header(raw: &[Vec<u8>]) -> crate::Result<ReferrerPolicy> {
59        use self::ReferrerPolicy::*;
60        // See https://www.w3.org/TR/referrer-policy/#determine-policy-for-token
61        let headers: Vec<String> = parsing::from_comma_delimited(raw)?;
62
63        for h in headers.iter().rev() {
64            let slice = &h.to_ascii_lowercase()[..];
65            match slice {
66                "no-referrer" | "never" => return Ok(NoReferrer),
67                "no-referrer-when-downgrade" | "default" => return Ok(NoReferrerWhenDowngrade),
68                "same-origin" => return Ok(SameOrigin),
69                "origin" => return Ok(Origin),
70                "origin-when-cross-origin" => return Ok(OriginWhenCrossOrigin),
71                "strict-origin" => return Ok(StrictOrigin),
72                "strict-origin-when-cross-origin" => return Ok(StrictOriginWhenCrossOrigin),
73                "unsafe-url" | "always" => return Ok(UnsafeUrl),
74                _ => continue,
75            }
76        }
77
78        Err(crate::Error::Header)
79    }
80}
81
82impl HeaderFormat for ReferrerPolicy {
83    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
84        fmt::Display::fmt(self, f)
85    }
86}
87
88impl fmt::Display for ReferrerPolicy {
89    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90        use self::ReferrerPolicy::*;
91        f.write_str(match *self {
92            NoReferrer => "no-referrer",
93            NoReferrerWhenDowngrade => "no-referrer-when-downgrade",
94            SameOrigin => "same-origin",
95            Origin => "origin",
96            OriginWhenCrossOrigin => "origin-when-cross-origin",
97            StrictOrigin => "strict-origin",
98            StrictOriginWhenCrossOrigin => "strict-origin-when-cross-origin",
99            UnsafeUrl => "unsafe-url",
100        })
101    }
102}
103
104#[test]
105fn test_parse_header() {
106    let a: ReferrerPolicy = Header::parse_header([b"origin".to_vec()].as_ref()).unwrap();
107    let b = ReferrerPolicy::Origin;
108    assert_eq!(a, b);
109    let e: crate::Result<ReferrerPolicy> = Header::parse_header([b"foobar".to_vec()].as_ref());
110    assert!(e.is_err());
111}
112
113#[test]
114fn test_rightmost_header() {
115    let a: ReferrerPolicy = Header::parse_header(&["same-origin, origin, foobar".into()]).unwrap();
116    let b = ReferrerPolicy::Origin;
117    assert_eq!(a, b);
118}