Skip to content

Commit accfbde

Browse files
committed
feat: cors support for embedder and opener
Refer: #202
1 parent f551187 commit accfbde

File tree

4 files changed

+82
-4
lines changed

4 files changed

+82
-4
lines changed

fixtures/config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ port = 7878
2121
# max_age = 600
2222
# request_headers = ["x-app-version"]
2323
# request_method = "GET"
24+
# embedder_policy = "require-corp"
25+
# opener_policy = "same-origin"
2426

2527
# [compression]
2628
# gzip = true

src/addon/cors.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ pub struct Cors {
7979
/// preflight request is always an OPTIONS and doesn't use the same method as
8080
/// the actual request.
8181
pub(crate) request_method: Option<String>,
82+
/// The HTTP Cross-Origin-Embedder-Policy (COEP) response header prevents a
83+
/// document from loading any cross-origin resources that don't explicitly
84+
/// grant the document permission (using CORP or CORS).
85+
///
86+
/// Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy
87+
pub(crate) embedder_policy: Option<String>,
88+
/// The HTTP Cross-Origin-Opener-Policy (COOP) response header allows you to
89+
/// ensure a top-level document does not share a browsing context group with
90+
/// cross-origin documents.
91+
///
92+
/// Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy
93+
pub(crate) opener_policy: Option<String>,
8294
}
8395

8496
impl Cors {
@@ -156,6 +168,32 @@ impl Cors {
156168
));
157169
}
158170

171+
if let Some(embedder_policy) = cors.embedder_policy {
172+
// TODO: Validate possible directives
173+
//
174+
// Cross-Origin-Embedder-Policy: unsafe-none | require-corp
175+
//
176+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#directives
177+
cors_headers.push((
178+
HeaderName::from_static("Cross-Origin-Embedder-Policy"),
179+
HeaderValue::from_str(&embedder_policy.as_str()).unwrap(),
180+
));
181+
}
182+
183+
if let Some(opener_policy) = cors.opener_policy {
184+
// TODO: Validate possible directives
185+
//
186+
// Cross-Origin-Opener-Policy: unsafe-none
187+
// Cross-Origin-Opener-Policy: same-origin-allow-popups
188+
// Cross-Origin-Opener-Policy: same-origin
189+
//
190+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy#directives
191+
cors_headers.push((
192+
HeaderName::from_static("Cross-Origin-Opener-Policy"),
193+
HeaderValue::from_str(&opener_policy.as_str()).unwrap(),
194+
));
195+
}
196+
159197
cors_headers
160198
}
161199
}
@@ -206,6 +244,16 @@ impl CorsBuilder {
206244
self
207245
}
208246

247+
pub fn embedder_policy(mut self, embedder_policy: String) -> Self {
248+
self.config.embedder_policy = Some(embedder_policy);
249+
self
250+
}
251+
252+
pub fn opener_policy(mut self, opener_policy: String) -> Self {
253+
self.config.opener_policy = Some(opener_policy);
254+
self
255+
}
256+
209257
pub fn build(self) -> Cors {
210258
self.config
211259
}
@@ -249,6 +297,14 @@ impl TryFrom<CorsConfig> for Cors {
249297
builder = builder.request_method(request_method);
250298
}
251299

300+
if let Some(embedder_policy) = value.embedder_policy {
301+
builder = builder.embedder_policy(embedder_policy);
302+
}
303+
304+
if let Some(opener_policy) = value.opener_policy {
305+
builder = builder.opener_policy(opener_policy);
306+
}
307+
252308
Ok(builder.build())
253309
}
254310
}
@@ -360,6 +416,7 @@ mod tests {
360416
max_age: Some(max_age),
361417
request_headers: Some(request_headers.clone()),
362418
request_method: Some(request_method.clone()),
419+
..Default::default()
363420
};
364421
let cors = Cors {
365422
allow_credentials: true,
@@ -370,6 +427,7 @@ mod tests {
370427
max_age: Some(max_age),
371428
request_headers: Some(request_headers),
372429
request_method: Some(request_method),
430+
..Default::default()
373431
};
374432

375433
assert_eq!(cors, Cors::try_from(config).unwrap());

src/config/cors.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ pub struct CorsConfig {
1010
pub max_age: Option<u64>,
1111
pub request_headers: Option<Vec<String>>,
1212
pub request_method: Option<String>,
13+
pub embedder_policy: Option<String>,
14+
pub opener_policy: Option<String>,
1315
}
1416

1517
impl CorsConfig {
@@ -31,7 +33,22 @@ impl CorsConfig {
3133
]),
3234
allow_credentials: false,
3335
max_age: Some(43200),
36+
..Default::default()
37+
}
38+
}
39+
}
40+
41+
impl Default for CorsConfig {
42+
fn default() -> Self {
43+
Self {
44+
allow_origin: None,
45+
allow_headers: None,
46+
allow_credentials: false,
47+
allow_methods: None,
48+
embedder_policy: None,
3449
expose_headers: None,
50+
max_age: None,
51+
opener_policy: None,
3552
request_headers: None,
3653
request_method: None,
3754
}

src/config/file.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,7 @@ mod tests {
190190
"DELETE".to_string(),
191191
]),
192192
allow_origin: Some(String::from("example.com")),
193-
expose_headers: None,
194-
max_age: None,
195-
request_headers: None,
196-
request_method: None,
193+
..Default::default()
197194
};
198195
let config = ConfigFile::parse_toml(file_contents).unwrap();
199196
let root_dir = Some(std::env::current_dir().unwrap());
@@ -219,6 +216,8 @@ mod tests {
219216
max_age = 2800
220217
request_headers = ["x-app-version"]
221218
request_method = "GET"
219+
embedder_policy = "require-corp"
220+
opener_policy = "same-origin"
222221
"#;
223222
let host = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
224223
let port = 8080;
@@ -242,6 +241,8 @@ mod tests {
242241
max_age: Some(2800),
243242
request_headers: Some(vec!["x-app-version".to_string()]),
244243
request_method: Some(String::from("GET")),
244+
embedder_policy: Some(String::from("require-corp")),
245+
opener_policy: Some(String::from("same-origin")),
245246
};
246247
let config = ConfigFile::parse_toml(file_contents).unwrap();
247248

0 commit comments

Comments
 (0)