Skip to main content

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
56impl std::str::FromStr for ReferrerPolicy {
57    type Err = Error;
58
59    fn from_str(s: &str) -> Result<Self> {
60        match s.to_lowercase().as_str() {
61            "no-referrer" => Ok(Self::NoReferrer),
62            "no-referrer-when-downgrade" => Ok(Self::NoReferrerWhenDowngrade),
63            "origin" => Ok(Self::Origin),
64            "origin-when-cross-origin" => Ok(Self::OriginWhenCrossOrigin),
65            "same-origin" => Ok(Self::SameOrigin),
66            "strict-origin" => Ok(Self::StrictOrigin),
67            "strict-origin-when-cross-origin" => Ok(Self::StrictOriginWhenCrossOrigin),
68            "unsafe-url" => Ok(Self::UnsafeUrl),
69            _ => Err(Error::InvalidReferrerPolicy(format!(
70                "Unknown referrer policy: '{}'",
71                s
72            ))),
73        }
74    }
75}
76
77impl std::fmt::Display for ReferrerPolicy {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        write!(f, "{}", self.as_str())
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86    use std::str::FromStr;
87
88    #[test]
89    fn test_as_str() {
90        assert_eq!(ReferrerPolicy::NoReferrer.as_str(), "no-referrer");
91        assert_eq!(
92            ReferrerPolicy::NoReferrerWhenDowngrade.as_str(),
93            "no-referrer-when-downgrade"
94        );
95        assert_eq!(ReferrerPolicy::Origin.as_str(), "origin");
96        assert_eq!(
97            ReferrerPolicy::OriginWhenCrossOrigin.as_str(),
98            "origin-when-cross-origin"
99        );
100        assert_eq!(ReferrerPolicy::SameOrigin.as_str(), "same-origin");
101        assert_eq!(ReferrerPolicy::StrictOrigin.as_str(), "strict-origin");
102        assert_eq!(
103            ReferrerPolicy::StrictOriginWhenCrossOrigin.as_str(),
104            "strict-origin-when-cross-origin"
105        );
106        assert_eq!(ReferrerPolicy::UnsafeUrl.as_str(), "unsafe-url");
107    }
108
109    #[test]
110    fn test_from_str() {
111        assert_eq!(
112            ReferrerPolicy::from_str("no-referrer").unwrap(),
113            ReferrerPolicy::NoReferrer
114        );
115        assert_eq!(
116            ReferrerPolicy::from_str("NO-REFERRER").unwrap(),
117            ReferrerPolicy::NoReferrer
118        );
119        assert_eq!(
120            ReferrerPolicy::from_str("strict-origin-when-cross-origin").unwrap(),
121            ReferrerPolicy::StrictOriginWhenCrossOrigin
122        );
123
124        assert!(ReferrerPolicy::from_str("invalid").is_err());
125    }
126
127    #[test]
128    fn test_display() {
129        assert_eq!(ReferrerPolicy::NoReferrer.to_string(), "no-referrer");
130        assert_eq!(
131            ReferrerPolicy::StrictOriginWhenCrossOrigin.to_string(),
132            "strict-origin-when-cross-origin"
133        );
134    }
135}