Skip to main content

rama_http_headers/privacy/
dnt.rs

1use crate::{HeaderDecode, HeaderEncode, TypedHeader};
2use rama_core::telemetry::tracing;
3use rama_http_types::{HeaderName, HeaderValue};
4
5#[derive(Debug, Default, Clone, Copy)]
6#[non_exhaustive]
7/// The HTTP DNT (Do Not Track) request header indicates the user's tracking preference.
8///
9/// It lets users indicate whether they would prefer privacy rather than personalized content.
10///
11/// [`Dnt`] in the wild is deprecated in favor of Global Privacy Control,
12/// which is communicated to servers using the [`Sec-GPC`] header,
13/// and accessible to clients from `navigator.globalPrivacyControl`.
14///
15/// [`Sec-GPC`]: super::SecGpc
16pub struct Dnt;
17
18impl Dnt {
19    /// Create a new [`Dnt`] typed header.
20    #[must_use]
21    pub fn new() -> Self {
22        Self
23    }
24}
25
26impl TypedHeader for Dnt {
27    fn name() -> &'static HeaderName {
28        &rama_http_types::header::DNT
29    }
30}
31
32impl HeaderDecode for Dnt {
33    fn decode<'i, I>(values: &mut I) -> Result<Self, crate::Error>
34    where
35        I: Iterator<Item = &'i HeaderValue>,
36    {
37        let value = values.next().ok_or_else(crate::Error::invalid)?;
38
39        if value == "0" {
40            tracing::debug!("unexpected Dnt header value of 0; only 1 is expected");
41            Err(crate::Error::invalid())
42        } else if value == "1" {
43            Ok(Self)
44        } else {
45            Err(crate::Error::invalid())
46        }
47    }
48}
49
50impl HeaderEncode for Dnt {
51    fn encode<E>(&self, values: &mut E)
52    where
53        E: Extend<HeaderValue>,
54    {
55        let value = HeaderValue::from_static("1");
56        values.extend(std::iter::once(value));
57    }
58}