mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-30 10:32:55 +01:00
feat(cors): allow using closures in allow_origin_fn (#110)
This commit is contained in:
parent
0f7a147323
commit
b33012999c
@ -1,6 +1,7 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
* Improve `allowed_origin_fn` to allow using of closures. [#110]
|
||||||
|
|
||||||
|
|
||||||
## 0.4.0 - 2020-09-27
|
## 0.4.0 - 2020-09-27
|
||||||
@ -9,7 +10,7 @@
|
|||||||
|
|
||||||
[#93]: https://github.com/actix/actix-extras/pull/93
|
[#93]: https://github.com/actix/actix-extras/pull/93
|
||||||
[#106]: https://github.com/actix/actix-extras/pull/106
|
[#106]: https://github.com/actix/actix-extras/pull/106
|
||||||
|
[#110]: https://github.com/actix/actix-extras/pull/110
|
||||||
|
|
||||||
## 0.3.0 - 2020-09-11
|
## 0.3.0 - 2020-09-11
|
||||||
* Update `actix-web` dependency to 3.0.0.
|
* Update `actix-web` dependency to 3.0.0.
|
||||||
|
@ -23,3 +23,4 @@ futures-util = { version = "0.3.4", default-features = false }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "1.1.1"
|
actix-rt = "1.1.1"
|
||||||
|
regex = "1.3.9"
|
||||||
|
@ -290,9 +290,14 @@ impl Cors {
|
|||||||
///
|
///
|
||||||
/// If the function returns `true`, the client's `Origin` request header will be echoed
|
/// If the function returns `true`, the client's `Origin` request header will be echoed
|
||||||
/// back into the `Access-Control-Allow-Origin` response header.
|
/// back into the `Access-Control-Allow-Origin` response header.
|
||||||
pub fn allowed_origin_fn(mut self, f: fn(req: &RequestHead) -> bool) -> Cors {
|
pub fn allowed_origin_fn<F>(mut self, f: F) -> Cors
|
||||||
|
where
|
||||||
|
F: (Fn(&RequestHead) -> bool) + 'static,
|
||||||
|
{
|
||||||
if let Some(cors) = cors(&mut self.cors, &self.error) {
|
if let Some(cors) = cors(&mut self.cors, &self.error) {
|
||||||
cors.origins_fns.push(OriginFn { f });
|
cors.origins_fns.push(OriginFn {
|
||||||
|
boxed_fn: Box::new(f),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -597,7 +602,7 @@ pub struct CorsMiddleware<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct OriginFn {
|
struct OriginFn {
|
||||||
f: fn(req: &RequestHead) -> bool,
|
boxed_fn: Box<dyn Fn(&RequestHead) -> bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for OriginFn {
|
impl fmt::Debug for OriginFn {
|
||||||
@ -650,7 +655,9 @@ impl Inner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate_origin_fns(&self, req: &RequestHead) -> bool {
|
fn validate_origin_fns(&self, req: &RequestHead) -> bool {
|
||||||
self.origins_fns.iter().any(|origin_fn| (origin_fn.f)(req))
|
self.origins_fns
|
||||||
|
.iter()
|
||||||
|
.any(|origin_fn| (origin_fn.boxed_fn)(req))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access_control_allow_origin(&self, req: &RequestHead) -> Option<HeaderValue> {
|
fn access_control_allow_origin(&self, req: &RequestHead) -> Option<HeaderValue> {
|
||||||
@ -882,6 +889,7 @@ mod tests {
|
|||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use regex::bytes::Regex;
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn allowed_header_tryfrom() {
|
async fn allowed_header_tryfrom() {
|
||||||
@ -1328,6 +1336,56 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_allowed_origin_fn_with_environment() {
|
||||||
|
let regex = Regex::new("https:.+\\.unknown\\.com").unwrap();
|
||||||
|
let mut cors = Cors::new()
|
||||||
|
.allowed_origin("https://www.example.com")
|
||||||
|
.allowed_origin_fn(move |req| {
|
||||||
|
req.headers
|
||||||
|
.get(header::ORIGIN)
|
||||||
|
.map(HeaderValue::as_bytes)
|
||||||
|
.filter(|b| regex.is_match(b))
|
||||||
|
.is_some()
|
||||||
|
})
|
||||||
|
.finish()
|
||||||
|
.new_transform(test::ok_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
{
|
||||||
|
let req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||||
|
.method(Method::GET)
|
||||||
|
.to_srv_request();
|
||||||
|
|
||||||
|
let resp = test::call_service(&mut cors, req).await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
"https://www.example.com",
|
||||||
|
resp.headers()
|
||||||
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let req = TestRequest::with_header("Origin", "https://www.unknown.com")
|
||||||
|
.method(Method::GET)
|
||||||
|
.to_srv_request();
|
||||||
|
|
||||||
|
let resp = test::call_service(&mut cors, req).await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Some(&b"https://www.unknown.com"[..]),
|
||||||
|
resp.headers()
|
||||||
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||||
|
.map(HeaderValue::as_bytes)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_not_allowed_origin_fn() {
|
async fn test_not_allowed_origin_fn() {
|
||||||
let mut cors = Cors::new()
|
let mut cors = Cors::new()
|
||||||
|
Loading…
Reference in New Issue
Block a user