Enum actix_cors::CorsError
source · [−]#[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
sourceimpl Clone for CorsError
impl Clone for CorsError
sourcefn clone(&self) -> CorsError
fn clone(&self) -> CorsError
Returns a copy of the value. Read more
+Trait Implementations
sourceimpl Error for CorsError
impl Error for CorsError
1.30.0 · sourcefn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
The lower-level source of this error, if any. Read more
sourcefn backtrace(&self) -> Option<&Backtrace>
fn backtrace(&self) -> Option<&Backtrace>
backtrace
)Returns a stack backtrace, if available, of where this error occurred. Read more
1.0.0 · sourcefn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
sourceimpl ResponseError for CorsError
impl ResponseError for CorsError
sourcefn status_code(&self) -> StatusCode
fn status_code(&self) -> StatusCode
Returns appropriate status code for error. Read more
-sourcefn error_response(&self) -> HttpResponse
fn error_response(&self) -> HttpResponse
Creates full response for error. Read more
+sourceimpl ResponseError for CorsError
impl ResponseError for CorsError
sourcefn status_code(&self) -> StatusCode
fn status_code(&self) -> StatusCode
Returns appropriate status code for error. Read more
+sourcefn error_response(&self) -> HttpResponse
fn error_response(&self) -> HttpResponse
Creates full response for error. Read more
Auto Trait Implementations
impl RefUnwindSafe for CorsError
impl Send for CorsError
impl Sync for CorsError
impl Unpin for CorsError
impl UnwindSafe for CorsError
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcepub fn borrow_mut(&mut self) -> &mut T
pub fn borrow_mut(&mut self) -> &mut T
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 +54use 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()
}
}
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);
+ }
}
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()
}