1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 23:51:06 +01:00

fix cors expose_any_header behavior (#204)

This commit is contained in:
Rob Ede 2021-10-21 15:47:56 +01:00 committed by GitHub
parent 545873b5b2
commit 45643d4035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 75 additions and 9 deletions

View File

@ -1,12 +1,17 @@
# Changes
## Unreleased - 2021-xx-xx
## 0.6.0-beta.3 - 2021-10-21
* 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]
* Minimum supported Rust version (MSRV) is now 1.52.
[#195]: https://github.com/actix/actix-extras/pull/195
[#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

View File

@ -1,6 +1,6 @@
[package]
name = "actix-cors"
version = "0.6.0-beta.2"
version = "0.6.0-beta.3"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Rob Ede <robjtede@icloud.com>",
@ -8,7 +8,7 @@ authors = [
description = "Cross-Origin Resource Sharing (CORS) controls for Actix Web"
keywords = ["actix", "cors", "web", "security", "crossorigin"]
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"
edition = "2018"

View File

@ -3,9 +3,9 @@
> 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)
[![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)
[![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

View File

@ -95,6 +95,7 @@ impl Cors {
expose_headers: AllOrSome::All,
expose_headers_baked: None,
max_age: Some(3600),
preflight: true,
send_wildcard: false,
@ -544,13 +545,18 @@ where
}
/// 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
T: AsRef<str>,
{
debug_assert!(
!val_set.is_empty(),
"only call `intersperse_header_values` when set is not empty"
);
val_set
.iter()
.fold(String::with_capacity(32), |mut acc, val| {
.fold(String::with_capacity(64), |mut acc, val| {
acc.push_str(", ");
acc.push_str(val.as_ref());
acc

View File

@ -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::{
body::{AnyBody, MessageBody},
@ -13,7 +13,7 @@ use actix_web::{
use futures_util::future::{ok, Either, FutureExt as _, LocalBoxFuture, Ready, TryFutureExt as _};
use log::debug;
use crate::Inner;
use crate::{builder::intersperse_header_values, AllOrSome, Inner};
/// 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 {
log::trace!("exposing selected headers: {:?}", expose);
res.headers_mut()
.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 {

View File

@ -416,3 +416,32 @@ async fn test_allow_any_origin_any_method_any_header() {
let resp = test::call_service(&cors, req).await;
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"));
}

View File

@ -24,5 +24,5 @@ base64 = "0.13"
futures-util = { version = "0.3.7", default-features = false }
[dev-dependencies]
actix-cors = "0.6.0-beta.2"
actix-cors = "0.6.0-beta.3"
actix-rt = "2"