diff --git a/actix_cors/enum.CorsError.html b/actix_cors/enum.CorsError.html index 150f94e3c..4fbe25378 100644 --- a/actix_cors/enum.CorsError.html +++ b/actix_cors/enum.CorsError.html @@ -6,7 +6,7 @@ logo

CorsError

logo
#[non_exhaustive]
+    

Enum actix_cors::CorsError

source · []
#[non_exhaustive]
 pub enum CorsError {
     WildcardOrigin,
     MissingOrigin,
@@ -25,16 +25,16 @@ pub enum CorsError {
 

OriginNotAllowed

Origin is not allowed to make this request.

MethodNotAllowed

Request method is not allowed.

HeadersNotAllowed

One or more request headers are not allowed.

-

Trait Implementations

Returns a copy of the value. Read more

+

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

-

Formats the value using the given formatter. Read more

-

Formats the value using the given formatter. Read more

-

The lower-level source of this error, if any. Read more

+

Formats the value using the given formatter. Read more

+

Formats the value using the given formatter. Read more

+

The lower-level source of this error, if any. Read more

🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. Read more

👎 Deprecated since 1.42.0:

use the Display impl or to_string()

👎 Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

-

Returns appropriate status code for error. Read more

-

Creates full response for error. Read more

+

Returns appropriate status code for error. Read more

+

Creates full response for error. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

diff --git a/src/actix_cors/error.rs.html b/src/actix_cors/error.rs.html index 08c5dd32e..7076ddc23 100644 --- a/src/actix_cors/error.rs.html +++ b/src/actix_cors/error.rs.html @@ -55,10 +55,16 @@ 48 49 50 +51 +52 +53 +54
use actix_web::{http::StatusCode, HttpResponse, ResponseError};
 
 use derive_more::{Display, Error};
 
+use crate::inner::add_vary_header;
+
 /// Errors that can occur when processing CORS guarded requests.
 #[derive(Debug, Clone, Display, Error)]
 #[non_exhaustive]
@@ -102,7 +108,9 @@
     }
 
     fn error_response(&self) -> HttpResponse {
-        HttpResponse::with_body(StatusCode::BAD_REQUEST, self.to_string()).map_into_boxed_body()
+        let mut res = HttpResponse::with_body(self.status_code(), self.to_string());
+        add_vary_header(res.headers_mut());
+        res.map_into_boxed_body()
     }
 }
 
diff --git a/src/actix_cors/inner.rs.html b/src/actix_cors/inner.rs.html index bd5171df3..2a87c90c9 100644 --- a/src/actix_cors/inner.rs.html +++ b/src/actix_cors/inner.rs.html @@ -335,13 +335,65 @@ 328 329 330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382
use std::{collections::HashSet, convert::TryFrom, convert::TryInto, fmt, rc::Rc};
 
 use actix_web::{
     dev::RequestHead,
     error::Result,
     http::{
-        header::{self, HeaderName, HeaderValue},
+        header::{self, HeaderMap, HeaderName, HeaderValue},
         Method,
     },
 };
@@ -536,6 +588,25 @@
     }
 }
 
+/// Add CORS related request headers to response's Vary header.
+///
+/// See <https://fetch.spec.whatwg.org/#cors-protocol-and-http-caches>.
+pub(crate) fn add_vary_header(headers: &mut HeaderMap) {
+    let value = match headers.get(header::VARY) {
+        Some(hdr) => {
+            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");
+            val.try_into().unwrap()
+        }
+        None => HeaderValue::from_static(
+            "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
+        ),
+    };
+
+    headers.insert(header::VARY, value);
+}
+
 #[cfg(test)]
 mod test {
     use std::rc::Rc;
@@ -664,6 +735,39 @@
         let resp = test::call_service(&cors, req).await;
         assert_eq!(resp.status(), StatusCode::OK);
     }
+
+    #[actix_web::test]
+    async fn allow_fn_origin_equals_head_origin() {
+        let cors = Cors::default()
+            .allowed_origin_fn(|origin, head| {
+                let head_origin = head
+                    .headers()
+                    .get(header::ORIGIN)
+                    .expect("unwrapping origin header should never fail in allowed_origin_fn");
+                assert!(origin == head_origin);
+                true
+            })
+            .allow_any_method()
+            .allow_any_header()
+            .new_transform(test::simple_service(StatusCode::NO_CONTENT))
+            .await
+            .unwrap();
+
+        let req = TestRequest::default()
+            .method(Method::OPTIONS)
+            .insert_header(("Origin", "https://www.example.com"))
+            .insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "POST"))
+            .to_srv_request();
+        let resp = test::call_service(&cors, req).await;
+        assert_eq!(resp.status(), StatusCode::OK);
+
+        let req = TestRequest::default()
+            .method(Method::GET)
+            .insert_header(("Origin", "https://www.example.com"))
+            .to_srv_request();
+        let resp = test::call_service(&cors, req).await;
+        assert_eq!(resp.status(), StatusCode::NO_CONTENT);
+    }
 }
 
diff --git a/src/actix_cors/middleware.rs.html b/src/actix_cors/middleware.rs.html index 16a1a747a..e89642f77 100644 --- a/src/actix_cors/middleware.rs.html +++ b/src/actix_cors/middleware.rs.html @@ -231,24 +231,7 @@ 224 225 226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -
use std::{collections::HashSet, convert::TryInto, rc::Rc};
+
use std::{collections::HashSet, rc::Rc};
 
 use actix_utils::future::ok;
 use actix_web::{
@@ -263,7 +246,7 @@
 use futures_util::future::{FutureExt as _, LocalBoxFuture};
 use log::debug;
 
-use crate::{builder::intersperse_header_values, AllOrSome, Inner};
+use crate::{builder::intersperse_header_values, inner::add_vary_header, AllOrSome, Inner};
 
 /// Service wrapper for Cross-Origin Resource Sharing support.
 ///
@@ -317,7 +300,9 @@
             res.insert_header((header::ACCESS_CONTROL_MAX_AGE, max_age.to_string()));
         }
 
-        let res = res.finish();
+        let mut res = res.finish();
+        add_vary_header(res.headers_mut());
+
         req.into_response(res)
     }
 
@@ -366,21 +351,7 @@
         }
 
         if inner.vary_header {
-            let value = match res.headers_mut().get(header::VARY) {
-                Some(hdr) => {
-                    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",
-                    );
-                    val.try_into().unwrap()
-                }
-                None => HeaderValue::from_static(
-                    "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
-                ),
-            };
-
-            res.headers_mut().insert(header::VARY, value);
+            add_vary_header(res.headers_mut());
         }
 
         res
@@ -422,12 +393,7 @@
             async move {
                 let res = fut.await;
 
-                if origin.is_some() {
-                    Ok(Self::augment_response(&inner, res?))
-                } else {
-                    res.map_err(Into::into)
-                }
-                .map(|res| res.map_into_left_body())
+                Ok(Self::augment_response(&inner, res?).map_into_left_body())
             }
             .boxed_local()
         }