Update to ntex 1.0

This commit is contained in:
Nikolay Kim 2024-01-08 21:01:33 +06:00
parent 1270f0c8a6
commit 14c6930954
11 changed files with 140 additions and 177 deletions

View file

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

View file

@ -45,16 +45,15 @@
//! endpoint.
//!
//! Cors middleware automatically handle *OPTIONS* preflight request.
use std::task::{Context, Poll};
use std::{
collections::HashSet, convert::TryFrom, iter::FromIterator, marker::PhantomData, rc::Rc,
};
use derive_more::Display;
use futures::future::{ok, Either, FutureExt, LocalBoxFuture, Ready};
use ntex::http::header::{self, HeaderName, HeaderValue};
use ntex::http::{error::HttpError, HeaderMap, Method, RequestHead, StatusCode, Uri};
use ntex::service::{Middleware, Service, ServiceCtx};
use ntex::util::Either;
use ntex::web::{
DefaultError, ErrorRenderer, HttpResponse, WebRequest, WebResponse, WebResponseError,
};
@ -747,40 +746,30 @@ where
{
type Response = WebResponse;
type Error = S::Error;
type Future<'f> = Either<
Ready<Result<Self::Response, S::Error>>,
LocalBoxFuture<'f, Result<Self::Response, S::Error>>,
> where Self: 'f;
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}
ntex::forward_poll_ready!(service);
ntex::forward_poll_shutdown!(service);
fn poll_shutdown(&self, cx: &mut Context<'_>) -> Poll<()> {
self.service.poll_shutdown(cx)
}
fn call<'a>(&'a self, req: WebRequest<Err>, ctx: ServiceCtx<'a, Self>) -> Self::Future<'a> {
async fn call(
&self,
req: WebRequest<Err>,
ctx: ServiceCtx<'_, Self>,
) -> Result<Self::Response, S::Error> {
match self.inner.preflight_check(req.head()) {
Ok(Either::Left(res)) => Either::Left(ok(req.into_response(res))),
Ok(Either::Left(res)) => Ok(req.into_response(res)),
Ok(Either::Right(_)) => {
let inner = self.inner.clone();
let has_origin = req.headers().contains_key(&header::ORIGIN);
let allowed_origin = inner.access_control_allow_origin(req.headers());
Either::Right(
async move {
let mut res = ctx.call(&self.service, req).await?;
let mut res = ctx.call(&self.service, req).await?;
if has_origin {
inner.handle_response(res.headers_mut(), allowed_origin);
}
Ok(res)
}
.boxed_local(),
)
if has_origin {
inner.handle_response(res.headers_mut(), allowed_origin);
}
Ok(res)
}
Err(e) => Either::Left(ok(req.render_error(e))),
Err(e) => Ok(req.render_error(e)),
}
}
}
@ -821,7 +810,7 @@ mod tests {
#[ntex::test]
async fn test_preflight() {
let mut cors: Pipeline<_> = Cors::new()
let cors: Pipeline<_> = Cors::new()
.send_wildcard()
.max_age(3600)
.allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST])
@ -1006,8 +995,8 @@ mod tests {
.expose_headers(exposed_headers.clone())
.allowed_header(header::CONTENT_TYPE)
.finish()
.create(fn_service(|req: WebRequest<DefaultError>| {
ok::<_, std::convert::Infallible>(req.into_response(
.create(fn_service(|req: WebRequest<DefaultError>| async move {
Ok::<_, std::convert::Infallible>(req.into_response(
HttpResponse::Ok().header(header::VARY, "Accept").finish(),
))
}))

View file

@ -1,6 +1,6 @@
[package]
name = "ntex-files"
version = "0.3.0"
version = "0.4.0-b.0"
authors = ["ntex contributors <team@ntex.rs>"]
description = "Static files support for ntex web."
readme = "README.md"
@ -18,8 +18,8 @@ name = "ntex_files"
path = "src/lib.rs"
[dependencies]
ntex = "0.7.0"
ntex-http = "0.1.8"
ntex = "1.0.0-b.1"
ntex-http = "0.1.11"
bitflags = "2.1"
futures = "0.3"
derive_more = "0.99"
@ -31,7 +31,7 @@ percent-encoding = "2.1"
v_htmlescape = "0.15.8"
unicase = "2.6.0"
language-tags = "0.3.2"
httpdate = "1.0.2"
httpdate = "1.0"
[dev-dependencies]
ntex = { version = "0.7.0", features = ["tokio", "openssl", "compress"] }
ntex = { version = "1.0.0-b.1", features = ["tokio", "openssl", "compress"] }

View file

@ -7,14 +7,14 @@ use std::{
cmp, fmt::Write, io, io::Read, io::Seek, pin::Pin, rc::Rc, task::Context, task::Poll,
};
use futures::future::{ok, ready, Either, FutureExt, LocalBoxFuture, Ready};
use futures::future::{FutureExt, LocalBoxFuture};
use futures::{Future, Stream};
use mime_guess::from_ext;
use ntex::http::error::BlockingError;
use ntex::http::{header, Method, Payload, Uri};
use ntex::router::{ResourceDef, ResourcePath};
use ntex::service::boxed::{self, BoxService, BoxServiceFactory};
use ntex::service::{IntoServiceFactory, Service, ServiceCall, ServiceCtx, ServiceFactory};
use ntex::service::{IntoServiceFactory, Service, ServiceCtx, ServiceFactory};
use ntex::util::Bytes;
use ntex::web::dev::{WebServiceConfig, WebServiceFactory};
use ntex::web::error::ErrorRenderer;
@ -404,9 +404,8 @@ where
type Error = Err::Container;
type Service = FilesService<Err>;
type InitError = ();
type Future<'f> = LocalBoxFuture<'f, Result<Self::Service, Self::InitError>>;
fn create(&self, _: ()) -> Self::Future<'_> {
async fn create(&self, _: ()) -> Result<Self::Service, Self::InitError> {
let mut srv = FilesService {
directory: self.directory.clone(),
index: self.index.clone(),
@ -429,9 +428,9 @@ where
}
Err(_) => Err(()),
})
.boxed_local()
.await
} else {
ok(srv).boxed_local()
Ok(srv)
}
}
}
@ -452,20 +451,17 @@ impl<Err: ErrorRenderer> FilesService<Err>
where
Err::Container: From<FilesError>,
{
fn handle_io_error<'a>(
&'a self,
async fn handle_io_error(
&self,
e: io::Error,
req: WebRequest<Err>,
ctx: ServiceCtx<'a, Self>,
) -> Either<
Ready<Result<WebResponse, Err::Container>>,
ServiceCall<'a, HttpService<Err>, WebRequest<Err>>,
> {
ctx: ServiceCtx<'_, Self>,
) -> Result<WebResponse, Err::Container> {
log::debug!("Files: Failed to handle {}: {}", req.path(), e);
if let Some(ref default) = self.default {
Either::Right(ctx.call(default, req))
ctx.call(default, req).await
} else {
Either::Left(ok(req.error_response(FilesError::from(e))))
Ok(req.error_response(FilesError::from(e)))
}
}
}
@ -477,12 +473,12 @@ where
{
type Response = WebResponse;
type Error = Err::Container;
type Future<'f> = Either<
Ready<Result<Self::Response, Self::Error>>,
ServiceCall<'f, HttpService<Err>, WebRequest<Err>>,
>;
fn call<'a>(&'a self, req: WebRequest<Err>, ctx: ServiceCtx<'a, Self>) -> Self::Future<'a> {
async fn call(
&self,
req: WebRequest<Err>,
ctx: ServiceCtx<'_, Self>,
) -> Result<Self::Response, Self::Error> {
let is_method_valid = if let Some(guard) = &self.guards {
// execute user defined guards
(**guard).check(req.head())
@ -492,30 +488,30 @@ where
};
if !is_method_valid {
return Either::Left(ok(req.error_response(FilesError::MethodNotAllowed)));
return Ok(req.error_response(FilesError::MethodNotAllowed));
}
let real_path = match PathBufWrp::get_pathbuf(req.match_info().path()) {
Ok(item) => item,
Err(e) => return Either::Left(ok(req.error_response(FilesError::from(e)))),
Err(e) => return Ok(req.error_response(FilesError::from(e))),
};
// full filepath
let path = match self.directory.join(real_path.0).canonicalize() {
Ok(path) => path,
Err(e) => return self.handle_io_error(e, req, ctx),
Err(e) => return self.handle_io_error(e, req, ctx).await,
};
if path.is_dir() {
if let Some(ref redir_index) = self.index {
if self.redirect_to_slash && !req.path().ends_with('/') {
let redirect_to = format!("{}/", req.path());
return Either::Left(ok(req.into_response(
return Ok(req.into_response(
HttpResponse::Found()
.header(header::LOCATION, redirect_to)
.body("")
.into_body(),
)));
));
}
let path = path.join(redir_index);
@ -530,26 +526,20 @@ where
named_file.flags = self.file_flags.clone();
let (req, _) = req.into_parts();
Either::Left(ok(WebResponse::new(named_file.into_response(&req), req)))
Ok(WebResponse::new(named_file.into_response(&req), req))
}
Err(e) => self.handle_io_error(e, req, ctx),
Err(e) => self.handle_io_error(e, req, ctx).await,
}
} else if self.show_index {
let dir = Directory::new(self.directory.clone(), path);
let (req, _) = req.into_parts();
let x = (self.renderer)(&dir, &req);
match x {
Ok(resp) => Either::Left(ok(resp)),
Err(e) => Either::Left(ok(WebResponse::from_err::<Err, _>(
FilesError::from(e),
req,
))),
Ok(resp) => Ok(resp),
Err(e) => Ok(WebResponse::from_err::<Err, _>(FilesError::from(e), req)),
}
} else {
Either::Left(ok(WebResponse::from_err::<Err, _>(
FilesError::IsDirectory,
req.into_parts().0,
)))
Ok(WebResponse::from_err::<Err, _>(FilesError::IsDirectory, req.into_parts().0))
}
} else {
match NamedFile::open(path) {
@ -561,9 +551,9 @@ where
named_file.flags = self.file_flags.clone();
let (req, _) = req.into_parts();
Either::Left(ok(WebResponse::new(named_file.into_response(&req), req)))
Ok(WebResponse::new(named_file.into_response(&req), req))
}
Err(e) => self.handle_io_error(e, req, ctx),
Err(e) => self.handle_io_error(e, req, ctx).await,
}
}
}
@ -603,10 +593,9 @@ impl PathBufWrp {
impl<Err> FromRequest<Err> for PathBufWrp {
type Error = UriSegmentError;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
ready(PathBufWrp::get_pathbuf(req.match_info().path()))
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
PathBufWrp::get_pathbuf(req.match_info().path())
}
}
@ -1179,8 +1168,8 @@ mod tests {
#[ntex::test]
async fn test_default_handler_file_missing() {
let st = Files::new("/", ".")
.default_handler(|req: WebRequest<DefaultError>| {
ok(req.into_response(HttpResponse::Ok().body("default content")))
.default_handler(|req: WebRequest<DefaultError>| async move {
Ok(req.into_response(HttpResponse::Ok().body("default content")))
})
.pipeline(())
.await

View file

@ -1,6 +1,6 @@
[package]
name = "ntex-identity"
version = "0.3.0"
version = "0.4.0-b.0"
authors = ["ntex contributors <team@ntex.rs>"]
description = "Identity service for ntex web framework."
readme = "README.md"
@ -21,13 +21,13 @@ default = ["cookie-policy"]
cookie-policy = ["cookie/secure", "ntex/cookie"]
[dependencies]
ntex = "0.7.0"
ntex = "1.0.0-b.1"
futures = "0.3"
serde = "1.0"
serde_json = "1.0"
derive_more = "0.99"
cookie = { version = "0.17", features = ["private"] }
cookie = { version = "0.18", features = ["private"] }
time = { version = "0.3", default-features = false, features = ["std"] }
[dev-dependencies]
ntex = { version = "0.7.0", features=["tokio"] }
ntex = { version = "1.0.0-b.1", features=["tokio"] }

View file

@ -44,13 +44,11 @@
//! .service(web::resource("/login.html").to(login))
//! .service(web::resource("/logout.html").to(logout));
//! ```
use std::task::{Context, Poll};
use std::time::SystemTime;
use std::{convert::Infallible, future::Future, rc::Rc};
use std::{convert::Infallible, future::Future, rc::Rc, time::SystemTime};
use cookie::{Cookie, CookieJar, Key, SameSite};
use derive_more::{Display, From};
use futures::future::{ok, FutureExt, LocalBoxFuture, Ready};
use futures::future::{ok, Ready};
use serde::{Deserialize, Serialize};
use time::Duration;
@ -164,11 +162,10 @@ where
/// ```
impl<Err: ErrorRenderer> FromRequest<Err> for Identity {
type Error = Infallible;
type Future = Ready<Result<Identity, Infallible>>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
ok(Identity(req.clone()))
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Identity, Infallible> {
Ok(Identity(req.clone()))
}
}
@ -249,43 +246,34 @@ where
{
type Response = WebResponse;
type Error = S::Error;
type Future<'f> = LocalBoxFuture<'f, Result<Self::Response, Self::Error>>;
fn poll_ready(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}
ntex::forward_poll_ready!(service);
ntex::forward_poll_shutdown!(service);
fn poll_shutdown(&self, cx: &mut Context) -> Poll<()> {
self.service.poll_shutdown(cx)
}
fn call<'a>(
&'a self,
async fn call(
&self,
mut req: WebRequest<Err>,
ctx: ServiceCtx<'a, Self>,
) -> Self::Future<'a> {
async move {
match self.backend.from_request(&mut req).await {
Ok(id) => {
req.extensions_mut().insert(IdentityItem { id, changed: false });
ctx: ServiceCtx<'_, Self>,
) -> Result<Self::Response, Self::Error> {
match self.backend.from_request(&mut req).await {
Ok(id) => {
req.extensions_mut().insert(IdentityItem { id, changed: false });
// https://github.com/actix/actix-web/issues/1263
let mut res = ctx.call(&self.service, req).await?;
let id = res.request().extensions_mut().remove::<IdentityItem>();
// https://github.com/actix/actix-web/issues/1263
let mut res = ctx.call(&self.service, req).await?;
let id = res.request().extensions_mut().remove::<IdentityItem>();
if let Some(id) = id {
match self.backend.to_response(id.id, id.changed, &mut res).await {
Ok(_) => Ok(res),
Err(e) => Ok(WebResponse::error_response::<Err, _>(res, e)),
}
} else {
Ok(res)
if let Some(id) = id {
match self.backend.to_response(id.id, id.changed, &mut res).await {
Ok(_) => Ok(res),
Err(e) => Ok(WebResponse::error_response::<Err, _>(res, e)),
}
} else {
Ok(res)
}
Err(err) => Ok(req.error_response(err)),
}
Err(err) => Ok(req.error_response(err)),
}
.boxed_local()
}
}
@ -621,12 +609,13 @@ mod tests {
})),
)
.await;
let resp = test::call_service(&srv, TestRequest::with_uri("/index").to_request()).await;
assert_eq!(resp.status(), StatusCode::OK);
let resp = test::call_service(&srv, TestRequest::with_uri("/login").to_request()).await;
assert_eq!(resp.status(), StatusCode::OK);
let c = resp.response().cookies().next().unwrap().to_owned();
let c = resp.response().cookies().next().unwrap().into_owned();
let resp = test::call_service(
&srv,

View file

@ -1,6 +1,6 @@
[package]
name = "ntex-multipart"
version = "0.3.0"
version = "0.4.0-b.0"
authors = ["ntex contributors <team@ntex.rs>"]
description = "Multipart support for ntex web framework."
readme = "README.md"
@ -16,7 +16,7 @@ name = "ntex_multipart"
path = "src/lib.rs"
[dependencies]
ntex = "0.7.0"
ntex = "1.0.0-b.1"
derive_more = "0.99"
httparse = "1.3"
futures = "0.3"
@ -25,4 +25,4 @@ mime = "0.3"
twoway = "0.2"
[dev-dependencies]
ntex = { version = "0.7.0", features=["tokio"] }
ntex = { version = "1.0.0-b.1", features=["tokio"] }

View file

@ -1,7 +1,6 @@
//! Multipart payload support
use std::convert::Infallible;
use futures::future::{ok, Ready};
use ntex::http::Payload;
use ntex::web::{FromRequest, HttpRequest};
@ -34,10 +33,12 @@ use crate::server::Multipart;
/// ```
impl<Err> FromRequest<Err> for Multipart {
type Error = Infallible;
type Future = Ready<Result<Multipart, Infallible>>;
#[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
ok(Multipart::new(req.headers(), payload.take()))
async fn from_request(
req: &HttpRequest,
payload: &mut Payload,
) -> Result<Multipart, Infallible> {
Ok(Multipart::new(req.headers(), payload.take()))
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "ntex-session"
version = "0.3.0"
version = "0.4.0-b.0"
authors = ["ntex contributors <team@ntex.rs>"]
description = "Session for ntex web framework."
readme = "README.md"
@ -22,8 +22,8 @@ default = ["cookie-session"]
cookie-session = ["cookie/secure", "ntex/cookie"]
[dependencies]
ntex = "0.7.0"
cookie = "0.17"
ntex = "1.0.0-b.1"
cookie = "0.18"
derive_more = "0.99"
futures = "0.3"
serde = "1.0"
@ -31,4 +31,4 @@ serde_json = "1.0"
time = { version = "0.3", default-features = false, features = ["std"] }
[dev-dependencies]
ntex = { version = "0.7.0", features=["tokio"] }
ntex = { version = "1.0.0-b.1", features=["tokio"] }

View file

@ -15,12 +15,10 @@
//! The constructors take a key as an argument. This is the private key
//! for cookie session - when this value is changed, all session data is lost.
use std::task::{Context, Poll};
use std::{collections::HashMap, convert::Infallible, rc::Rc};
use cookie::{Cookie, CookieJar, Key, SameSite};
use derive_more::{Display, From};
use futures::future::{FutureExt, LocalBoxFuture};
use ntex::http::{header::HeaderValue, header::SET_COOKIE, HttpMessage};
use ntex::service::{Middleware, Service, ServiceCtx};
use ntex::web::{DefaultError, ErrorRenderer, WebRequest, WebResponse, WebResponseError};
@ -125,7 +123,7 @@ impl CookieSessionInner {
/// invalidates session cookie
fn remove_cookie(&self, res: &mut WebResponse) -> Result<(), Infallible> {
let mut cookie = Cookie::named(self.name.clone());
let mut cookie = Cookie::from(self.name.clone());
cookie.set_value("");
cookie.set_max_age(Duration::ZERO);
cookie.set_expires(OffsetDateTime::now_utc() - Duration::days(365));
@ -301,58 +299,53 @@ where
{
type Response = WebResponse;
type Error = S::Error;
type Future<'f> = LocalBoxFuture<'f, Result<Self::Response, Self::Error>> where Self: 'f;
fn poll_ready(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}
fn poll_shutdown(&self, cx: &mut Context) -> Poll<()> {
self.service.poll_shutdown(cx)
}
ntex::forward_poll_ready!(service);
ntex::forward_poll_shutdown!(service);
/// On first request, a new session cookie is returned in response, regardless
/// of whether any session state is set. With subsequent requests, if the
/// session state changes, then set-cookie is returned in response. As
/// a user logs out, call session.purge() to set SessionStatus accordingly
/// and this will trigger removal of the session cookie in the response.
fn call<'a>(&'a self, req: WebRequest<Err>, ctx: ServiceCtx<'a, Self>) -> Self::Future<'a> {
async fn call(
&self,
req: WebRequest<Err>,
ctx: ServiceCtx<'_, Self>,
) -> Result<Self::Response, Self::Error> {
let inner = self.inner.clone();
let (is_new, state) = self.inner.load(&req);
let prolong_expiration = self.inner.expires_in.is_some();
Session::set_session(state.into_iter(), &req);
async move {
ctx.call(&self.service, req).await.map(|mut res| {
match Session::get_changes(&mut res) {
(SessionStatus::Changed, Some(state))
| (SessionStatus::Renewed, Some(state)) => {
res.checked_expr::<Err, _, _>(|res| inner.set_cookie(res, state))
}
(SessionStatus::Unchanged, Some(state)) if prolong_expiration => {
res.checked_expr::<Err, _, _>(|res| inner.set_cookie(res, state))
}
(SessionStatus::Unchanged, _) =>
// set a new session cookie upon first request (new client)
{
if is_new {
let state: HashMap<String, String> = HashMap::new();
res.checked_expr::<Err, _, _>(|res| {
inner.set_cookie(res, state.into_iter())
})
} else {
res
}
}
(SessionStatus::Purged, _) => {
let _ = inner.remove_cookie(&mut res);
ctx.call(&self.service, req).await.map(|mut res| {
match Session::get_changes(&mut res) {
(SessionStatus::Changed, Some(state))
| (SessionStatus::Renewed, Some(state)) => {
res.checked_expr::<Err, _, _>(|res| inner.set_cookie(res, state))
}
(SessionStatus::Unchanged, Some(state)) if prolong_expiration => {
res.checked_expr::<Err, _, _>(|res| inner.set_cookie(res, state))
}
(SessionStatus::Unchanged, _) =>
// set a new session cookie upon first request (new client)
{
if is_new {
let state: HashMap<String, String> = HashMap::new();
res.checked_expr::<Err, _, _>(|res| {
inner.set_cookie(res, state.into_iter())
})
} else {
res
}
_ => res,
}
})
}
.boxed_local()
(SessionStatus::Purged, _) => {
let _ = inner.remove_cookie(&mut res);
res
}
_ => res,
}
})
}
}
@ -439,8 +432,12 @@ mod tests {
let request = test::TestRequest::get().to_request();
let response = app.call(request).await.unwrap();
let cookie =
response.response().cookies().find(|c| c.name() == "ntex-test").unwrap().clone();
let cookie = response
.response()
.cookies()
.find(|c| c.name() == "ntex-test")
.unwrap()
.into_owned();
assert_eq!(cookie.path().unwrap(), "/test/");
let request = test::TestRequest::with_uri("/test/").cookie(cookie).to_request();

View file

@ -46,7 +46,6 @@ use std::collections::HashMap;
use std::convert::Infallible;
use std::rc::Rc;
use futures::future::{ok, Ready};
use ntex::http::{Payload, RequestHead};
use ntex::util::Extensions;
use ntex::web::{Error, FromRequest, HttpRequest, WebRequest, WebResponse};
@ -228,11 +227,10 @@ impl Session {
/// ```
impl<Err> FromRequest<Err> for Session {
type Error = Infallible;
type Future = Ready<Result<Session, Infallible>>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
ok(Session::get_session(&mut req.extensions_mut()))
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Session, Infallible> {
Ok(Session::get_session(&mut req.extensions_mut()))
}
}