1
0
mirror of https://github.com/actix/actix-extras.git synced 2025-06-26 10:27:42 +02:00

add support for private network access cors header (#297)

closes #294
This commit is contained in:
Rob Ede
2022-10-28 23:44:21 +01:00
committed by GitHub
parent fb8a814acb
commit ac444ca798
7 changed files with 183 additions and 14 deletions

View File

@ -101,6 +101,8 @@ impl Cors {
preflight: true,
send_wildcard: false,
supports_credentials: true,
#[cfg(feature = "draft-private-network-access")]
allow_private_network_access: false,
vary_header: true,
block_on_origin_mismatch: true,
};
@ -370,7 +372,7 @@ impl Cors {
/// [Fetch Standard CORS protocol]: https://fetch.spec.whatwg.org/#http-cors-protocol
pub fn max_age(mut self, max_age: impl Into<Option<usize>>) -> Cors {
if let Some(cors) = cors(&mut self.inner, &self.error) {
cors.max_age = max_age.into()
cors.max_age = max_age.into();
}
self
@ -389,7 +391,7 @@ impl Cors {
/// Defaults to `false`.
pub fn send_wildcard(mut self) -> Cors {
if let Some(cors) = cors(&mut self.inner, &self.error) {
cors.send_wildcard = true
cors.send_wildcard = true;
}
self
@ -412,7 +414,27 @@ impl Cors {
/// [Fetch Standard CORS protocol]: https://fetch.spec.whatwg.org/#http-cors-protocol
pub fn supports_credentials(mut self) -> Cors {
if let Some(cors) = cors(&mut self.inner, &self.error) {
cors.supports_credentials = true
cors.supports_credentials = true;
}
self
}
/// Allow private network access.
///
/// If true, injects the `Access-Control-Allow-Private-Network: true` header in responses if the
/// request contained the `Access-Control-Request-Private-Network: true` header.
///
/// For more information on this behavior, see the draft [Private Network Access] spec.
///
/// Defaults to `false`.
///
/// [Private Network Access]: https://wicg.github.io/private-network-access
#[cfg(feature = "draft-private-network-access")]
#[cfg_attr(docsrs, doc(cfg(feature = "draft-private-network-access")))]
pub fn allow_private_network_access(mut self) -> Cors {
if let Some(cors) = cors(&mut self.inner, &self.error) {
cors.allow_private_network_access = true;
}
self
@ -430,7 +452,7 @@ impl Cors {
/// By default, `Vary` header support is enabled.
pub fn disable_vary_header(mut self) -> Cors {
if let Some(cors) = cors(&mut self.inner, &self.error) {
cors.vary_header = false
cors.vary_header = false;
}
self
@ -444,7 +466,7 @@ impl Cors {
/// By default *preflight* support is enabled.
pub fn disable_preflight(mut self) -> Cors {
if let Some(cors) = cors(&mut self.inner, &self.error) {
cors.preflight = false
cors.preflight = false;
}
self
@ -462,7 +484,7 @@ impl Cors {
/// Defaults to `true`.
pub fn block_on_origin_mismatch(mut self, block: bool) -> Cors {
if let Some(cors) = cors(&mut self.inner, &self.error) {
cors.block_on_origin_mismatch = block
cors.block_on_origin_mismatch = block;
}
self
@ -492,6 +514,8 @@ impl Default for Cors {
preflight: true,
send_wildcard: false,
supports_credentials: false,
#[cfg(feature = "draft-private-network-access")]
allow_private_network_access: false,
vary_header: true,
block_on_origin_mismatch: true,
};

View File

@ -64,6 +64,8 @@ pub(crate) struct Inner {
pub(crate) preflight: bool,
pub(crate) send_wildcard: bool,
pub(crate) supports_credentials: bool,
#[cfg(feature = "draft-private-network-access")]
pub(crate) allow_private_network_access: bool,
pub(crate) vary_header: bool,
pub(crate) block_on_origin_mismatch: bool,
}
@ -219,8 +221,20 @@ pub(crate) fn add_vary_header(headers: &mut HeaderMap) {
let mut val: Vec<u8> = Vec::with_capacity(hdr.len() + 71);
val.extend(hdr.as_bytes());
val.extend(b", Origin, Access-Control-Request-Method, Access-Control-Request-Headers");
#[cfg(feature = "draft-private-network-access")]
val.extend(b", Access-Control-Allow-Private-Network");
val.try_into().unwrap()
}
#[cfg(feature = "draft-private-network-access")]
None => HeaderValue::from_static(
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, \
Access-Control-Allow-Private-Network",
),
#[cfg(not(feature = "draft-private-network-access"))]
None => HeaderValue::from_static(
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
),

View File

@ -1,11 +1,16 @@
//! Cross-Origin Resource Sharing (CORS) controls for Actix Web.
//!
//! This middleware can be applied to both applications and resources. Once built, a
//! [`Cors`] builder can be used as an argument for Actix Web's `App::wrap()`,
//! `Scope::wrap()`, or `Resource::wrap()` methods.
//! This middleware can be applied to both applications and resources. Once built, a [`Cors`]
//! builder can be used as an argument for Actix Web's `App::wrap()`, `Scope::wrap()`, or
//! `Resource::wrap()` methods.
//!
//! This CORS middleware automatically handles `OPTIONS` preflight requests.
//!
//! # Crate Features
//! - `draft-private-network-access`: ⚠️ Unstable. Adds opt-in support for the [Private Network
//! Access] spec extensions. This feature is unstable since it will follow any breaking changes in
//! the draft spec until it is finalized.
//!
//! # Example
//! ```no_run
//! use actix_cors::Cors;
@ -40,12 +45,15 @@
//! Ok(())
//! }
//! ```
//!
//! [Private Network Access]: https://wicg.github.io/private-network-access
#![forbid(unsafe_code)]
#![deny(rust_2018_idioms, nonstandard_style)]
#![warn(future_incompatible, missing_docs, missing_debug_implementations)]
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
#![cfg_attr(docsrs, feature(doc_cfg))]
mod all_or_some;
mod builder;

View File

@ -93,6 +93,18 @@ impl<S> CorsMiddleware<S> {
res.insert_header((header::ACCESS_CONTROL_ALLOW_HEADERS, headers.clone()));
}
#[cfg(feature = "draft-private-network-access")]
if inner.allow_private_network_access
&& req
.headers()
.contains_key("access-control-request-private-network")
{
res.insert_header((
header::HeaderName::from_static("access-control-allow-private-network"),
HeaderValue::from_static("true"),
));
}
if inner.supports_credentials {
res.insert_header((
header::ACCESS_CONTROL_ALLOW_CREDENTIALS,
@ -162,6 +174,19 @@ impl<S> CorsMiddleware<S> {
);
}
#[cfg(feature = "draft-private-network-access")]
if inner.allow_private_network_access
&& res
.request()
.headers()
.contains_key("access-control-request-private-network")
{
res.headers_mut().insert(
header::HeaderName::from_static("access-control-allow-private-network"),
HeaderValue::from_static("true"),
);
}
if inner.vary_header {
add_vary_header(res.headers_mut());
}