upgrade ntex 0.5 release

This commit is contained in:
Nikolay Kim 2021-12-21 01:24:04 +06:00
parent 74148e3ddf
commit 6ec85aa238
10 changed files with 124 additions and 200 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "ntex-cors" name = "ntex-cors"
version = "0.1.0" version = "0.2.0"
authors = ["ntex contributors <team@ntex.rs>"] authors = ["ntex contributors <team@ntex.rs>"]
description = "Cross-origin resource sharing (CORS) for ntex applications." description = "Cross-origin resource sharing (CORS) for ntex applications."
readme = "README.md" readme = "README.md"
@ -16,6 +16,9 @@ name = "ntex_cors"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
ntex = "0.3.18" ntex = "0.5.10"
derive_more = "0.99.11" derive_more = "0.99"
futures = "0.3.13" futures = "0.3"
[dev-dependencies]
ntex = { version = "0.5", features=["tokio"] }

View file

@ -45,19 +45,19 @@
//! endpoint. //! endpoint.
//! //!
//! Cors middleware automatically handle *OPTIONS* preflight request. //! Cors middleware automatically handle *OPTIONS* preflight request.
use std::collections::HashSet;
use std::convert::TryFrom;
use std::iter::FromIterator;
use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::{
collections::HashSet, convert::TryFrom, iter::FromIterator, marker::PhantomData, rc::Rc,
};
use derive_more::Display; use derive_more::Display;
use futures::future::{ok, Either, FutureExt, LocalBoxFuture, Ready}; use futures::future::{ok, Either, FutureExt, LocalBoxFuture, Ready};
use ntex::http::header::{self, HeaderName, HeaderValue}; use ntex::http::header::{self, HeaderName, HeaderValue};
use ntex::http::{error::HttpError, HeaderMap, Method, RequestHead, StatusCode, Uri}; use ntex::http::{error::HttpError, HeaderMap, Method, RequestHead, StatusCode, Uri};
use ntex::service::{Service, Transform}; use ntex::service::{Service, Transform};
use ntex::web::dev::{WebRequest, WebResponse}; use ntex::web::{
use ntex::web::{DefaultError, ErrorRenderer, HttpResponse, WebResponseError}; DefaultError, ErrorRenderer, HttpResponse, WebRequest, WebResponse, WebResponseError,
};
/// A set of errors that can occur during processing CORS /// A set of errors that can occur during processing CORS
#[derive(Debug, Display)] #[derive(Debug, Display)]
@ -196,7 +196,7 @@ impl Cors {
} }
/// Build a new CORS default middleware /// Build a new CORS default middleware
pub fn default() -> CorsFactory { pub fn default<Err>() -> CorsFactory<Err> {
let inner = Inner { let inner = Inner {
origins: AllOrSome::default(), origins: AllOrSome::default(),
origins_str: None, origins_str: None,
@ -220,7 +220,7 @@ impl Cors {
supports_credentials: false, supports_credentials: false,
vary_header: true, vary_header: true,
}; };
CorsFactory { inner: Rc::new(inner) } CorsFactory { inner: Rc::new(inner), _t: PhantomData }
} }
/// Add an origin that are allowed to make requests. /// Add an origin that are allowed to make requests.
@ -462,7 +462,7 @@ impl Cors {
} }
/// Construct cors middleware /// Construct cors middleware
pub fn finish(self) -> CorsFactory { pub fn finish<Err>(self) -> CorsFactory<Err> {
let mut slf = if !self.methods { let mut slf = if !self.methods {
self.allowed_methods(vec![ self.allowed_methods(vec![
Method::GET, Method::GET,
@ -503,7 +503,7 @@ impl Cors {
); );
} }
CorsFactory { inner: Rc::new(cors) } CorsFactory { inner: Rc::new(cors), _t: PhantomData }
} }
} }
@ -716,27 +716,20 @@ impl Inner {
/// ///
/// The Cors struct contains the settings for CORS requests to be validated and /// The Cors struct contains the settings for CORS requests to be validated and
/// for responses to be generated. /// for responses to be generated.
pub struct CorsFactory { pub struct CorsFactory<Err> {
inner: Rc<Inner>, inner: Rc<Inner>,
_t: PhantomData<Err>,
} }
impl<S, Err> Transform<S> for CorsFactory impl<S, Err> Transform<S> for CorsFactory<Err>
where where
S: Service<Request = WebRequest<Err>, Response = WebResponse>, S: Service<WebRequest<Err>, Response = WebResponse>,
S::Future: 'static, S::Future: 'static,
Err: ErrorRenderer,
Err::Container: From<S::Error>,
CorsError: WebResponseError<Err>,
{ {
type Request = WebRequest<Err>; type Service = CorsMiddleware<S>;
type Response = WebResponse;
type Error = S::Error;
type InitError = ();
type Transform = CorsMiddleware<S>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Service {
ok(CorsMiddleware { service, inner: self.inner.clone() }) CorsMiddleware { service, inner: self.inner.clone() }
} }
} }
@ -750,15 +743,14 @@ pub struct CorsMiddleware<S> {
inner: Rc<Inner>, inner: Rc<Inner>,
} }
impl<S, Err> Service for CorsMiddleware<S> impl<S, Err> Service<WebRequest<Err>> for CorsMiddleware<S>
where where
S: Service<Request = WebRequest<Err>, Response = WebResponse>, S: Service<WebRequest<Err>, Response = WebResponse>,
S::Future: 'static, S::Future: 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
Err::Container: From<S::Error>, Err::Container: From<S::Error>,
CorsError: WebResponseError<Err>, CorsError: WebResponseError<Err>,
{ {
type Request = WebRequest<Err>;
type Response = WebResponse; type Response = WebResponse;
type Error = S::Error; type Error = S::Error;
type Future = Either< type Future = Either<
@ -803,19 +795,20 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use ntex::service::{fn_service, Transform}; use ntex::service::{fn_service, Transform};
use ntex::web::test::{self, TestRequest}; use ntex::web::{self, test, test::TestRequest};
use super::*; use super::*;
#[ntex::test] #[ntex::test]
#[should_panic(expected = "Credentials are allowed, but the Origin is set to")] #[should_panic(expected = "Credentials are allowed, but the Origin is set to")]
async fn cors_validates_illegal_allow_credentials() { async fn cors_validates_illegal_allow_credentials() {
let _cors = Cors::new().supports_credentials().send_wildcard().finish(); let _cors =
Cors::new().supports_credentials().send_wildcard().finish::<web::DefaultError>();
} }
#[ntex::test] #[ntex::test]
async fn validate_origin_allows_all_origins() { async fn validate_origin_allows_all_origins() {
let cors = Cors::new().finish().new_transform(test::ok_service()).await.unwrap(); let cors = Cors::new().finish().new_transform(test::ok_service());
let req = let req =
TestRequest::with_header("Origin", "https://www.example.com").to_srv_request(); TestRequest::with_header("Origin", "https://www.example.com").to_srv_request();
@ -825,7 +818,7 @@ mod tests {
#[ntex::test] #[ntex::test]
async fn default() { async fn default() {
let cors = Cors::default().new_transform(test::ok_service()).await.unwrap(); let cors = Cors::default().new_transform(test::ok_service());
let req = let req =
TestRequest::with_header("Origin", "https://www.example.com").to_srv_request(); TestRequest::with_header("Origin", "https://www.example.com").to_srv_request();
@ -842,9 +835,7 @@ mod tests {
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT]) .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
.allowed_header(header::CONTENT_TYPE) .allowed_header(header::CONTENT_TYPE)
.finish() .finish()
.new_transform(test::ok_service()) .new_transform(test::ok_service());
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS) .method(Method::OPTIONS)
@ -923,9 +914,7 @@ mod tests {
let cors = Cors::new() let cors = Cors::new()
.allowed_origin("https://www.example.com") .allowed_origin("https://www.example.com")
.finish() .finish()
.new_transform(test::ok_service()) .new_transform(test::ok_service::<web::DefaultError>());
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.unknown.com") let req = TestRequest::with_header("Origin", "https://www.unknown.com")
.method(Method::GET) .method(Method::GET)
@ -940,9 +929,7 @@ mod tests {
let cors = Cors::new() let cors = Cors::new()
.allowed_origin("https://www.example.com") .allowed_origin("https://www.example.com")
.finish() .finish()
.new_transform(test::ok_service()) .new_transform(test::ok_service());
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::GET) .method(Method::GET)
@ -954,12 +941,7 @@ mod tests {
#[ntex::test] #[ntex::test]
async fn test_no_origin_response() { async fn test_no_origin_response() {
let cors = Cors::new() let cors = Cors::new().disable_preflight().finish().new_transform(test::ok_service());
.disable_preflight()
.finish()
.new_transform(test::ok_service())
.await
.unwrap();
let req = TestRequest::default().method(Method::GET).to_srv_request(); let req = TestRequest::default().method(Method::GET).to_srv_request();
let resp = test::call_service(&cors, req).await; let resp = test::call_service(&cors, req).await;
@ -987,9 +969,7 @@ mod tests {
.expose_headers(exposed_headers.clone()) .expose_headers(exposed_headers.clone())
.allowed_header(header::CONTENT_TYPE) .allowed_header(header::CONTENT_TYPE)
.finish() .finish()
.new_transform(test::ok_service()) .new_transform(test::ok_service());
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS) .method(Method::OPTIONS)
@ -1033,9 +1013,7 @@ mod tests {
ok::<_, std::convert::Infallible>(req.into_response( ok::<_, std::convert::Infallible>(req.into_response(
HttpResponse::Ok().header(header::VARY, "Accept").finish(), HttpResponse::Ok().header(header::VARY, "Accept").finish(),
)) ))
})) }));
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS) .method(Method::OPTIONS)
.to_srv_request(); .to_srv_request();
@ -1050,9 +1028,7 @@ mod tests {
.allowed_origin("https://www.example.com") .allowed_origin("https://www.example.com")
.allowed_origin("https://www.google.com") .allowed_origin("https://www.google.com")
.finish() .finish()
.new_transform(test::ok_service()) .new_transform(test::ok_service());
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS) .method(Method::OPTIONS)
@ -1073,9 +1049,7 @@ mod tests {
.allowed_origin("https://example.org") .allowed_origin("https://example.org")
.allowed_methods(vec![Method::GET]) .allowed_methods(vec![Method::GET])
.finish() .finish()
.new_transform(test::ok_service()) .new_transform(test::ok_service());
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://example.com") let req = TestRequest::with_header("Origin", "https://example.com")
.method(Method::GET) .method(Method::GET)
@ -1105,9 +1079,7 @@ mod tests {
.allowed_origin("https://example.org") .allowed_origin("https://example.org")
.allowed_methods(vec![Method::GET]) .allowed_methods(vec![Method::GET])
.finish() .finish()
.new_transform(test::ok_service()) .new_transform(test::ok_service());
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://example.com") let req = TestRequest::with_header("Origin", "https://example.com")
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "GET") .header(header::ACCESS_CONTROL_REQUEST_METHOD, "GET")

View file

@ -18,16 +18,16 @@ name = "ntex_files"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
ntex = "0.3.18" ntex = "0.5.10"
bitflags = "1.2" bitflags = "1.3"
futures = "0.3" futures = "0.3"
derive_more = "0.99.11" derive_more = "0.99"
hyperx = "1.0.0" hyperx = "1.0.0"
log = "0.4" log = "0.4"
mime = "0.3" mime = "0.3"
mime_guess = "2.0.1" mime_guess = "2.0.1"
percent-encoding = "2.1" percent-encoding = "2.1"
v_htmlescape = "0.13" v_htmlescape = "0.14.1"
[dev-dependencies] [dev-dependencies]
ntex = { version = "0.3.18", features=["openssl", "compress"] } ntex = { version = "0.5", features=["tokio", "openssl", "compress"] }

View file

@ -17,10 +17,10 @@ use ntex::router::{ResourceDef, ResourcePath};
use ntex::service::boxed::{self, BoxService, BoxServiceFactory}; use ntex::service::boxed::{self, BoxService, BoxServiceFactory};
use ntex::service::{IntoServiceFactory, Service, ServiceFactory}; use ntex::service::{IntoServiceFactory, Service, ServiceFactory};
use ntex::util::Bytes; use ntex::util::Bytes;
use ntex::web::dev::{WebRequest, WebResponse, WebServiceConfig, WebServiceFactory}; use ntex::web::dev::{WebServiceConfig, WebServiceFactory};
use ntex::web::error::ErrorRenderer; use ntex::web::error::ErrorRenderer;
use ntex::web::guard::Guard; use ntex::web::guard::Guard;
use ntex::web::{self, FromRequest, HttpRequest, HttpResponse}; use ntex::web::{self, FromRequest, HttpRequest, HttpResponse, WebRequest, WebResponse};
use percent_encoding::{utf8_percent_encode, CONTROLS}; use percent_encoding::{utf8_percent_encode, CONTROLS};
use v_htmlescape::escape as escape_html_entity; use v_htmlescape::escape as escape_html_entity;
@ -366,13 +366,9 @@ impl<Err: ErrorRenderer> Files<Err> {
/// Sets default handler which is used when no matched file could be found. /// Sets default handler which is used when no matched file could be found.
pub fn default_handler<F, U>(mut self, f: F) -> Self pub fn default_handler<F, U>(mut self, f: F) -> Self
where where
F: IntoServiceFactory<U>, F: IntoServiceFactory<U, WebRequest<Err>>,
U: ServiceFactory< U: ServiceFactory<WebRequest<Err>, Response = WebResponse, Error = Err::Container>
Config = (), + 'static,
Request = WebRequest<Err>,
Response = WebResponse,
Error = Err::Container,
> + 'static,
{ {
// create and configure default resource // create and configure default resource
self.default = Some(Rc::new(boxed::factory(f.into_factory().map_init_err(|_| ())))); self.default = Some(Rc::new(boxed::factory(f.into_factory().map_init_err(|_| ()))));
@ -399,15 +395,13 @@ where
} }
} }
impl<Err> ServiceFactory for Files<Err> impl<Err> ServiceFactory<WebRequest<Err>> for Files<Err>
where where
Err: ErrorRenderer, Err: ErrorRenderer,
Err::Container: From<FilesError>, Err::Container: From<FilesError>,
{ {
type Request = WebRequest<Err>;
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
type Config = ();
type Service = FilesService<Err>; type Service = FilesService<Err>;
type InitError = (); type InitError = ();
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::InitError>>; type Future = LocalBoxFuture<'static, Result<Self::Service, Self::InitError>>;
@ -475,12 +469,11 @@ where
} }
} }
impl<Err> Service for FilesService<Err> impl<Err> Service<WebRequest<Err>> for FilesService<Err>
where where
Err: ErrorRenderer, Err: ErrorRenderer,
Err::Container: From<FilesError>, Err::Container: From<FilesError>,
{ {
type Request = WebRequest<Err>;
type Response = WebResponse; type Response = WebResponse;
type Error = Err::Container; type Error = Err::Container;
type Future = Either< type Future = Either<

View file

@ -21,10 +21,13 @@ default = ["cookie-policy"]
cookie-policy = ["cookie/secure", "ntex/cookie"] cookie-policy = ["cookie/secure", "ntex/cookie"]
[dependencies] [dependencies]
ntex = "0.3.18" ntex = "0.5.10"
futures = "0.3.13" futures = "0.3"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
derive_more = "0.99.11" derive_more = "0.99"
cookie = { version = "0.15", features = ["private"] } cookie = { version = "0.16", features = ["private"] }
time = { version = "0.2.5", default-features = false, features = ["std"] } time = { version = "0.3", default-features = false, features = ["std"] }
[dev-dependencies]
ntex = { version = "0.5", features=["tokio"] }

View file

@ -44,12 +44,9 @@
//! .service(web::resource("/login.html").to(login)) //! .service(web::resource("/login.html").to(login))
//! .service(web::resource("/logout.html").to(logout)); //! .service(web::resource("/logout.html").to(logout));
//! ``` //! ```
use std::convert::Infallible;
use std::future::Future;
use std::marker::PhantomData;
use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::SystemTime; use std::time::SystemTime;
use std::{convert::Infallible, future::Future, rc::Rc};
use cookie::{Cookie, CookieJar, Key, SameSite}; use cookie::{Cookie, CookieJar, Key, SameSite};
use derive_more::{Display, From}; use derive_more::{Display, From};
@ -62,8 +59,10 @@ use ntex::http::header::{self, HeaderValue};
use ntex::http::{HttpMessage, Payload}; use ntex::http::{HttpMessage, Payload};
use ntex::service::{Service, Transform}; use ntex::service::{Service, Transform};
use ntex::util::Extensions; use ntex::util::Extensions;
use ntex::web::dev::{WebRequest, WebResponse}; use ntex::web::{
use ntex::web::{DefaultError, ErrorRenderer, FromRequest, HttpRequest, WebResponseError}; DefaultError, ErrorRenderer, FromRequest, HttpRequest, WebRequest, WebResponse,
WebResponseError,
};
/// The extractor type to obtain your identity from a request. /// The extractor type to obtain your identity from a request.
/// ///
@ -210,66 +209,46 @@ pub trait IdentityPolicy<Err>: Sized + 'static {
/// .secure(false), /// .secure(false),
/// )); /// ));
/// ``` /// ```
pub struct IdentityService<T, Err> { pub struct IdentityService<T> {
backend: Rc<T>, backend: Rc<T>,
_t: PhantomData<Err>,
} }
impl<T, Err> IdentityService<T, Err> { impl<T> IdentityService<T> {
/// Create new identity service with specified backend. /// Create new identity service with specified backend.
pub fn new(backend: T) -> Self { pub fn new(backend: T) -> Self {
IdentityService { backend: Rc::new(backend), _t: PhantomData } IdentityService { backend: Rc::new(backend) }
} }
} }
impl<S, T, Err> Transform<S> for IdentityService<T, Err> impl<S, T> Transform<S> for IdentityService<T> {
where type Service = IdentityServiceMiddleware<S, T>;
S: Service<Request = WebRequest<Err>, Response = WebResponse> + 'static,
S::Future: 'static,
T: IdentityPolicy<Err>,
Err: ErrorRenderer,
Err::Container: From<S::Error>,
Err::Container: From<T::Error>,
{
type Request = WebRequest<Err>;
type Response = WebResponse;
type Error = S::Error;
type InitError = ();
type Transform = IdentityServiceMiddleware<S, T, Err>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Service {
ok(IdentityServiceMiddleware { IdentityServiceMiddleware { backend: self.backend.clone(), service: Rc::new(service) }
backend: self.backend.clone(),
service: Rc::new(service),
_t: PhantomData,
})
} }
} }
#[doc(hidden)] #[doc(hidden)]
pub struct IdentityServiceMiddleware<S, T, Err> { pub struct IdentityServiceMiddleware<S, T> {
backend: Rc<T>, backend: Rc<T>,
service: Rc<S>, service: Rc<S>,
_t: PhantomData<Err>,
} }
impl<S, T, Err> Clone for IdentityServiceMiddleware<S, T, Err> { impl<S, T> Clone for IdentityServiceMiddleware<S, T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { backend: self.backend.clone(), service: self.service.clone(), _t: PhantomData } Self { backend: self.backend.clone(), service: self.service.clone() }
} }
} }
impl<S, T, Err> Service for IdentityServiceMiddleware<S, T, Err> impl<S, T, Err> Service<WebRequest<Err>> for IdentityServiceMiddleware<S, T>
where where
S: Service<Request = WebRequest<Err>, Response = WebResponse> + 'static, S: Service<WebRequest<Err>, Response = WebResponse> + 'static,
S::Future: 'static, S::Future: 'static,
T: IdentityPolicy<Err>, T: IdentityPolicy<Err>,
Err: ErrorRenderer, Err: ErrorRenderer,
Err::Container: From<S::Error>, Err::Container: From<S::Error>,
Err::Container: From<T::Error>, Err::Container: From<T::Error>,
{ {
type Request = WebRequest<Err>;
type Response = WebResponse; type Response = WebResponse;
type Error = S::Error; type Error = S::Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
@ -313,7 +292,7 @@ where
} }
} }
struct CookieIdentityInner<Err> { struct CookieIdentityInner {
key: Key, key: Key,
key_v2: Key, key_v2: Key,
name: String, name: String,
@ -324,7 +303,6 @@ struct CookieIdentityInner<Err> {
same_site: Option<SameSite>, same_site: Option<SameSite>,
visit_deadline: Option<Duration>, visit_deadline: Option<Duration>,
login_deadline: Option<Duration>, login_deadline: Option<Duration>,
_t: PhantomData<Err>,
} }
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
@ -341,8 +319,8 @@ struct CookieIdentityExtention {
login_timestamp: Option<SystemTime>, login_timestamp: Option<SystemTime>,
} }
impl<Err: ErrorRenderer> CookieIdentityInner<Err> { impl CookieIdentityInner {
fn new(key: &[u8]) -> CookieIdentityInner<Err> { fn new(key: &[u8]) -> CookieIdentityInner {
let key_v2: Vec<u8> = key.iter().chain([1, 0, 0, 0].iter()).cloned().collect(); let key_v2: Vec<u8> = key.iter().chain([1, 0, 0, 0].iter()).cloned().collect();
CookieIdentityInner { CookieIdentityInner {
key: Key::derive_from(key), key: Key::derive_from(key),
@ -355,7 +333,6 @@ impl<Err: ErrorRenderer> CookieIdentityInner<Err> {
same_site: None, same_site: None,
visit_deadline: None, visit_deadline: None,
login_deadline: None, login_deadline: None,
_t: PhantomData,
} }
} }
@ -377,15 +354,12 @@ impl<Err: ErrorRenderer> CookieIdentityInner<Err> {
cookie.set_path(self.path.clone()); cookie.set_path(self.path.clone());
cookie.set_secure(self.secure); cookie.set_secure(self.secure);
cookie.set_http_only(true); cookie.set_http_only(true);
cookie.set_max_age(self.max_age);
if let Some(ref domain) = self.domain { if let Some(ref domain) = self.domain {
cookie.set_domain(domain.clone()); cookie.set_domain(domain.clone());
} }
if let Some(max_age) = self.max_age {
cookie.set_max_age(max_age);
}
if let Some(same_site) = self.same_site { if let Some(same_site) = self.same_site {
cookie.set_same_site(same_site); cookie.set_same_site(same_site);
} }
@ -405,7 +379,7 @@ impl<Err: ErrorRenderer> CookieIdentityInner<Err> {
Ok(()) Ok(())
} }
fn load(&self, req: &WebRequest<Err>) -> Option<CookieValue> { fn load<Err>(&self, req: &WebRequest<Err>) -> Option<CookieValue> {
let cookie = req.cookie(&self.name)?; let cookie = req.cookie(&self.name)?;
let mut jar = CookieJar::new(); let mut jar = CookieJar::new();
jar.add_original(cookie.clone()); jar.add_original(cookie.clone());
@ -472,7 +446,7 @@ impl<Err: ErrorRenderer> CookieIdentityInner<Err> {
/// .secure(true), /// .secure(true),
/// )); /// ));
/// ``` /// ```
pub struct CookieIdentityPolicy<Err>(Rc<CookieIdentityInner<Err>>); pub struct CookieIdentityPolicy(Rc<CookieIdentityInner>);
#[derive(Debug, Display, From)] #[derive(Debug, Display, From)]
pub enum CookieIdentityPolicyError { pub enum CookieIdentityPolicyError {
@ -482,7 +456,7 @@ pub enum CookieIdentityPolicyError {
impl WebResponseError<DefaultError> for CookieIdentityPolicyError {} impl WebResponseError<DefaultError> for CookieIdentityPolicyError {}
impl<Err: ErrorRenderer> CookieIdentityPolicy<Err> { impl CookieIdentityPolicy {
/// Construct new `CookieIdentityPolicy` instance. /// Construct new `CookieIdentityPolicy` instance.
/// ///
/// Panics if key length is less than 32 bytes. /// Panics if key length is less than 32 bytes.
@ -551,7 +525,7 @@ impl<Err: ErrorRenderer> CookieIdentityPolicy<Err> {
} }
} }
impl<Err: ErrorRenderer> IdentityPolicy<Err> for CookieIdentityPolicy<Err> { impl<Err: ErrorRenderer> IdentityPolicy<Err> for CookieIdentityPolicy {
type Error = CookieIdentityPolicyError; type Error = CookieIdentityPolicyError;
type Future = Ready<Result<Option<String>, CookieIdentityPolicyError>>; type Future = Ready<Result<Option<String>, CookieIdentityPolicyError>>;
type ResponseFuture = Ready<Result<(), CookieIdentityPolicyError>>; type ResponseFuture = Ready<Result<(), CookieIdentityPolicyError>>;
@ -610,10 +584,9 @@ mod tests {
use std::borrow::Borrow; use std::borrow::Borrow;
use super::*; use super::*;
use ntex::http::StatusCode;
use ntex::service::into_service;
use ntex::web::test::{self, TestRequest}; use ntex::web::test::{self, TestRequest};
use ntex::web::{self, error, App, Error, HttpResponse}; use ntex::web::{self, error, App, Error, HttpResponse};
use ntex::{http::StatusCode, service::into_service, time};
const COOKIE_KEY_MASTER: [u8; 32] = [0; 32]; const COOKIE_KEY_MASTER: [u8; 32] = [0; 32];
const COOKIE_NAME: &'static str = "ntex_auth"; const COOKIE_NAME: &'static str = "ntex_auth";
@ -731,18 +704,11 @@ mod tests {
} }
async fn create_identity_server< async fn create_identity_server<
F: Fn(CookieIdentityPolicy<DefaultError>) -> CookieIdentityPolicy<DefaultError> F: Fn(CookieIdentityPolicy) -> CookieIdentityPolicy + Sync + Send + Clone + 'static,
+ Sync
+ Send
+ Clone
+ 'static,
>( >(
f: F, f: F,
) -> impl ntex::service::Service< ) -> impl ntex::service::Service<ntex::http::Request, Response = WebResponse, Error = Error>
Request = ntex::http::Request, {
Response = WebResponse,
Error = Error,
> {
test::init_service( test::init_service(
App::new() App::new()
.wrap(IdentityService::new(f(CookieIdentityPolicy::new(&COOKIE_KEY_MASTER) .wrap(IdentityService::new(f(CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
@ -1051,10 +1017,9 @@ mod tests {
let srv = IdentityServiceMiddleware { let srv = IdentityServiceMiddleware {
backend: Rc::new(Ident), backend: Rc::new(Ident),
service: Rc::new(into_service(|_: WebRequest<DefaultError>| async move { service: Rc::new(into_service(|_: WebRequest<DefaultError>| async move {
ntex::rt::time::delay_for(std::time::Duration::from_secs(100)).await; time::sleep(time::Seconds(100)).await;
Err::<WebResponse, _>(error::ErrorBadRequest("error")) Err::<WebResponse, _>(error::ErrorBadRequest("error"))
})), })),
_t: PhantomData,
}; };
let srv2 = srv.clone(); let srv2 = srv.clone();
@ -1062,7 +1027,7 @@ mod tests {
ntex::rt::spawn(async move { ntex::rt::spawn(async move {
let _ = srv2.call(req).await; let _ = srv2.call(req).await;
}); });
ntex::rt::time::delay_for(std::time::Duration::from_millis(50)).await; time::sleep(time::Millis(50)).await;
let _ = lazy(|cx| srv.poll_ready(cx)).await; let _ = lazy(|cx| srv.poll_ready(cx)).await;
} }

View file

@ -16,10 +16,13 @@ name = "ntex_multipart"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
ntex = "0.3.18" ntex = "0.5.10"
derive_more = "0.99.11" derive_more = "0.99"
httparse = "1.3" httparse = "1.3"
futures = "0.3.13" futures = "0.3"
log = "0.4" log = "0.4"
mime = "0.3" mime = "0.3"
twoway = "0.2" twoway = "0.2"
[dev-dependencies]
ntex = { version = "0.5", features=["tokio"] }

View file

@ -22,10 +22,13 @@ default = ["cookie-session"]
cookie-session = ["cookie/secure", "ntex/cookie"] cookie-session = ["cookie/secure", "ntex/cookie"]
[dependencies] [dependencies]
ntex = "0.3.18" ntex = "0.5.10"
cookie = "0.15" cookie = "0.16"
derive_more = "0.99.11" derive_more = "0.99"
futures = "0.3.13" futures = "0.3"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
time = { version = "0.2.5", default-features = false, features = ["std"] } time = { version = "0.3", default-features = false, features = ["std"] }
[dev-dependencies]
ntex = { version = "0.5", features=["tokio"] }

View file

@ -17,18 +17,16 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::Infallible; use std::convert::Infallible;
use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use cookie::{Cookie, CookieJar, Key, SameSite}; use cookie::{Cookie, CookieJar, Key, SameSite};
use derive_more::{Display, From}; use derive_more::{Display, From};
use futures::future::{ok, FutureExt, LocalBoxFuture, Ready}; use futures::future::{FutureExt, LocalBoxFuture};
use ntex::http::header::{HeaderValue, SET_COOKIE}; use ntex::http::header::{HeaderValue, SET_COOKIE};
use ntex::http::HttpMessage; use ntex::http::HttpMessage;
use ntex::service::{Service, Transform}; use ntex::service::{Service, Transform};
use ntex::web::dev::{WebRequest, WebResponse}; use ntex::web::{DefaultError, ErrorRenderer, WebRequest, WebResponse, WebResponseError};
use ntex::web::{DefaultError, ErrorRenderer, WebResponseError};
use serde_json::error::Error as JsonError; use serde_json::error::Error as JsonError;
use time::{Duration, OffsetDateTime}; use time::{Duration, OffsetDateTime};
@ -52,7 +50,7 @@ enum CookieSecurity {
Private, Private,
} }
struct CookieSessionInner<Err> { struct CookieSessionInner {
key: Key, key: Key,
security: CookieSecurity, security: CookieSecurity,
name: String, name: String,
@ -63,10 +61,9 @@ struct CookieSessionInner<Err> {
max_age: Option<Duration>, max_age: Option<Duration>,
expires_in: Option<Duration>, expires_in: Option<Duration>,
same_site: Option<SameSite>, same_site: Option<SameSite>,
_t: PhantomData<Err>,
} }
impl<Err> CookieSessionInner<Err> { impl CookieSessionInner {
fn new(key: &[u8], security: CookieSecurity) -> Self { fn new(key: &[u8], security: CookieSecurity) -> Self {
CookieSessionInner { CookieSessionInner {
security, security,
@ -79,7 +76,6 @@ impl<Err> CookieSessionInner<Err> {
max_age: None, max_age: None,
expires_in: None, expires_in: None,
same_site: None, same_site: None,
_t: PhantomData,
} }
} }
@ -134,7 +130,7 @@ impl<Err> CookieSessionInner<Err> {
fn remove_cookie(&self, res: &mut WebResponse) -> Result<(), Infallible> { fn remove_cookie(&self, res: &mut WebResponse) -> Result<(), Infallible> {
let mut cookie = Cookie::named(self.name.clone()); let mut cookie = Cookie::named(self.name.clone());
cookie.set_value(""); cookie.set_value("");
cookie.set_max_age(Duration::zero()); cookie.set_max_age(Duration::ZERO);
cookie.set_expires(OffsetDateTime::now_utc() - Duration::days(365)); cookie.set_expires(OffsetDateTime::now_utc() - Duration::days(365));
let val = HeaderValue::from_str(&cookie.to_string()).unwrap(); let val = HeaderValue::from_str(&cookie.to_string()).unwrap();
@ -143,7 +139,7 @@ impl<Err> CookieSessionInner<Err> {
Ok(()) Ok(())
} }
fn load(&self, req: &WebRequest<Err>) -> (bool, HashMap<String, String>) { fn load<Err>(&self, req: &WebRequest<Err>) -> (bool, HashMap<String, String>) {
if let Ok(cookies) = req.cookies() { if let Ok(cookies) = req.cookies() {
for cookie in cookies.iter() { for cookie in cookies.iter() {
if cookie.name() == self.name { if cookie.name() == self.name {
@ -206,9 +202,9 @@ impl<Err> CookieSessionInner<Err> {
/// .secure(true)) /// .secure(true))
/// .service(web::resource("/").to(|| async { HttpResponse::Ok() })); /// .service(web::resource("/").to(|| async { HttpResponse::Ok() }));
/// ``` /// ```
pub struct CookieSession<Err>(Rc<CookieSessionInner<Err>>); pub struct CookieSession(Rc<CookieSessionInner>);
impl<Err> CookieSession<Err> { impl CookieSession {
/// Construct new *signed* `CookieSessionBackend` instance. /// Construct new *signed* `CookieSessionBackend` instance.
/// ///
/// Panics if key length is less than 32 bytes. /// Panics if key length is less than 32 bytes.
@ -285,41 +281,28 @@ impl<Err> CookieSession<Err> {
} }
} }
impl<S, Err> Transform<S> for CookieSession<Err> impl<S> Transform<S> for CookieSession {
where type Service = CookieSessionMiddleware<S>;
S: Service<Request = WebRequest<Err>, Response = WebResponse>,
S::Future: 'static,
S::Error: 'static,
Err: ErrorRenderer,
Err::Container: From<CookieSessionError>,
{
type Request = WebRequest<Err>;
type Response = WebResponse;
type Error = S::Error;
type InitError = ();
type Transform = CookieSessionMiddleware<S, Err>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Service {
ok(CookieSessionMiddleware { service, inner: self.0.clone() }) CookieSessionMiddleware { service, inner: self.0.clone() }
} }
} }
/// Cookie session middleware /// Cookie session middleware
pub struct CookieSessionMiddleware<S, Err> { pub struct CookieSessionMiddleware<S> {
service: S, service: S,
inner: Rc<CookieSessionInner<Err>>, inner: Rc<CookieSessionInner>,
} }
impl<S, Err> Service for CookieSessionMiddleware<S, Err> impl<S, Err> Service<WebRequest<Err>> for CookieSessionMiddleware<S>
where where
S: Service<Request = WebRequest<Err>, Response = WebResponse>, S: Service<WebRequest<Err>, Response = WebResponse>,
S::Future: 'static, S::Future: 'static,
S::Error: 'static, S::Error: 'static,
Err: ErrorRenderer, Err: ErrorRenderer,
Err::Container: From<CookieSessionError>, Err::Container: From<CookieSessionError>,
{ {
type Request = WebRequest<Err>;
type Response = WebResponse; type Response = WebResponse;
type Error = S::Error; type Error = S::Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
@ -382,8 +365,8 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use ntex::util::Bytes;
use ntex::web::{self, test, App}; use ntex::web::{self, test, App};
use ntex::{time, util::Bytes};
#[ntex::test] #[ntex::test]
async fn cookie_session() { async fn cookie_session() {
@ -494,7 +477,7 @@ mod tests {
.expires() .expires()
.expect("Expiration is set"); .expect("Expiration is set");
ntex::rt::time::delay_for(std::time::Duration::from_secs(1)).await; time::sleep(time::Seconds::ONE).await;
let request = test::TestRequest::with_uri("/test/").to_request(); let request = test::TestRequest::with_uri("/test/").to_request();
let response = app.call(request).await.unwrap(); let response = app.call(request).await.unwrap();

View file

@ -49,8 +49,7 @@ use std::rc::Rc;
use futures::future::{ok, Ready}; use futures::future::{ok, Ready};
use ntex::http::{Payload, RequestHead}; use ntex::http::{Payload, RequestHead};
use ntex::util::Extensions; use ntex::util::Extensions;
use ntex::web::dev::{WebRequest, WebResponse}; use ntex::web::{Error, FromRequest, HttpRequest, WebRequest, WebResponse};
use ntex::web::{Error, FromRequest, HttpRequest};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;