mirror of
https://github.com/actix/actix-extras.git
synced 2025-02-17 08:33:30 +01:00
fix cors expose_any_header behavior (#204)
This commit is contained in:
parent
545873b5b2
commit
45643d4035
@ -1,12 +1,17 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 0.6.0-beta.3 - 2021-10-21
|
||||||
* Make `Cors` middleware generic over body type [#195]
|
* Make `Cors` middleware generic over body type [#195]
|
||||||
|
* Fix `expose_any_header` behavior. [#204]
|
||||||
* Update `actix-web` dependency to v4.0.0-beta.10. [#203]
|
* Update `actix-web` dependency to v4.0.0-beta.10. [#203]
|
||||||
* Minimum supported Rust version (MSRV) is now 1.52.
|
* Minimum supported Rust version (MSRV) is now 1.52.
|
||||||
|
|
||||||
[#195]: https://github.com/actix/actix-extras/pull/195
|
[#195]: https://github.com/actix/actix-extras/pull/195
|
||||||
[#203]: https://github.com/actix/actix-extras/pull/203
|
[#203]: https://github.com/actix/actix-extras/pull/203
|
||||||
|
[#204]: https://github.com/actix/actix-extras/pull/204
|
||||||
|
|
||||||
|
|
||||||
## 0.6.0-beta.2 - 2021-06-27
|
## 0.6.0-beta.2 - 2021-06-27
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-cors"
|
name = "actix-cors"
|
||||||
version = "0.6.0-beta.2"
|
version = "0.6.0-beta.3"
|
||||||
authors = [
|
authors = [
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
"Rob Ede <robjtede@icloud.com>",
|
||||||
@ -8,7 +8,7 @@ authors = [
|
|||||||
description = "Cross-Origin Resource Sharing (CORS) controls for Actix Web"
|
description = "Cross-Origin Resource Sharing (CORS) controls for Actix Web"
|
||||||
keywords = ["actix", "cors", "web", "security", "crossorigin"]
|
keywords = ["actix", "cors", "web", "security", "crossorigin"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-extras"
|
repository = "https://github.com/actix/actix-extras.git"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
> Cross-origin resource sharing (CORS) for Actix Web.
|
> Cross-origin resource sharing (CORS) for Actix Web.
|
||||||
|
|
||||||
[![crates.io](https://img.shields.io/crates/v/actix-cors?label=latest)](https://crates.io/crates/actix-cors)
|
[![crates.io](https://img.shields.io/crates/v/actix-cors?label=latest)](https://crates.io/crates/actix-cors)
|
||||||
[![Documentation](https://docs.rs/actix-cors/badge.svg?version=0.6.0-beta.2)](https://docs.rs/actix-cors/0.6.0-beta.2)
|
[![Documentation](https://docs.rs/actix-cors/badge.svg?version=0.6.0-beta.3)](https://docs.rs/actix-cors/0.6.0-beta.3)
|
||||||
![Apache 2.0 or MIT licensed](https://img.shields.io/crates/l/actix-cors)
|
![Apache 2.0 or MIT licensed](https://img.shields.io/crates/l/actix-cors)
|
||||||
[![Dependency Status](https://deps.rs/crate/actix-cors/0.6.0-beta.2/status.svg)](https://deps.rs/crate/actix-cors/0.6.0-beta.2)
|
[![Dependency Status](https://deps.rs/crate/actix-cors/0.6.0-beta.3/status.svg)](https://deps.rs/crate/actix-cors/0.6.0-beta.3)
|
||||||
|
|
||||||
## Documentation & Resources
|
## Documentation & Resources
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ impl Cors {
|
|||||||
|
|
||||||
expose_headers: AllOrSome::All,
|
expose_headers: AllOrSome::All,
|
||||||
expose_headers_baked: None,
|
expose_headers_baked: None,
|
||||||
|
|
||||||
max_age: Some(3600),
|
max_age: Some(3600),
|
||||||
preflight: true,
|
preflight: true,
|
||||||
send_wildcard: false,
|
send_wildcard: false,
|
||||||
@ -544,13 +545,18 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Only call when values are guaranteed to be valid header values and set is not empty.
|
/// Only call when values are guaranteed to be valid header values and set is not empty.
|
||||||
fn intersperse_header_values<T>(val_set: &HashSet<T>) -> HeaderValue
|
pub(crate) fn intersperse_header_values<T>(val_set: &HashSet<T>) -> HeaderValue
|
||||||
where
|
where
|
||||||
T: AsRef<str>,
|
T: AsRef<str>,
|
||||||
{
|
{
|
||||||
|
debug_assert!(
|
||||||
|
!val_set.is_empty(),
|
||||||
|
"only call `intersperse_header_values` when set is not empty"
|
||||||
|
);
|
||||||
|
|
||||||
val_set
|
val_set
|
||||||
.iter()
|
.iter()
|
||||||
.fold(String::with_capacity(32), |mut acc, val| {
|
.fold(String::with_capacity(64), |mut acc, val| {
|
||||||
acc.push_str(", ");
|
acc.push_str(", ");
|
||||||
acc.push_str(val.as_ref());
|
acc.push_str(val.as_ref());
|
||||||
acc
|
acc
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::{convert::TryInto, error::Error as StdError, rc::Rc};
|
use std::{collections::HashSet, convert::TryInto, error::Error as StdError, rc::Rc};
|
||||||
|
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
body::{AnyBody, MessageBody},
|
body::{AnyBody, MessageBody},
|
||||||
@ -13,7 +13,7 @@ use actix_web::{
|
|||||||
use futures_util::future::{ok, Either, FutureExt as _, LocalBoxFuture, Ready, TryFutureExt as _};
|
use futures_util::future::{ok, Either, FutureExt as _, LocalBoxFuture, Ready, TryFutureExt as _};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::Inner;
|
use crate::{builder::intersperse_header_values, AllOrSome, Inner};
|
||||||
|
|
||||||
/// Service wrapper for Cross-Origin Resource Sharing support.
|
/// Service wrapper for Cross-Origin Resource Sharing support.
|
||||||
///
|
///
|
||||||
@ -78,8 +78,34 @@ impl<S> CorsMiddleware<S> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ref expose) = inner.expose_headers_baked {
|
if let Some(ref expose) = inner.expose_headers_baked {
|
||||||
|
log::trace!("exposing selected headers: {:?}", expose);
|
||||||
|
|
||||||
res.headers_mut()
|
res.headers_mut()
|
||||||
.insert(header::ACCESS_CONTROL_EXPOSE_HEADERS, expose.clone());
|
.insert(header::ACCESS_CONTROL_EXPOSE_HEADERS, expose.clone());
|
||||||
|
} else if matches!(inner.expose_headers, AllOrSome::All) {
|
||||||
|
// intersperse_header_values requires that argument is non-empty
|
||||||
|
if !res.request().headers().is_empty() {
|
||||||
|
// extract header names from request
|
||||||
|
let expose_all_request_headers = res
|
||||||
|
.request()
|
||||||
|
.headers()
|
||||||
|
.keys()
|
||||||
|
.into_iter()
|
||||||
|
.map(|name| name.as_str())
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
// create comma separated string of header names
|
||||||
|
let expose_headers_value = intersperse_header_values(&expose_all_request_headers);
|
||||||
|
|
||||||
|
log::trace!(
|
||||||
|
"exposing all headers from request: {:?}",
|
||||||
|
expose_headers_value
|
||||||
|
);
|
||||||
|
|
||||||
|
// add header names to expose response header
|
||||||
|
res.headers_mut()
|
||||||
|
.insert(header::ACCESS_CONTROL_EXPOSE_HEADERS, expose_headers_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if inner.supports_credentials {
|
if inner.supports_credentials {
|
||||||
|
@ -416,3 +416,32 @@ async fn test_allow_any_origin_any_method_any_header() {
|
|||||||
let resp = test::call_service(&cors, req).await;
|
let resp = test::call_service(&cors, req).await;
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_web::test]
|
||||||
|
async fn expose_all_request_header_values() {
|
||||||
|
let cors = Cors::permissive()
|
||||||
|
.new_transform(test::ok_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let req = TestRequest::default()
|
||||||
|
.insert_header((header::ORIGIN, "https://www.example.com"))
|
||||||
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "POST"))
|
||||||
|
.insert_header((header::ACCESS_CONTROL_REQUEST_HEADERS, "content-type"))
|
||||||
|
.insert_header(("X-XSRF-TOKEN", "xsrf-token"))
|
||||||
|
.to_srv_request();
|
||||||
|
|
||||||
|
let resp = test::call_service(&cors, req).await;
|
||||||
|
|
||||||
|
assert!(resp
|
||||||
|
.headers()
|
||||||
|
.contains_key(header::ACCESS_CONTROL_EXPOSE_HEADERS));
|
||||||
|
|
||||||
|
assert!(resp
|
||||||
|
.headers()
|
||||||
|
.get(header::ACCESS_CONTROL_EXPOSE_HEADERS)
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.contains("xsrf-token"));
|
||||||
|
}
|
||||||
|
@ -24,5 +24,5 @@ base64 = "0.13"
|
|||||||
futures-util = { version = "0.3.7", default-features = false }
|
futures-util = { version = "0.3.7", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-cors = "0.6.0-beta.2"
|
actix-cors = "0.6.0-beta.3"
|
||||||
actix-rt = "2"
|
actix-rt = "2"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user