Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cors support for embedder and opener #203

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 11 additions & 9 deletions fixtures/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ port = 7878
# cert = "cert.pem"
# key = "key.pem"

# [cors]
# allow_credentials = false
# allow_headers = ["content-type", "authorization", "content-length"]
# allow_methods = ["GET", "PATCH", "POST", "PUT", "DELETE"]
# allow_origin = "example.com"
# expose_headers = ["*", "authorization"]
# max_age = 600
# request_headers = ["x-app-version"]
# request_method = "GET"
[cors]
allow_credentials = false
allow_headers = ["content-type", "authorization", "content-length"]
allow_methods = ["GET", "PATCH", "POST", "PUT", "DELETE"]
allow_origin = "example.com"
expose_headers = ["*", "authorization"]
max_age = 600
request_headers = ["x-app-version"]
request_method = "GET"
embedder_policy = "require-corp"
opener_policy = "same-origin"

# [compression]
# gzip = true
Expand Down
58 changes: 58 additions & 0 deletions src/addon/cors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ pub struct Cors {
/// preflight request is always an OPTIONS and doesn't use the same method as
/// the actual request.
pub(crate) request_method: Option<String>,
/// The HTTP Cross-Origin-Embedder-Policy (COEP) response header prevents a
/// document from loading any cross-origin resources that don't explicitly
/// grant the document permission (using CORP or CORS).
///
/// Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy
pub(crate) embedder_policy: Option<String>,
/// The HTTP Cross-Origin-Opener-Policy (COOP) response header allows you to
/// ensure a top-level document does not share a browsing context group with
/// cross-origin documents.
///
/// Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy
pub(crate) opener_policy: Option<String>,
}

impl Cors {
Expand Down Expand Up @@ -156,6 +168,32 @@ impl Cors {
));
}

if let Some(embedder_policy) = cors.embedder_policy {
// TODO: Validate possible directives
//
// Cross-Origin-Embedder-Policy: unsafe-none | require-corp
//
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#directives
cors_headers.push((
HeaderName::from_static("Cross-Origin-Embedder-Policy"),
HeaderValue::from_str(embedder_policy.as_str()).unwrap(),
));
}

if let Some(opener_policy) = cors.opener_policy {
// TODO: Validate possible directives
//
// Cross-Origin-Opener-Policy: unsafe-none
// Cross-Origin-Opener-Policy: same-origin-allow-popups
// Cross-Origin-Opener-Policy: same-origin
//
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy#directives
cors_headers.push((
HeaderName::from_static("Cross-Origin-Opener-Policy"),
HeaderValue::from_str(opener_policy.as_str()).unwrap(),
));
}

cors_headers
}
}
Expand Down Expand Up @@ -206,6 +244,16 @@ impl CorsBuilder {
self
}

pub fn embedder_policy(mut self, embedder_policy: String) -> Self {
self.config.embedder_policy = Some(embedder_policy);
self
}

pub fn opener_policy(mut self, opener_policy: String) -> Self {
self.config.opener_policy = Some(opener_policy);
self
}

pub fn build(self) -> Cors {
self.config
}
Expand Down Expand Up @@ -249,6 +297,14 @@ impl TryFrom<CorsConfig> for Cors {
builder = builder.request_method(request_method);
}

if let Some(embedder_policy) = value.embedder_policy {
builder = builder.embedder_policy(embedder_policy);
}

if let Some(opener_policy) = value.opener_policy {
builder = builder.opener_policy(opener_policy);
}

Ok(builder.build())
}
}
Expand Down Expand Up @@ -360,6 +416,7 @@ mod tests {
max_age: Some(max_age),
request_headers: Some(request_headers.clone()),
request_method: Some(request_method.clone()),
..Default::default()
};
let cors = Cors {
allow_credentials: true,
Expand All @@ -370,6 +427,7 @@ mod tests {
max_age: Some(max_age),
request_headers: Some(request_headers),
request_method: Some(request_method),
..Default::default()
};

assert_eq!(cors, Cors::try_from(config).unwrap());
Expand Down
9 changes: 6 additions & 3 deletions src/config/cors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use serde::Deserialize;

#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
#[derive(Default)]
pub struct CorsConfig {
pub allow_credentials: bool,
pub allow_headers: Option<Vec<String>>,
Expand All @@ -10,6 +11,8 @@ pub struct CorsConfig {
pub max_age: Option<u64>,
pub request_headers: Option<Vec<String>>,
pub request_method: Option<String>,
pub embedder_policy: Option<String>,
pub opener_policy: Option<String>,
}

impl CorsConfig {
Expand All @@ -31,9 +34,9 @@ impl CorsConfig {
]),
allow_credentials: false,
max_age: Some(43200),
expose_headers: None,
request_headers: None,
request_method: None,
..Default::default()
}
}
}


9 changes: 5 additions & 4 deletions src/config/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,7 @@ mod tests {
"DELETE".to_string(),
]),
allow_origin: Some(String::from("example.com")),
expose_headers: None,
max_age: None,
request_headers: None,
request_method: None,
..Default::default()
};
let config = ConfigFile::parse_toml(file_contents).unwrap();
let root_dir = Some(std::env::current_dir().unwrap());
Expand All @@ -219,6 +216,8 @@ mod tests {
max_age = 2800
request_headers = ["x-app-version"]
request_method = "GET"
embedder_policy = "require-corp"
opener_policy = "same-origin"
"#;
let host = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
let port = 8080;
Expand All @@ -242,6 +241,8 @@ mod tests {
max_age: Some(2800),
request_headers: Some(vec!["x-app-version".to_string()]),
request_method: Some(String::from("GET")),
embedder_policy: Some(String::from("require-corp")),
opener_policy: Some(String::from("same-origin")),
};
let config = ConfigFile::parse_toml(file_contents).unwrap();

Expand Down