2022-03-29 12:46:13 +02:00
|
|
|
use actix_cors::Cors;
|
2021-12-08 08:29:12 +01:00
|
|
|
use actix_utils::future::ok;
|
2020-10-08 12:50:56 +02:00
|
|
|
use actix_web::{
|
2022-09-11 22:55:40 +02:00
|
|
|
dev::{fn_service, ServiceRequest, Transform},
|
2021-12-11 17:05:21 +01:00
|
|
|
http::{
|
|
|
|
header::{self, HeaderValue},
|
|
|
|
Method, StatusCode,
|
|
|
|
},
|
2020-10-08 12:50:56 +02:00
|
|
|
test::{self, TestRequest},
|
|
|
|
HttpResponse,
|
|
|
|
};
|
|
|
|
use regex::bytes::Regex;
|
|
|
|
|
2020-10-19 06:51:31 +02:00
|
|
|
fn val_as_str(val: &HeaderValue) -> &str {
|
|
|
|
val.to_str().unwrap()
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-10 15:25:33 +02:00
|
|
|
#[should_panic]
|
|
|
|
async fn test_wildcard_origin() {
|
2020-10-19 06:51:31 +02:00
|
|
|
Cors::default()
|
2020-10-10 15:25:33 +02:00
|
|
|
.allowed_origin("*")
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn test_not_allowed_origin_fn() {
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-08 12:50:56 +02:00
|
|
|
.allowed_origin("https://www.example.com")
|
2020-10-19 20:30:46 +02:00
|
|
|
.allowed_origin_fn(|origin, req| {
|
|
|
|
assert_eq!(&origin, req.headers.get(header::ORIGIN).unwrap());
|
|
|
|
|
2020-10-08 12:50:56 +02:00
|
|
|
req.headers
|
|
|
|
.get(header::ORIGIN)
|
|
|
|
.map(HeaderValue::as_bytes)
|
|
|
|
.filter(|b| b.ends_with(b".unknown.com"))
|
|
|
|
.is_some()
|
|
|
|
})
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
{
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
Some(&b"https://www.example.com"[..]),
|
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
|
|
|
.map(HeaderValue::as_bytes)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://www.known.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
None,
|
|
|
|
resp.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn test_allowed_origin_fn() {
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-08 12:50:56 +02:00
|
|
|
.allowed_origin("https://www.example.com")
|
2020-10-19 20:30:46 +02:00
|
|
|
.allowed_origin_fn(|origin, req| {
|
|
|
|
assert_eq!(&origin, req.headers.get(header::ORIGIN).unwrap());
|
|
|
|
|
2020-10-08 12:50:56 +02:00
|
|
|
req.headers
|
|
|
|
.get(header::ORIGIN)
|
|
|
|
.map(HeaderValue::as_bytes)
|
|
|
|
.filter(|b| b.ends_with(b".unknown.com"))
|
|
|
|
.is_some()
|
|
|
|
})
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
"https://www.example.com",
|
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(val_as_str)
|
2020-10-08 12:50:56 +02:00
|
|
|
.unwrap()
|
|
|
|
);
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://www.unknown.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
Some(&b"https://www.unknown.com"[..]),
|
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
|
|
|
.map(HeaderValue::as_bytes)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn test_allowed_origin_fn_with_environment() {
|
|
|
|
let regex = Regex::new("https:.+\\.unknown\\.com").unwrap();
|
2020-10-19 20:30:46 +02:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-08 12:50:56 +02:00
|
|
|
.allowed_origin("https://www.example.com")
|
2020-10-19 20:30:46 +02:00
|
|
|
.allowed_origin_fn(move |origin, req| {
|
|
|
|
assert_eq!(&origin, req.headers.get(header::ORIGIN).unwrap());
|
|
|
|
|
2020-10-08 12:50:56 +02:00
|
|
|
req.headers
|
|
|
|
.get(header::ORIGIN)
|
|
|
|
.map(HeaderValue::as_bytes)
|
|
|
|
.filter(|b| regex.is_match(b))
|
|
|
|
.is_some()
|
|
|
|
})
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
"https://www.example.com",
|
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(val_as_str)
|
2020-10-08 12:50:56 +02:00
|
|
|
.unwrap()
|
|
|
|
);
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://www.unknown.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
Some(&b"https://www.unknown.com"[..]),
|
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
|
|
|
.map(HeaderValue::as_bytes)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn test_multiple_origins_preflight() {
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-08 12:50:56 +02:00
|
|
|
.allowed_origin("https://example.com")
|
|
|
|
.allowed_origin("https://example.org")
|
|
|
|
.allowed_methods(vec![Method::GET])
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header(("Origin", "https://example.com"))
|
|
|
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "GET"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.method(Method::OPTIONS)
|
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(
|
2020-10-19 06:51:31 +02:00
|
|
|
Some(&b"https://example.com"[..]),
|
2020-10-08 12:50:56 +02:00
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(HeaderValue::as_bytes)
|
2020-10-08 12:50:56 +02:00
|
|
|
);
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header(("Origin", "https://example.org"))
|
|
|
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "GET"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.method(Method::OPTIONS)
|
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(
|
2020-10-19 06:51:31 +02:00
|
|
|
Some(&b"https://example.org"[..]),
|
2020-10-08 12:50:56 +02:00
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(HeaderValue::as_bytes)
|
2020-10-08 12:50:56 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn test_multiple_origins() {
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-08 12:50:56 +02:00
|
|
|
.allowed_origin("https://example.com")
|
|
|
|
.allowed_origin("https://example.org")
|
|
|
|
.allowed_methods(vec![Method::GET])
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(
|
2020-10-19 06:51:31 +02:00
|
|
|
Some(&b"https://example.com"[..]),
|
2020-10-08 12:50:56 +02:00
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(HeaderValue::as_bytes)
|
2020-10-08 12:50:56 +02:00
|
|
|
);
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://example.org"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(
|
2020-10-19 06:51:31 +02:00
|
|
|
Some(&b"https://example.org"[..]),
|
2020-10-08 12:50:56 +02:00
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(HeaderValue::as_bytes)
|
2020-10-08 12:50:56 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn test_response() {
|
|
|
|
let exposed_headers = vec![header::AUTHORIZATION, header::ACCEPT];
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-19 06:51:31 +02:00
|
|
|
.allow_any_origin()
|
2020-10-08 12:50:56 +02:00
|
|
|
.send_wildcard()
|
|
|
|
.disable_preflight()
|
|
|
|
.max_age(3600)
|
|
|
|
.allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST])
|
|
|
|
.allowed_headers(exposed_headers.clone())
|
|
|
|
.expose_headers(exposed_headers.clone())
|
|
|
|
.allowed_header(header::CONTENT_TYPE)
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.method(Method::OPTIONS)
|
|
|
|
.to_srv_request();
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(
|
2020-10-19 06:51:31 +02:00
|
|
|
Some(&b"*"[..]),
|
2020-10-08 12:50:56 +02:00
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(HeaderValue::as_bytes)
|
2020-10-08 12:50:56 +02:00
|
|
|
);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(not(feature = "draft-private-network-access"))]
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(
|
2022-01-02 00:07:27 +01:00
|
|
|
resp.headers().get(header::VARY).map(HeaderValue::as_bytes),
|
|
|
|
Some(&b"Origin, Access-Control-Request-Method, Access-Control-Request-Headers"[..]),
|
2020-10-08 12:50:56 +02:00
|
|
|
);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(feature = "draft-private-network-access")]
|
2022-10-29 00:44:21 +02:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers().get(header::VARY).map(HeaderValue::as_bytes),
|
2023-12-06 14:52:22 +01:00
|
|
|
Some(&b"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Private-Network"[..]),
|
2022-10-29 00:44:21 +02:00
|
|
|
);
|
2020-10-08 12:50:56 +02:00
|
|
|
|
|
|
|
#[allow(clippy::needless_collect)]
|
|
|
|
{
|
|
|
|
let headers = resp
|
|
|
|
.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_EXPOSE_HEADERS)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(val_as_str)
|
2020-10-08 12:50:56 +02:00
|
|
|
.unwrap()
|
|
|
|
.split(',')
|
|
|
|
.map(|s| s.trim())
|
|
|
|
.collect::<Vec<&str>>();
|
|
|
|
|
2020-10-19 06:51:31 +02:00
|
|
|
// TODO: use HashSet subset check
|
2020-10-08 12:50:56 +02:00
|
|
|
for h in exposed_headers {
|
|
|
|
assert!(headers.contains(&h.as_str()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let exposed_headers = vec![header::AUTHORIZATION, header::ACCEPT];
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-19 06:51:31 +02:00
|
|
|
.allow_any_origin()
|
2020-10-08 12:50:56 +02:00
|
|
|
.send_wildcard()
|
|
|
|
.disable_preflight()
|
|
|
|
.max_age(3600)
|
|
|
|
.allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST])
|
|
|
|
.allowed_headers(exposed_headers.clone())
|
|
|
|
.expose_headers(exposed_headers.clone())
|
|
|
|
.allowed_header(header::CONTENT_TYPE)
|
|
|
|
.new_transform(fn_service(|req: ServiceRequest| {
|
2020-10-19 06:51:31 +02:00
|
|
|
ok(req.into_response({
|
2021-03-21 23:50:26 +01:00
|
|
|
HttpResponse::Ok()
|
|
|
|
.insert_header((header::VARY, "Accept"))
|
|
|
|
.finish()
|
2020-10-19 06:51:31 +02:00
|
|
|
}))
|
2020-10-08 12:50:56 +02:00
|
|
|
}))
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2020-10-19 06:51:31 +02:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.method(Method::OPTIONS)
|
|
|
|
.to_srv_request();
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(not(feature = "draft-private-network-access"))]
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(
|
2022-10-29 00:44:21 +02:00
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.map(HeaderValue::as_bytes)
|
|
|
|
.unwrap(),
|
|
|
|
b"Accept, Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
|
|
|
);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(feature = "draft-private-network-access")]
|
2022-10-29 00:44:21 +02:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers().get(header::VARY).map(HeaderValue::as_bytes).unwrap(),
|
2023-12-06 14:52:22 +01:00
|
|
|
b"Accept, Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Private-Network",
|
2020-10-08 12:50:56 +02:00
|
|
|
);
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-08 12:50:56 +02:00
|
|
|
.disable_vary_header()
|
2020-10-19 06:51:31 +02:00
|
|
|
.allowed_methods(vec!["POST"])
|
2020-10-08 12:50:56 +02:00
|
|
|
.allowed_origin("https://www.example.com")
|
|
|
|
.allowed_origin("https://www.google.com")
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.method(Method::OPTIONS)
|
2021-03-21 23:50:26 +01:00
|
|
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "POST"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
let origins_str = resp
|
|
|
|
.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(val_as_str);
|
|
|
|
assert_eq!(Some("https://www.example.com"), origins_str);
|
2020-10-08 12:50:56 +02:00
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn test_validate_origin() {
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-10-08 12:50:56 +02:00
|
|
|
.allowed_origin("https://www.example.com")
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
|
|
}
|
|
|
|
|
2022-09-22 01:22:20 +02:00
|
|
|
#[actix_web::test]
|
|
|
|
async fn test_blocks_mismatched_origin_by_default() {
|
|
|
|
let cors = Cors::default()
|
|
|
|
.allowed_origin("https://www.example.com")
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://www.example.test"))
|
|
|
|
.to_srv_request();
|
|
|
|
|
|
|
|
let res = test::call_service(&cors, req).await;
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
|
|
assert_eq!(res.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN), None);
|
|
|
|
assert!(res
|
|
|
|
.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_METHODS)
|
|
|
|
.is_none());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_web::test]
|
|
|
|
async fn test_mismatched_origin_block_turned_off() {
|
|
|
|
let cors = Cors::default()
|
|
|
|
.allow_any_method()
|
|
|
|
.allowed_origin("https://www.example.com")
|
|
|
|
.block_on_origin_mismatch(false)
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let req = TestRequest::default()
|
|
|
|
.method(Method::OPTIONS)
|
|
|
|
.insert_header(("Origin", "https://wrong.com"))
|
|
|
|
.insert_header(("Access-Control-Request-Method", "POST"))
|
|
|
|
.to_srv_request();
|
|
|
|
let res = test::call_service(&cors, req).await;
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
|
|
assert_eq!(res.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN), None);
|
|
|
|
|
|
|
|
let req = TestRequest::get()
|
|
|
|
.insert_header(("Origin", "https://wrong.com"))
|
|
|
|
.to_srv_request();
|
|
|
|
let res = test::call_service(&cors, req).await;
|
|
|
|
assert_eq!(res.status(), StatusCode::OK);
|
|
|
|
assert_eq!(res.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN), None);
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn test_no_origin_response() {
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::permissive()
|
2020-10-08 12:50:56 +02:00
|
|
|
.disable_preflight()
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let req = TestRequest::default().method(Method::GET).to_srv_request();
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert!(resp
|
|
|
|
.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
|
|
|
.is_none());
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
2020-10-08 12:50:56 +02:00
|
|
|
.method(Method::OPTIONS)
|
|
|
|
.to_srv_request();
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(
|
2020-10-19 06:51:31 +02:00
|
|
|
Some(&b"https://www.example.com"[..]),
|
2020-10-08 12:50:56 +02:00
|
|
|
resp.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
2020-10-19 06:51:31 +02:00
|
|
|
.map(HeaderValue::as_bytes)
|
2020-10-08 12:50:56 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-10-08 12:50:56 +02:00
|
|
|
async fn validate_origin_allows_all_origins() {
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::permissive()
|
2020-10-08 12:50:56 +02:00
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header(("Origin", "https://www.example.com"))
|
|
|
|
.to_srv_request();
|
2020-10-08 12:50:56 +02:00
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-10-08 12:50:56 +02:00
|
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
|
|
}
|
2020-11-05 19:38:27 +01:00
|
|
|
|
2022-02-07 17:34:01 +01:00
|
|
|
#[actix_web::test]
|
|
|
|
async fn vary_header_on_all_handled_responses() {
|
|
|
|
let cors = Cors::permissive()
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// preflight request
|
|
|
|
let req = TestRequest::default()
|
|
|
|
.method(Method::OPTIONS)
|
|
|
|
.insert_header((header::ORIGIN, "https://www.example.com"))
|
|
|
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "GET"))
|
|
|
|
.to_srv_request();
|
|
|
|
let resp = test::call_service(&cors, req).await;
|
|
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
|
|
assert!(resp
|
|
|
|
.headers()
|
|
|
|
.contains_key(header::ACCESS_CONTROL_ALLOW_METHODS));
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(not(feature = "draft-private-network-access"))]
|
2022-02-07 17:34:01 +01:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.expect("response should have Vary header")
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
|
|
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
|
|
|
);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(feature = "draft-private-network-access")]
|
2022-10-29 00:44:21 +02:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.expect("response should have Vary header")
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
2023-12-06 14:52:22 +01:00
|
|
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Private-Network",
|
2022-10-29 00:44:21 +02:00
|
|
|
);
|
2022-02-07 17:34:01 +01:00
|
|
|
|
|
|
|
// follow-up regular request
|
|
|
|
let req = TestRequest::default()
|
|
|
|
.method(Method::PUT)
|
|
|
|
.insert_header((header::ORIGIN, "https://www.example.com"))
|
|
|
|
.to_srv_request();
|
|
|
|
let resp = test::call_service(&cors, req).await;
|
|
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(not(feature = "draft-private-network-access"))]
|
2022-02-07 17:34:01 +01:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.expect("response should have Vary header")
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
|
|
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
|
|
|
);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(feature = "draft-private-network-access")]
|
2022-10-29 00:44:21 +02:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.expect("response should have Vary header")
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
2023-12-06 14:52:22 +01:00
|
|
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Private-Network",
|
2022-10-29 00:44:21 +02:00
|
|
|
);
|
2022-02-07 17:34:01 +01:00
|
|
|
|
|
|
|
let cors = Cors::default()
|
|
|
|
.allow_any_method()
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// regular request bad origin
|
|
|
|
let req = TestRequest::default()
|
|
|
|
.method(Method::PUT)
|
|
|
|
.insert_header((header::ORIGIN, "https://www.example.com"))
|
|
|
|
.to_srv_request();
|
|
|
|
let resp = test::call_service(&cors, req).await;
|
|
|
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(not(feature = "draft-private-network-access"))]
|
2022-02-07 17:34:01 +01:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.expect("response should have Vary header")
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
|
|
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
|
|
|
);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(feature = "draft-private-network-access")]
|
2022-10-29 00:44:21 +02:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.expect("response should have Vary header")
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
2023-12-06 14:52:22 +01:00
|
|
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Private-Network",
|
2022-10-29 00:44:21 +02:00
|
|
|
);
|
2022-02-07 17:34:01 +01:00
|
|
|
|
|
|
|
// regular request no origin
|
|
|
|
let req = TestRequest::default().method(Method::PUT).to_srv_request();
|
|
|
|
let resp = test::call_service(&cors, req).await;
|
|
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(not(feature = "draft-private-network-access"))]
|
2022-02-07 17:34:01 +01:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.expect("response should have Vary header")
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
|
|
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
|
|
|
);
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(feature = "draft-private-network-access")]
|
2022-10-29 00:44:21 +02:00
|
|
|
assert_eq!(
|
|
|
|
resp.headers()
|
|
|
|
.get(header::VARY)
|
|
|
|
.expect("response should have Vary header")
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
2023-12-06 14:52:22 +01:00
|
|
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Private-Network",
|
2022-10-29 00:44:21 +02:00
|
|
|
);
|
2022-02-07 17:34:01 +01:00
|
|
|
}
|
|
|
|
|
2022-02-03 23:33:47 +01:00
|
|
|
#[actix_web::test]
|
2020-11-05 19:38:27 +01:00
|
|
|
async fn test_allow_any_origin_any_method_any_header() {
|
2021-03-21 23:50:26 +01:00
|
|
|
let cors = Cors::default()
|
2020-11-05 19:38:27 +01:00
|
|
|
.allow_any_origin()
|
|
|
|
.allow_any_method()
|
|
|
|
.allow_any_header()
|
|
|
|
.new_transform(test::ok_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "POST"))
|
|
|
|
.insert_header((header::ACCESS_CONTROL_REQUEST_HEADERS, "content-type"))
|
|
|
|
.insert_header((header::ORIGIN, "https://www.example.com"))
|
2020-11-05 19:38:27 +01:00
|
|
|
.method(Method::OPTIONS)
|
|
|
|
.to_srv_request();
|
|
|
|
|
2021-03-21 23:50:26 +01:00
|
|
|
let resp = test::call_service(&cors, req).await;
|
2020-11-05 19:38:27 +01:00
|
|
|
assert_eq!(resp.status(), StatusCode::OK);
|
|
|
|
}
|
2021-10-21 16:47:56 +02:00
|
|
|
|
|
|
|
#[actix_web::test]
|
|
|
|
async fn expose_all_request_header_values() {
|
|
|
|
let cors = Cors::permissive()
|
2022-08-07 21:56:33 +02:00
|
|
|
.new_transform(fn_service(|req: ServiceRequest| async move {
|
|
|
|
let res = req.into_response(
|
|
|
|
HttpResponse::Ok()
|
|
|
|
.insert_header((header::CONTENT_DISPOSITION, "test disposition"))
|
|
|
|
.finish(),
|
|
|
|
);
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}))
|
2021-10-21 16:47:56 +02:00
|
|
|
.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"))
|
|
|
|
.to_srv_request();
|
|
|
|
|
2022-08-07 21:56:33 +02:00
|
|
|
let res = test::call_service(&cors, req).await;
|
2021-10-21 16:47:56 +02:00
|
|
|
|
2022-08-07 21:56:33 +02:00
|
|
|
let cd_hdr = res
|
2021-10-21 16:47:56 +02:00
|
|
|
.headers()
|
|
|
|
.get(header::ACCESS_CONTROL_EXPOSE_HEADERS)
|
|
|
|
.unwrap()
|
|
|
|
.to_str()
|
2022-08-07 21:56:33 +02:00
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert!(cd_hdr.contains("content-disposition"));
|
|
|
|
assert!(cd_hdr.contains("access-control-allow-origin"));
|
2021-10-21 16:47:56 +02:00
|
|
|
}
|
2022-10-29 00:44:21 +02:00
|
|
|
|
2023-04-09 20:56:43 +02:00
|
|
|
#[cfg(feature = "draft-private-network-access")]
|
2022-10-29 00:44:21 +02:00
|
|
|
#[actix_web::test]
|
|
|
|
async fn private_network_access() {
|
|
|
|
let cors = Cors::permissive()
|
|
|
|
.allowed_origin("https://public.site")
|
2023-04-09 20:56:43 +02:00
|
|
|
.allow_private_network_access()
|
2022-10-29 00:44:21 +02:00
|
|
|
.new_transform(fn_service(|req: ServiceRequest| async move {
|
|
|
|
let res = req.into_response(
|
|
|
|
HttpResponse::Ok()
|
|
|
|
.insert_header((header::CONTENT_DISPOSITION, "test disposition"))
|
|
|
|
.finish(),
|
|
|
|
);
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}))
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header((header::ORIGIN, "https://public.site"))
|
|
|
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "POST"))
|
|
|
|
.insert_header((header::ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"))
|
|
|
|
.to_srv_request();
|
|
|
|
let res = test::call_service(&cors, req).await;
|
|
|
|
assert!(res.headers().contains_key("access-control-allow-origin"));
|
|
|
|
|
|
|
|
let req = TestRequest::default()
|
|
|
|
.insert_header((header::ORIGIN, "https://public.site"))
|
|
|
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "POST"))
|
|
|
|
.insert_header((header::ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"))
|
2023-04-09 20:56:43 +02:00
|
|
|
.insert_header(("Access-Control-Request-Private-Network", "true"))
|
2022-10-29 00:44:21 +02:00
|
|
|
.to_srv_request();
|
|
|
|
let res = test::call_service(&cors, req).await;
|
|
|
|
assert!(res.headers().contains_key("access-control-allow-origin"));
|
|
|
|
assert!(res
|
|
|
|
.headers()
|
2023-04-09 20:56:43 +02:00
|
|
|
.contains_key("access-control-allow-private-network"));
|
2022-10-29 00:44:21 +02:00
|
|
|
}
|