net/fetch/
headers.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use content_security_policy::Destination;
6use headers::{Error, Header};
7use http::{HeaderName, HeaderValue};
8use net_traits::request::RequestMode;
9
10static SEC_FETCH_DEST: HeaderName = HeaderName::from_static("sec-fetch-dest");
11
12static SEC_FETCH_MODE: HeaderName = HeaderName::from_static("sec-fetch-mode");
13
14static SEC_FETCH_SITE: HeaderName = HeaderName::from_static("sec-fetch-site");
15
16static SEC_FETCH_USER: HeaderName = HeaderName::from_static("sec-fetch-user");
17
18/// The `sec-fetch-dest` header
19pub struct SecFetchDest(pub Destination);
20
21/// The `sec-fetch-mode` header
22///
23/// This is effectively the same as a [RequestMode], except
24/// it doesn't keep track of the websocket protocols
25pub enum SecFetchMode {
26    SameOrigin,
27    Cors,
28    NoCors,
29    Navigate,
30    WebSocket,
31}
32
33/// The `sec-fetch-user` header
34pub struct SecFetchUser;
35
36/// The `sec-fetch-site` header
37#[derive(Eq, PartialEq)]
38pub enum SecFetchSite {
39    None,
40    SameOrigin,
41    SameSite,
42    CrossSite,
43}
44
45impl Header for SecFetchDest {
46    fn name() -> &'static HeaderName {
47        &SEC_FETCH_DEST
48    }
49
50    fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
51    where
52        Self: Sized,
53        I: Iterator<Item = &'i HeaderValue>,
54    {
55        // TODO
56        Err(Error::invalid())
57    }
58
59    fn encode<E>(&self, values: &mut E)
60    where
61        E: Extend<HeaderValue>,
62    {
63        let value = HeaderValue::from_static(destination_as_str(self.0));
64        values.extend(std::iter::once(value));
65    }
66}
67
68impl From<Destination> for SecFetchDest {
69    fn from(value: Destination) -> Self {
70        Self(value)
71    }
72}
73
74impl Header for SecFetchMode {
75    fn name() -> &'static HeaderName {
76        &SEC_FETCH_MODE
77    }
78
79    fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
80    where
81        Self: Sized,
82        I: Iterator<Item = &'i HeaderValue>,
83    {
84        // TODO
85        Err(Error::invalid())
86    }
87
88    fn encode<E>(&self, values: &mut E)
89    where
90        E: Extend<HeaderValue>,
91    {
92        let value = HeaderValue::from_static(self.as_str());
93        values.extend(std::iter::once(value));
94    }
95}
96
97impl<'a> From<&'a RequestMode> for SecFetchMode {
98    fn from(value: &'a RequestMode) -> Self {
99        match value {
100            RequestMode::SameOrigin => Self::SameOrigin,
101            RequestMode::CorsMode => Self::Cors,
102            RequestMode::NoCors => Self::NoCors,
103            RequestMode::Navigate => Self::Navigate,
104            RequestMode::WebSocket { .. } => Self::WebSocket,
105        }
106    }
107}
108
109impl Header for SecFetchSite {
110    fn name() -> &'static HeaderName {
111        &SEC_FETCH_SITE
112    }
113
114    fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
115    where
116        Self: Sized,
117        I: Iterator<Item = &'i HeaderValue>,
118    {
119        // TODO
120        Err(Error::invalid())
121    }
122
123    fn encode<E>(&self, values: &mut E)
124    where
125        E: Extend<HeaderValue>,
126    {
127        let s = match self {
128            Self::None => "none",
129            Self::SameSite => "same-site",
130            Self::CrossSite => "cross-site",
131            Self::SameOrigin => "same-origin",
132        };
133        let value = HeaderValue::from_static(s);
134        values.extend(std::iter::once(value));
135    }
136}
137
138impl Header for SecFetchUser {
139    fn name() -> &'static HeaderName {
140        &SEC_FETCH_USER
141    }
142
143    fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
144    where
145        Self: Sized,
146        I: Iterator<Item = &'i HeaderValue>,
147    {
148        // TODO
149        Err(Error::invalid())
150    }
151
152    fn encode<E>(&self, values: &mut E)
153    where
154        E: Extend<HeaderValue>,
155    {
156        let value = HeaderValue::from_static("?1");
157        values.extend(std::iter::once(value));
158    }
159}
160
161const fn destination_as_str(destination: Destination) -> &'static str {
162    match destination {
163        Destination::None => "empty",
164        Destination::Audio => "audio",
165        Destination::AudioWorklet => "audioworklet",
166        Destination::Document => "document",
167        Destination::Embed => "embed",
168        Destination::Font => "font",
169        Destination::Frame => "frame",
170        Destination::IFrame => "iframe",
171        Destination::Image => "image",
172        Destination::Json => "json",
173        Destination::Manifest => "manifest",
174        Destination::Object => "object",
175        Destination::PaintWorklet => "paintworklet",
176        Destination::Report => "report",
177        Destination::Script => "script",
178        Destination::ServiceWorker => "serviceworker",
179        Destination::SharedWorker => "sharedworker",
180        Destination::Style => "style",
181        Destination::Track => "track",
182        Destination::Video => "video",
183        Destination::WebIdentity => "webidentity",
184        Destination::Worker => "worker",
185        Destination::Xslt => "xslt",
186    }
187}
188
189impl SecFetchMode {
190    /// Converts to the spec representation of a [RequestMode]
191    fn as_str(&self) -> &'static str {
192        match self {
193            Self::SameOrigin => "same-origin",
194            Self::Cors => "cors",
195            Self::NoCors => "no-cors",
196            Self::Navigate => "navigate",
197            Self::WebSocket => "websocket",
198        }
199    }
200}