Add option to use default AppConfig for App type factory

This commit is contained in:
Nikolay Kim 2022-01-02 03:32:18 +06:00
parent 44b00682e0
commit 713e02d6a3
9 changed files with 153 additions and 146 deletions

View file

@ -4,6 +4,8 @@
* http1: Unregister keep-alive timer after request is received
* web: Add option to use default `AppConfig` for App type factory
## [0.5.3] - 2021-12-31
* Fix WsTransport shutdown, send close frame

View file

@ -20,7 +20,7 @@ impl BodySize {
}
/// Type that provides this trait can be streamed to a peer.
pub trait MessageBody {
pub trait MessageBody: 'static {
fn size(&self) -> BodySize;
fn poll_next_chunk(
@ -392,7 +392,7 @@ where
impl<S, E> MessageBody for BodyStream<S, E>
where
S: Stream<Item = Result<Bytes, E>> + Unpin,
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
E: Error + 'static,
{
fn size(&self) -> BodySize {
@ -435,7 +435,7 @@ where
impl<S> MessageBody for BoxedBodyStream<S>
where
S: Stream<Item = Result<Bytes, Box<dyn Error>>> + Unpin,
S: Stream<Item = Result<Bytes, Box<dyn Error>>> + Unpin + 'static,
{
fn size(&self) -> BodySize {
BodySize::Stream
@ -478,7 +478,7 @@ where
impl<S> MessageBody for SizedStream<S>
where
S: Stream<Item = Result<Bytes, Box<dyn Error>>> + Unpin,
S: Stream<Item = Result<Bytes, Box<dyn Error>>> + Unpin + 'static,
{
fn size(&self) -> BodySize {
BodySize::Sized(self.size)

View file

@ -1,6 +1,6 @@
//! Framed transport dispatcher
use std::task::{Context, Poll};
use std::{error::Error, fmt, future::Future, io, marker, pin::Pin, rc::Rc};
use std::{error::Error, future::Future, io, marker, pin::Pin, rc::Rc};
use crate::io::{Filter, Io, IoRef, RecvError};
use crate::{service::Service, util::ready, util::Bytes};
@ -78,15 +78,14 @@ struct DispatcherInner<F, S, B, X, U> {
impl<F, S, B, X, U> Dispatcher<F, S, B, X, U>
where
F: Filter + 'static,
F: Filter,
S: Service<Request>,
S::Error: ResponseError + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
X: Service<Request, Response = Request>,
X::Error: ResponseError,
U: Service<(Request, Io<F>, Codec), Response = ()> + 'static,
U::Error: Error + fmt::Display,
U: Service<(Request, Io<F>, Codec), Response = ()>,
{
/// Construct new `Dispatcher` instance with outgoing messages stream.
pub(in crate::http) fn new(io: Io<F>, config: Rc<DispatcherConfig<S, X, U>>) -> Self {
@ -129,7 +128,6 @@ where
X: Service<Request, Response = Request>,
X::Error: ResponseError + 'static,
U: Service<(Request, Io<F>, Codec), Response = ()> + 'static,
U::Error: Error + fmt::Display,
{
type Output = Result<(), DispatchError>;

View file

@ -29,8 +29,8 @@ pub struct H1Service<F, S, B, X = ExpectHandler, U = UpgradeHandler<F>> {
impl<F, S, B> H1Service<F, S, B>
where
S: ServiceFactory<Request>,
S::Error: ResponseError + 'static,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>>,
B: MessageBody,
@ -63,16 +63,14 @@ mod openssl {
impl<F, S, B, X, U> H1Service<SslFilter<F>, S, B, X, U>
where
F: Filter,
S: ServiceFactory<Request>,
S::Error: ResponseError + 'static,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>>,
S::Future: 'static,
B: MessageBody,
X: ServiceFactory<Request, Response = Request>,
X::Error: ResponseError + 'static,
X: ServiceFactory<Request, Response = Request> + 'static,
X::Error: ResponseError,
X::InitError: fmt::Debug,
X::Future: 'static,
U: ServiceFactory<(Request, Io<SslFilter<F>>, Codec), Response = ()> + 'static,
U::Error: fmt::Display + Error,
U::InitError: fmt::Debug,
@ -111,16 +109,14 @@ mod rustls {
impl<F, S, B, X, U> H1Service<TlsFilter<F>, S, B, X, U>
where
F: Filter,
S: ServiceFactory<Request>,
S::Error: ResponseError + 'static,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>>,
S::Future: 'static,
B: MessageBody,
X: ServiceFactory<Request, Response = Request>,
X::Error: ResponseError + 'static,
X: ServiceFactory<Request, Response = Request> + 'static,
X::Error: ResponseError,
X::InitError: fmt::Debug,
X::Future: 'static,
U: ServiceFactory<(Request, Io<TlsFilter<F>>, Codec), Response = ()> + 'static,
U::Error: fmt::Display + Error,
U::InitError: fmt::Debug,
@ -149,19 +145,17 @@ mod rustls {
impl<F, S, B, X, U> H1Service<F, S, B, X, U>
where
F: Filter,
S: ServiceFactory<Request>,
S::Error: ResponseError + 'static,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
S::InitError: fmt::Debug,
S::Future: 'static,
B: MessageBody,
{
pub fn expect<X1>(self, expect: X1) -> H1Service<F, S, B, X1, U>
where
X1: ServiceFactory<Request, Response = Request>,
X1::Error: ResponseError + 'static,
X1: ServiceFactory<Request, Response = Request> + 'static,
X1::Error: ResponseError,
X1::InitError: fmt::Debug,
X1::Future: 'static,
{
H1Service {
expect,
@ -176,10 +170,9 @@ where
pub fn upgrade<U1>(self, upgrade: Option<U1>) -> H1Service<F, S, B, X, U1>
where
U1: ServiceFactory<(Request, Io<F>, Codec), Response = ()>,
U1::Error: fmt::Display + Error + 'static,
U1: ServiceFactory<(Request, Io<F>, Codec), Response = ()> + 'static,
U1::Error: fmt::Display + Error,
U1::InitError: fmt::Debug,
U1::Future: 'static,
{
H1Service {
upgrade,
@ -203,17 +196,15 @@ where
impl<F, S, B, X, U> ServiceFactory<Io<F>> for H1Service<F, S, B, X, U>
where
F: Filter + 'static,
S: ServiceFactory<Request>,
S::Error: ResponseError + 'static,
F: Filter,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
S::InitError: fmt::Debug,
S::Future: 'static,
B: MessageBody,
X: ServiceFactory<Request, Response = Request>,
X::Error: ResponseError + 'static,
X: ServiceFactory<Request, Response = Request> + 'static,
X::Error: ResponseError,
X::InitError: fmt::Debug,
X::Future: 'static,
U: ServiceFactory<(Request, Io<F>, Codec), Response = ()> + 'static,
U::Error: fmt::Display + Error,
U::InitError: fmt::Debug,
@ -267,13 +258,13 @@ pub struct H1ServiceHandler<F, S, B, X, U> {
impl<F, S, B, X, U> Service<Io<F>> for H1ServiceHandler<F, S, B, X, U>
where
F: Filter + 'static,
S: Service<Request>,
S::Error: ResponseError + 'static,
F: Filter,
S: Service<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
X: Service<Request, Response = Request>,
X::Error: ResponseError + 'static,
X: Service<Request, Response = Request> + 'static,
X::Error: ResponseError,
U: Service<(Request, Io<F>, Codec), Response = ()> + 'static,
U::Error: fmt::Display + Error,
{

View file

@ -36,8 +36,8 @@ pin_project_lite::pin_project! {
impl<F, S, B, X, U> Dispatcher<F, S, B, X, U>
where
F: Filter,
S: Service<Request>,
S::Error: ResponseError + 'static,
S: Service<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
{
@ -72,11 +72,10 @@ where
impl<F, S, B, X, U> Future for Dispatcher<F, S, B, X, U>
where
F: Filter,
S: Service<Request>,
S::Error: ResponseError + 'static,
S::Future: 'static,
S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static,
S: Service<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
{
type Output = Result<(), DispatchError>;

View file

@ -62,7 +62,7 @@ mod openssl {
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody + 'static,
B: MessageBody,
{
/// Create ssl based service
pub fn openssl(
@ -99,7 +99,7 @@ mod rustls {
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody + 'static,
B: MessageBody,
{
/// Create openssl based service
pub fn rustls(
@ -131,7 +131,7 @@ where
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody + 'static,
B: MessageBody,
{
type Response = ();
type Error = DispatchError;
@ -164,11 +164,10 @@ pub struct H2ServiceHandler<F, S: Service<Request>, B> {
impl<F, S, B> Service<Io<F>> for H2ServiceHandler<F, S, B>
where
F: Filter,
S: Service<Request>,
S::Error: ResponseError + 'static,
S::Future: 'static,
S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static,
S: Service<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
{
type Response = ();
type Error = DispatchError;
@ -207,7 +206,7 @@ where
enum State<F, S: Service<Request>, B: MessageBody>
where
F: Filter,
S::Future: 'static,
S: 'static,
{
Incoming(Dispatcher<F, S, B, (), ()>),
Handshake(
@ -220,11 +219,10 @@ where
pub struct H2ServiceHandlerResponse<F, S, B>
where
F: Filter,
S: Service<Request>,
S::Error: ResponseError + 'static,
S::Future: 'static,
S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static,
S: Service<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
{
state: State<F, S, B>,
}
@ -232,10 +230,9 @@ where
impl<F, S, B> Future for H2ServiceHandlerResponse<F, S, B>
where
F: Filter,
S: Service<Request>,
S::Error: ResponseError + 'static,
S::Future: 'static,
S::Response: Into<Response<B>> + 'static,
S: Service<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
{
type Output = Result<(), DispatchError>;

View file

@ -29,13 +29,11 @@ pub struct HttpService<F, S, B, X = h1::ExpectHandler, U = h1::UpgradeHandler<F>
impl<F, S, B> HttpService<F, S, B>
where
S: ServiceFactory<Request>,
S::Error: ResponseError + 'static,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static,
S::Future: 'static,
<S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static,
S::Response: Into<Response<B>>,
B: MessageBody,
{
/// Create builder for `HttpService` instance.
pub fn build() -> HttpServiceBuilder<F, S> {
@ -46,13 +44,11 @@ where
impl<F, S, B> HttpService<F, S, B>
where
F: Filter,
S: ServiceFactory<Request>,
S::Error: ResponseError + 'static,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static,
S::Future: 'static,
<S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static,
S::Response: Into<Response<B>>,
B: MessageBody,
{
/// Create new `HttpService` instance.
pub fn new<U: IntoServiceFactory<S, Request>>(service: U) -> Self {
@ -92,12 +88,10 @@ where
impl<F, S, B, X, U> HttpService<F, S, B, X, U>
where
F: Filter,
S: ServiceFactory<Request>,
S::Error: ResponseError + 'static,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static,
S::Future: 'static,
<S::Service as Service<Request>>::Future: 'static,
S::Response: Into<Response<B>>,
B: MessageBody,
{
/// Provide service for `EXPECT: 100-Continue` support.
@ -164,12 +158,10 @@ mod openssl {
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>>,
S::Future: 'static,
B: MessageBody + 'static,
B: MessageBody,
X: ServiceFactory<Request, Response = Request> + 'static,
X::Error: ResponseError,
X::InitError: fmt::Debug,
X::Future: 'static,
U: ServiceFactory<(Request, Io<SslFilter<F>>, h1::Codec), Response = ()> + 'static,
U::Error: fmt::Display + error::Error,
U::InitError: fmt::Debug,
@ -210,7 +202,7 @@ mod rustls {
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>>,
B: MessageBody + 'static,
B: MessageBody,
X: ServiceFactory<Request, Response = Request> + 'static,
X::Error: ResponseError,
X::InitError: fmt::Debug,
@ -244,12 +236,12 @@ mod rustls {
impl<F, S, B, X, U> ServiceFactory<Io<F>> for HttpService<F, S, B, X, U>
where
F: Filter + 'static,
F: Filter,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>>,
B: MessageBody + 'static,
B: MessageBody,
X: ServiceFactory<Request, Response = Request> + 'static,
X::Error: ResponseError,
X::InitError: fmt::Debug,
@ -307,14 +299,13 @@ pub struct HttpServiceHandler<F, S, B, X, U> {
impl<F, S, B, X, U> Service<Io<F>> for HttpServiceHandler<F, S, B, X, U>
where
F: Filter + 'static,
S: Service<Request>,
S::Error: ResponseError + 'static,
S::Future: 'static,
S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static,
X: Service<Request, Response = Request>,
X::Error: ResponseError + 'static,
F: Filter,
S: Service<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
X: Service<Request, Response = Request> + 'static,
X::Error: ResponseError,
U: Service<(Request, Io<F>, h1::Codec), Response = ()> + 'static,
U::Error: fmt::Display + error::Error,
{
@ -410,14 +401,11 @@ pin_project_lite::pin_project! {
pub struct HttpServiceHandlerResponse<F, S, B, X, U>
where
F: Filter,
F: 'static,
S: Service<Request>,
S: 'static,
S::Error: ResponseError,
S::Error: 'static,
S::Response: Into<Response<B>>,
S::Response: 'static,
B: MessageBody,
B: 'static,
X: Service<Request, Response = Request>,
X::Error: ResponseError,
X::Error: 'static,
@ -435,11 +423,10 @@ pin_project_lite::pin_project! {
#[project = StateProject]
enum ResponseState<F, S, B, X, U>
where
S: Service<Request>,
S::Error: ResponseError,
S::Error: 'static,
F: Filter,
F: 'static,
S: Service<Request>,
S: 'static,
S::Error: ResponseError,
B: MessageBody,
X: Service<Request, Response = Request>,
X::Error: ResponseError,
@ -463,14 +450,13 @@ pin_project_lite::pin_project! {
impl<F, S, B, X, U> future::Future for HttpServiceHandlerResponse<F, S, B, X, U>
where
F: Filter + 'static,
S: Service<Request>,
S::Error: ResponseError + 'static,
S::Future: 'static,
S::Response: Into<Response<B>> + 'static,
F: Filter,
S: Service<Request> + 'static,
S::Error: ResponseError,
S::Response: Into<Response<B>>,
B: MessageBody,
X: Service<Request, Response = Request>,
X::Error: ResponseError + 'static,
X: Service<Request, Response = Request> + 'static,
X::Error: ResponseError,
U: Service<(Request, Io<F>, h1::Codec), Response = ()> + 'static,
U::Error: fmt::Display + error::Error,
{

View file

@ -449,35 +449,6 @@ where
F::Future: 'static,
Err: ErrorRenderer,
{
/// Construct service factory with default `AppConfig`, suitable for `http::HttpService`.
///
/// ```rust,no_run
/// use ntex::{web, http, server};
///
/// #[ntex::main]
/// async fn main() -> std::io::Result<()> {
/// server::build().bind("http", "127.0.0.1:0", |_|
/// http::HttpService::build().finish(
/// web::App::new()
/// .route("/index.html", web::get().to(|| async { "hello_world" }))
/// .finish()
/// )
/// )?
/// .run()
/// .await
/// }
/// ```
pub fn finish(
self,
) -> impl ServiceFactory<
Request,
Response = WebResponse,
Error = Err::Container,
InitError = (),
> {
map_config(self.into_factory(), move |_| Default::default())
}
/// Construct service factory suitable for `http::HttpService`.
///
/// ```rust,no_run
@ -505,7 +476,18 @@ where
Error = Err::Container,
InitError = (),
> {
map_config(self.into_factory(), move |_| cfg.clone())
let app = AppFactory {
filter: self.filter,
middleware: Rc::new(self.middleware),
data: Rc::new(self.data),
data_factories: Rc::new(self.data_factories),
services: Rc::new(RefCell::new(self.services)),
external: RefCell::new(self.external),
default: self.default,
extensions: RefCell::new(Some(self.extensions)),
case_insensitive: self.case_insensitive,
};
map_config(app, move |_| cfg.clone())
}
}
@ -538,6 +520,34 @@ where
}
}
impl<M, F, Err> IntoServiceFactory<AppFactory<M, F, Err>, Request, ()> for App<M, F, Err>
where
M: Transform<AppService<F::Service, Err>> + 'static,
M::Service: Service<WebRequest<Err>, Response = WebResponse, Error = Err::Container>,
F: ServiceFactory<
WebRequest<Err>,
Response = WebRequest<Err>,
Error = Err::Container,
InitError = (),
>,
F::Future: 'static,
Err: ErrorRenderer,
{
fn into_factory(self) -> AppFactory<M, F, Err> {
AppFactory {
filter: self.filter,
middleware: Rc::new(self.middleware),
data: Rc::new(self.data),
data_factories: Rc::new(self.data_factories),
services: Rc::new(RefCell::new(self.services)),
external: RefCell::new(self.external),
default: self.default,
extensions: RefCell::new(Some(self.extensions)),
case_insensitive: self.case_insensitive,
}
}
}
pub struct Stack<Inner, Outer> {
inner: Inner,
outer: Outer,

View file

@ -51,6 +51,30 @@ where
pub(super) case_insensitive: bool,
}
impl<T, F, Err> ServiceFactory<Request> for AppFactory<T, F, Err>
where
T: Transform<AppService<F::Service, Err>> + 'static,
T::Service: Service<WebRequest<Err>, Response = WebResponse, Error = Err::Container>,
F: ServiceFactory<
WebRequest<Err>,
Response = WebRequest<Err>,
Error = Err::Container,
InitError = (),
>,
F::Future: 'static,
Err: ErrorRenderer,
{
type Response = WebResponse;
type Error = Err::Container;
type InitError = ();
type Service = AppFactoryService<T::Service, Err>;
type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
fn new_service(&self, _: ()) -> Self::Future {
ServiceFactory::<Request, AppConfig>::new_service(self, AppConfig::default())
}
}
impl<T, F, Err> ServiceFactory<Request, AppConfig> for AppFactory<T, F, Err>
where
T: Transform<AppService<F::Service, Err>> + 'static,