mirror of
https://github.com/actix/actix-extras.git
synced 2025-06-26 10:27:42 +02:00
migrate to actix-web beta 14 (#209)
This commit is contained in:
@ -4,11 +4,14 @@ use std::{
|
||||
|
||||
use actix_utils::future::{self, Ready};
|
||||
use actix_web::{
|
||||
body::MessageBody,
|
||||
body::{EitherBody, MessageBody},
|
||||
dev::{RequestHead, Service, ServiceRequest, ServiceResponse, Transform},
|
||||
error::{Error, Result},
|
||||
http::{self, header::HeaderName, Error as HttpError, HeaderValue, Method, Uri},
|
||||
Either,
|
||||
error::HttpError,
|
||||
http::{
|
||||
header::{HeaderName, HeaderValue},
|
||||
Method, Uri,
|
||||
},
|
||||
Either, Error, Result,
|
||||
};
|
||||
use log::error;
|
||||
use once_cell::sync::Lazy;
|
||||
@ -20,7 +23,7 @@ use crate::{AllOrSome, CorsError, CorsMiddleware, Inner, OriginFn};
|
||||
/// Additionally, always causes first error (if any) to be reported during initialization.
|
||||
fn cors<'a>(
|
||||
inner: &'a mut Rc<Inner>,
|
||||
err: &Option<Either<http::Error, CorsError>>,
|
||||
err: &Option<Either<HttpError, CorsError>>,
|
||||
) -> Option<&'a mut Inner> {
|
||||
if err.is_some() {
|
||||
return None;
|
||||
@ -74,7 +77,7 @@ static ALL_METHODS_SET: Lazy<HashSet<Method>> = Lazy::new(|| {
|
||||
#[derive(Debug)]
|
||||
pub struct Cors {
|
||||
inner: Rc<Inner>,
|
||||
error: Option<Either<http::Error, CorsError>>,
|
||||
error: Option<Either<HttpError, CorsError>>,
|
||||
}
|
||||
|
||||
impl Cors {
|
||||
@ -490,7 +493,7 @@ where
|
||||
B: MessageBody + 'static,
|
||||
B::Error: StdError,
|
||||
{
|
||||
type Response = ServiceResponse;
|
||||
type Response = ServiceResponse<EitherBody<B>>;
|
||||
type Error = Error;
|
||||
type InitError = ();
|
||||
type Transform = CorsMiddleware<S>;
|
||||
@ -571,15 +574,13 @@ where
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::convert::{Infallible, TryInto};
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_web::{
|
||||
body::{BodySize, MessageBody},
|
||||
body,
|
||||
dev::{fn_service, Transform},
|
||||
http::{HeaderName, StatusCode},
|
||||
http::{header::HeaderName, StatusCode},
|
||||
test::{self, TestRequest},
|
||||
web::{Bytes, HttpResponse},
|
||||
web::HttpResponse,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
@ -634,23 +635,8 @@ mod test {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn middleware_generic_over_body_type() {
|
||||
struct Foo;
|
||||
|
||||
impl MessageBody for Foo {
|
||||
type Error = std::io::Error;
|
||||
fn size(&self) -> BodySize {
|
||||
BodySize::None
|
||||
}
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Bytes, Self::Error>>> {
|
||||
Poll::Ready(None)
|
||||
}
|
||||
}
|
||||
|
||||
let srv = fn_service(|req: ServiceRequest| async move {
|
||||
Ok(req.into_response(HttpResponse::Ok().message_body(Foo)?))
|
||||
Ok(req.into_response(HttpResponse::Ok().message_body(body::None::new())?))
|
||||
});
|
||||
|
||||
Cors::default().new_transform(srv).await.unwrap();
|
||||
|
@ -7,35 +7,35 @@ use derive_more::{Display, Error};
|
||||
#[non_exhaustive]
|
||||
pub enum CorsError {
|
||||
/// Allowed origin argument must not be wildcard (`*`).
|
||||
#[display(fmt = "`allowed_origin` argument must not be wildcard (`*`).")]
|
||||
#[display(fmt = "`allowed_origin` argument must not be wildcard (`*`)")]
|
||||
WildcardOrigin,
|
||||
|
||||
/// Request header `Origin` is required but was not provided.
|
||||
#[display(fmt = "Request header `Origin` is required but was not provided.")]
|
||||
#[display(fmt = "Request header `Origin` is required but was not provided")]
|
||||
MissingOrigin,
|
||||
|
||||
/// Request header `Access-Control-Request-Method` is required but is missing.
|
||||
#[display(fmt = "Request header `Access-Control-Request-Method` is required but is missing.")]
|
||||
#[display(fmt = "Request header `Access-Control-Request-Method` is required but is missing")]
|
||||
MissingRequestMethod,
|
||||
|
||||
/// Request header `Access-Control-Request-Method` has an invalid value.
|
||||
#[display(fmt = "Request header `Access-Control-Request-Method` has an invalid value.")]
|
||||
#[display(fmt = "Request header `Access-Control-Request-Method` has an invalid value")]
|
||||
BadRequestMethod,
|
||||
|
||||
/// Request header `Access-Control-Request-Headers` has an invalid value.
|
||||
#[display(fmt = "Request header `Access-Control-Request-Headers` has an invalid value.")]
|
||||
#[display(fmt = "Request header `Access-Control-Request-Headers` has an invalid value")]
|
||||
BadRequestHeaders,
|
||||
|
||||
/// Origin is not allowed to make this request.
|
||||
#[display(fmt = "Origin is not allowed to make this request.")]
|
||||
#[display(fmt = "Origin is not allowed to make this request")]
|
||||
OriginNotAllowed,
|
||||
|
||||
/// Request method is not allowed.
|
||||
#[display(fmt = "Requested method is not allowed.")]
|
||||
#[display(fmt = "Requested method is not allowed")]
|
||||
MethodNotAllowed,
|
||||
|
||||
/// One or more request headers are not allowed.
|
||||
#[display(fmt = "One or more request headers are not allowed.")]
|
||||
#[display(fmt = "One or more request headers are not allowed")]
|
||||
HeadersNotAllowed,
|
||||
}
|
||||
|
||||
@ -45,6 +45,6 @@ impl ResponseError for CorsError {
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
HttpResponse::with_body(StatusCode::BAD_REQUEST, self.to_string().into())
|
||||
HttpResponse::with_body(StatusCode::BAD_REQUEST, self.to_string()).map_into_boxed_body()
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +205,10 @@ mod test {
|
||||
|
||||
use actix_web::{
|
||||
dev::Transform,
|
||||
http::{header, HeaderValue, Method, StatusCode},
|
||||
http::{
|
||||
header::{self, HeaderValue},
|
||||
Method, StatusCode,
|
||||
},
|
||||
test::{self, TestRequest},
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::{collections::HashSet, convert::TryInto, error::Error as StdError, rc::Rc};
|
||||
|
||||
use actix_utils::future::{ok, Either, Ready};
|
||||
use actix_utils::future::ok;
|
||||
use actix_web::{
|
||||
body::{AnyBody, MessageBody},
|
||||
body::{EitherBody, MessageBody},
|
||||
dev::{Service, ServiceRequest, ServiceResponse},
|
||||
error::{Error, Result},
|
||||
http::{
|
||||
@ -11,7 +11,7 @@ use actix_web::{
|
||||
},
|
||||
HttpResponse,
|
||||
};
|
||||
use futures_util::future::{FutureExt as _, LocalBoxFuture, TryFutureExt as _};
|
||||
use futures_util::future::{FutureExt as _, LocalBoxFuture};
|
||||
use log::debug;
|
||||
|
||||
use crate::{builder::intersperse_header_values, AllOrSome, Inner};
|
||||
@ -134,11 +134,6 @@ impl<S> CorsMiddleware<S> {
|
||||
}
|
||||
}
|
||||
|
||||
type CorsMiddlewareServiceFuture = Either<
|
||||
Ready<Result<ServiceResponse, Error>>,
|
||||
LocalBoxFuture<'static, Result<ServiceResponse, Error>>,
|
||||
>;
|
||||
|
||||
impl<S, B> Service<ServiceRequest> for CorsMiddleware<S>
|
||||
where
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
@ -146,9 +141,9 @@ where
|
||||
B: MessageBody + 'static,
|
||||
B::Error: StdError,
|
||||
{
|
||||
type Response = ServiceResponse;
|
||||
type Response = ServiceResponse<EitherBody<B>>;
|
||||
type Error = Error;
|
||||
type Future = CorsMiddlewareServiceFuture;
|
||||
type Future = LocalBoxFuture<'static, Result<ServiceResponse<EitherBody<B>>, Error>>;
|
||||
|
||||
actix_service::forward_ready!(service);
|
||||
|
||||
@ -156,7 +151,7 @@ where
|
||||
if self.inner.preflight && req.method() == Method::OPTIONS {
|
||||
let inner = Rc::clone(&self.inner);
|
||||
let res = Self::handle_preflight(&inner, req);
|
||||
Either::left(ok(res))
|
||||
ok(res.map_into_right_body()).boxed_local()
|
||||
} else {
|
||||
let origin = req.headers().get(header::ORIGIN).cloned();
|
||||
|
||||
@ -164,27 +159,37 @@ where
|
||||
// Only check requests with a origin header.
|
||||
if let Err(err) = self.inner.validate_origin(req.head()) {
|
||||
debug!("origin validation failed; inner service is not called");
|
||||
return Either::left(ok(req.error_response(err)));
|
||||
return ok(req.error_response(err).map_into_right_body()).boxed_local();
|
||||
}
|
||||
}
|
||||
|
||||
let (req, pl) = req.into_parts();
|
||||
let req2 = req.clone();
|
||||
let req = ServiceRequest::from_parts(req, pl);
|
||||
|
||||
let inner = Rc::clone(&self.inner);
|
||||
let fut = self.service.call(req);
|
||||
|
||||
let res = async move {
|
||||
async move {
|
||||
let res = fut.await;
|
||||
|
||||
if origin.is_some() {
|
||||
let res = res?;
|
||||
let res = match res {
|
||||
Ok(res) => res,
|
||||
Err(err) => {
|
||||
let res = HttpResponse::from_error(err);
|
||||
let res = ServiceResponse::new(req2, res);
|
||||
return Ok(res.map_into_right_body());
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self::augment_response(&inner, res))
|
||||
} else {
|
||||
res
|
||||
}
|
||||
.map(|res| res.map_into_left_body())
|
||||
}
|
||||
.map_ok(|res| res.map_body(|_, body| AnyBody::new_boxed(body)))
|
||||
.boxed_local();
|
||||
|
||||
Either::right(res)
|
||||
.boxed_local()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user