mirror of
https://github.com/ntex-rs/ntex-extras.git
synced 2025-04-05 22:07:40 +03:00
upgrade ntex 0.5 release
This commit is contained in:
parent
74148e3ddf
commit
6ec85aa238
10 changed files with 124 additions and 200 deletions
|
@ -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"] }
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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<
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue