http_security_headers/policy/
referrer.rs

1//! Referrer-Policy header configuration.
2//!
3//! The Referrer-Policy header controls how much referrer information should be
4//! included with requests.
5
6use crate::error::{Error, Result};
7
8/// Referrer-Policy header value.
9///
10/// # Examples
11///
12/// ```
13/// use http_security_headers::ReferrerPolicy;
14///
15/// let policy = ReferrerPolicy::NoReferrer;
16/// let policy = ReferrerPolicy::StrictOriginWhenCrossOrigin;
17/// ```
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum ReferrerPolicy {
20    /// No referrer information is sent.
21    NoReferrer,
22    /// Only send the origin when the protocol security level stays the same (HTTPS→HTTPS).
23    NoReferrerWhenDowngrade,
24    /// Only send the origin, not the full URL.
25    Origin,
26    /// Send the full URL when performing a same-origin request, but only the origin for other cases.
27    OriginWhenCrossOrigin,
28    /// Send the full URL for same-origin requests, and no referrer for cross-origin requests.
29    SameOrigin,
30    /// Only send the origin when the protocol security level stays the same (HTTPS→HTTPS),
31    /// and send no referrer to a less secure destination (HTTPS→HTTP).
32    StrictOrigin,
33    /// Send the full URL for same-origin requests, only the origin for cross-origin requests
34    /// on the same protocol level, and no referrer to less secure destinations.
35    StrictOriginWhenCrossOrigin,
36    /// Send the full URL for all requests.
37    UnsafeUrl,
38}
39
40impl ReferrerPolicy {
41    /// Converts the policy to its header value string.
42    pub fn as_str(&self) -> &'static str {
43        match self {
44            Self::NoReferrer => "no-referrer",
45            Self::NoReferrerWhenDowngrade => "no-referrer-when-downgrade",
46            Self::Origin => "origin",
47            Self::OriginWhenCrossOrigin => "origin-when-cross-origin",
48            Self::SameOrigin => "same-origin",
49            Self::StrictOrigin => "strict-origin",
50            Self::StrictOriginWhenCrossOrigin => "strict-origin-when-cross-origin",
51            Self::UnsafeUrl => "unsafe-url",
52        }
53    }
54
55    /// Parses a Referrer-Policy value from a string.
56    pub fn from_str(s: &str) -> Result<Self> {
57        match s.to_lowercase().as_str() {
58            "no-referrer" => Ok(Self::NoReferrer),
59            "no-referrer-when-downgrade" => Ok(Self::NoReferrerWhenDowngrade),
60            "origin" => Ok(Self::Origin),
61            "origin-when-cross-origin" => Ok(Self::OriginWhenCrossOrigin),
62            "same-origin" => Ok(Self::SameOrigin),
63            "strict-origin" => Ok(Self::StrictOrigin),
64            "strict-origin-when-cross-origin" => Ok(Self::StrictOriginWhenCrossOrigin),
65            "unsafe-url" => Ok(Self::UnsafeUrl),
66            _ => Err(Error::InvalidReferrerPolicy(format!(
67                "Unknown referrer policy: '{}'",
68                s
69            ))),
70        }
71    }
72}
73
74impl std::fmt::Display for ReferrerPolicy {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(f, "{}", self.as_str())
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_as_str() {
86        assert_eq!(ReferrerPolicy::NoReferrer.as_str(), "no-referrer");
87        assert_eq!(
88            ReferrerPolicy::NoReferrerWhenDowngrade.as_str(),
89            "no-referrer-when-downgrade"
90        );
91        assert_eq!(ReferrerPolicy::Origin.as_str(), "origin");
92        assert_eq!(
93            ReferrerPolicy::OriginWhenCrossOrigin.as_str(),
94            "origin-when-cross-origin"
95        );
96        assert_eq!(ReferrerPolicy::SameOrigin.as_str(), "same-origin");
97        assert_eq!(ReferrerPolicy::StrictOrigin.as_str(), "strict-origin");
98        assert_eq!(
99            ReferrerPolicy::StrictOriginWhenCrossOrigin.as_str(),
100            "strict-origin-when-cross-origin"
101        );
102        assert_eq!(ReferrerPolicy::UnsafeUrl.as_str(), "unsafe-url");
103    }
104
105    #[test]
106    fn test_from_str() {
107        assert_eq!(
108            ReferrerPolicy::from_str("no-referrer").unwrap(),
109            ReferrerPolicy::NoReferrer
110        );
111        assert_eq!(
112            ReferrerPolicy::from_str("NO-REFERRER").unwrap(),
113            ReferrerPolicy::NoReferrer
114        );
115        assert_eq!(
116            ReferrerPolicy::from_str("strict-origin-when-cross-origin").unwrap(),
117            ReferrerPolicy::StrictOriginWhenCrossOrigin
118        );
119
120        assert!(ReferrerPolicy::from_str("invalid").is_err());
121    }
122
123    #[test]
124    fn test_display() {
125        assert_eq!(ReferrerPolicy::NoReferrer.to_string(), "no-referrer");
126        assert_eq!(
127            ReferrerPolicy::StrictOriginWhenCrossOrigin.to_string(),
128            "strict-origin-when-cross-origin"
129        );
130    }
131}