refactor Factory trait

This commit is contained in:
Nikolay Kim 2020-04-01 14:34:45 +06:00
parent d2edbdf9f1
commit c1607f1698
16 changed files with 96 additions and 108 deletions

View file

@ -6,7 +6,7 @@ members = [
"ntex-rt",
"ntex-rt-macros",
"ntex-service",
# "ntex-web-macros",
"ntex-macros",
]
[patch.crates-io]
@ -16,4 +16,4 @@ ntex-router = { path = "ntex-router" }
ntex-rt = { path = "ntex-rt" }
ntex-rt-macros = { path = "ntex-rt-macros" }
ntex-service = { path = "ntex-service" }
ntex-web-macros = { path = "ntex-web-macros" }
ntex-macros = { path = "ntex-macros" }

View file

@ -1,10 +1,10 @@
[package]
name = "ntex-web-macros"
name = "ntex-macros"
version = "0.1.0"
description = "ntex web proc macros"
description = "ntex proc macros"
readme = "README.md"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
license = "MIT/Apache-2.0"
license = "MIT"
edition = "2018"
[lib]

View file

@ -7,15 +7,15 @@
//!
//! Macros:
//!
//! - [get](attr.get.html)
//! - [post](attr.post.html)
//! - [put](attr.put.html)
//! - [delete](attr.delete.html)
//! - [head](attr.head.html)
//! - [connect](attr.connect.html)
//! - [options](attr.options.html)
//! - [trace](attr.trace.html)
//! - [patch](attr.patch.html)
//! - [web_get](attr.get.html)
//! - [web_post](attr.post.html)
//! - [web_put](attr.put.html)
//! - [web_delete](attr.delete.html)
//! - [web_head](attr.head.html)
//! - [web_connect](attr.connect.html)
//! - [web_options](attr.options.html)
//! - [web_trace](attr.trace.html)
//! - [web_patch](attr.patch.html)
//!
//! ### Attributes:
//!
@ -55,7 +55,7 @@ use syn::parse_macro_input;
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
/// - `guard="function_name"` - Registers function as guard using `ntex::web::guard::fn_guard`
#[proc_macro_attribute]
pub fn get(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_get(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Get) {
Ok(gen) => gen,
@ -70,7 +70,7 @@ pub fn get(args: TokenStream, input: TokenStream) -> TokenStream {
///
/// Attributes are the same as in [get](attr.get.html)
#[proc_macro_attribute]
pub fn post(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_post(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Post) {
Ok(gen) => gen,
@ -85,7 +85,7 @@ pub fn post(args: TokenStream, input: TokenStream) -> TokenStream {
///
/// Attributes are the same as in [get](attr.get.html)
#[proc_macro_attribute]
pub fn put(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_put(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Put) {
Ok(gen) => gen,
@ -100,7 +100,7 @@ pub fn put(args: TokenStream, input: TokenStream) -> TokenStream {
///
/// Attributes are the same as in [get](attr.get.html)
#[proc_macro_attribute]
pub fn delete(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_delete(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Delete) {
Ok(gen) => gen,
@ -115,7 +115,7 @@ pub fn delete(args: TokenStream, input: TokenStream) -> TokenStream {
///
/// Attributes are the same as in [head](attr.head.html)
#[proc_macro_attribute]
pub fn head(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_head(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Head) {
Ok(gen) => gen,
@ -130,7 +130,7 @@ pub fn head(args: TokenStream, input: TokenStream) -> TokenStream {
///
/// Attributes are the same as in [connect](attr.connect.html)
#[proc_macro_attribute]
pub fn connect(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_connect(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Connect) {
Ok(gen) => gen,
@ -145,7 +145,7 @@ pub fn connect(args: TokenStream, input: TokenStream) -> TokenStream {
///
/// Attributes are the same as in [options](attr.options.html)
#[proc_macro_attribute]
pub fn options(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_options(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Options) {
Ok(gen) => gen,
@ -160,7 +160,7 @@ pub fn options(args: TokenStream, input: TokenStream) -> TokenStream {
///
/// Attributes are the same as in [trace](attr.trace.html)
#[proc_macro_attribute]
pub fn trace(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_trace(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Trace) {
Ok(gen) => gen,
@ -175,7 +175,7 @@ pub fn trace(args: TokenStream, input: TokenStream) -> TokenStream {
///
/// Attributes are the same as in [patch](attr.patch.html)
#[proc_macro_attribute]
pub fn patch(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn web_patch(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Patch) {
Ok(gen) => gen,

View file

@ -161,7 +161,7 @@ impl Route {
.unwrap();
let stream = quote! {
// #[allow(non_camel_case_types)]
#[allow(non_camel_case_types)]
pub struct #name;
impl<__E: 'static> ntex::web::dev::HttpServiceFactory<__E> for #name

View file

@ -41,7 +41,7 @@ ntex-rt = "0.1"
ntex-rt-macros = "0.1"
ntex-router = "0.3"
ntex-service = "0.1"
ntex-web-macros = "0.1"
ntex-macros = "0.1"
actix-threadpool = "0.3.1"
base64 = "0.12"

View file

@ -37,7 +37,7 @@ async fn main() -> std::io::Result<()> {
.default_service(
web::route().to(|| async { HttpResponse::MethodNotAllowed() }),
)
.route(web::get().to(web::dev::__assert_handler1(index_async))),
.route(web::get().to(index_async)),
)
.service(web::resource("/test1.html").to(|| async { "Test\r\n" }))
})

View file

@ -27,7 +27,6 @@ async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2"))
.wrap(middleware::Compress::default())
.wrap(middleware::Logger::default())
.service(web::resource("/resource1/{name}/index.html").to(index))
.service(web::resource("/").route(web::get().to(no_params)))

View file

@ -12,23 +12,27 @@ use super::request::HttpRequest;
use super::responder::Responder;
use super::service::{WebRequest, WebResponse};
/// Async handler converter factory
pub trait Factory<T, R, O, Err>: Clone + 'static
/// Async fn handler factory
pub trait Factory<T, Err>: Clone + 'static
where
R: Future<Output = O>,
O: Responder<Err>,
Err: ErrorRenderer,
{
fn call(&self, param: T) -> R;
type Future: Future<Output = Self::Result> + 'static;
type Result: Responder<Err>;
fn call(&self, param: T) -> Self::Future;
}
impl<F, R, O, Err> Factory<(), R, O, Err> for F
impl<F, R, Err> Factory<(), Err> for F
where
F: Fn() -> R + Clone + 'static,
R: Future<Output = O>,
O: Responder<Err>,
R: Future + 'static,
R::Output: Responder<Err>,
Err: ErrorRenderer,
{
type Future = R;
type Result = R::Output;
fn call(&self, _: ()) -> R {
(self)()
}
@ -45,12 +49,12 @@ pub(super) trait HandlerFn<Err: ErrorRenderer> {
pub(super) struct Handler<F, T, R, O, Err>
where
F: Factory<T, R, O, Err>,
F: Factory<T, Err, Future = R, Result = O>,
T: FromRequest<Err>,
<T as FromRequest<Err>>::Error: Into<Err::Container>,
R: Future<Output = O>,
T::Error: Into<Err::Container>,
R: Future<Output = O> + 'static,
O: Responder<Err>,
<O as Responder<Err>>::Error: Into<Err::Container>,
O::Error: Into<Err::Container>,
Err: ErrorRenderer,
{
hnd: F,
@ -59,12 +63,12 @@ where
impl<F, T, R, O, Err> Handler<F, T, R, O, Err>
where
F: Factory<T, R, O, Err>,
F: Factory<T, Err, Future = R, Result = O>,
T: FromRequest<Err>,
<T as FromRequest<Err>>::Error: Into<Err::Container>,
R: Future<Output = O>,
T::Error: Into<Err::Container>,
R: Future<Output = O> + 'static,
O: Responder<Err>,
<O as Responder<Err>>::Error: Into<Err::Container>,
O::Error: Into<Err::Container>,
Err: ErrorRenderer,
{
pub(super) fn new(hnd: F) -> Self {
@ -77,12 +81,12 @@ where
impl<F, T, R, O, Err> HandlerFn<Err> for Handler<F, T, R, O, Err>
where
F: Factory<T, R, O, Err>,
F: Factory<T, Err, Future = R, Result = O>,
T: FromRequest<Err> + 'static,
<T as FromRequest<Err>>::Error: Into<Err::Container>,
T::Error: Into<Err::Container>,
R: Future<Output = O> + 'static,
O: Responder<Err> + 'static,
<O as Responder<Err>>::Error: Into<Err::Container>,
O::Error: Into<Err::Container>,
Err: ErrorRenderer,
{
fn call(
@ -111,12 +115,12 @@ where
impl<F, T, R, O, Err> Clone for Handler<F, T, R, O, Err>
where
F: Factory<T, R, O, Err>,
F: Factory<T, Err, Future = R, Result = O>,
T: FromRequest<Err>,
<T as FromRequest<Err>>::Error: Into<Err::Container>,
R: Future<Output = O>,
T::Error: Into<Err::Container>,
R: Future<Output = O> + 'static,
O: Responder<Err>,
<O as Responder<Err>>::Error: Into<Err::Container>,
O::Error: Into<Err::Container>,
Err: ErrorRenderer,
{
fn clone(&self) -> Self {
@ -130,12 +134,12 @@ where
#[pin_project]
pub(super) struct HandlerWebResponse<F, T, R, O, Err>
where
F: Factory<T, R, O, Err>,
F: Factory<T, Err, Future = R, Result = O>,
T: FromRequest<Err>,
<T as FromRequest<Err>>::Error: Into<Err::Container>,
R: Future<Output = O>,
T::Error: Into<Err::Container>,
R: Future<Output = O> + 'static,
O: Responder<Err>,
<O as Responder<Err>>::Error: Into<Err::Container>,
O::Error: Into<Err::Container>,
Err: ErrorRenderer,
{
hnd: F,
@ -150,12 +154,12 @@ where
impl<F, T, R, O, Err> Future for HandlerWebResponse<F, T, R, O, Err>
where
F: Factory<T, R, O, Err>,
F: Factory<T, Err, Future = R, Result = O>,
T: FromRequest<Err>,
<T as FromRequest<Err>>::Error: Into<Err::Container>,
R: Future<Output = O>,
T::Error: Into<Err::Container>,
R: Future<Output = O> + 'static,
O: Responder<Err>,
<O as Responder<Err>>::Error: Into<Err::Container>,
O::Error: Into<Err::Container>,
Err: ErrorRenderer,
{
type Output = Result<WebResponse, Err::Container>;
@ -212,13 +216,15 @@ where
/// FromRequest trait impl for tuples
macro_rules! factory_tuple ({ $(($n:tt, $T:ident)),+} => {
impl<Func, $($T,)+ Res, O, Err> Factory<($($T,)+), Res, O, Err> for Func
impl<Func, $($T,)+ Res, Err> Factory<($($T,)+), Err> for Func
where Func: Fn($($T,)+) -> Res + Clone + 'static,
Res: Future<Output = O>,
O: Responder<Err>,
// <O as Responder<Err>>::Error: Into<Err::Container>,
Res: Future + 'static,
Res::Output: Responder<Err>,
Err: ErrorRenderer,
{
type Future = Res;
type Result = Res::Output;
fn call(&self, param: ($($T,)+)) -> Res {
(self)($(param.$n,)+)
}

View file

@ -91,7 +91,11 @@ pub mod test;
pub mod types;
mod util;
pub use ntex_web_macros::*;
pub use ntex_macros::{
web_connect as connect, web_delete as delete, web_get as get, web_head as head,
web_options as options, web_patch as patch, web_post as post, web_put as put,
web_trace as trace,
};
pub use crate::http::Response as HttpResponse;
pub use crate::http::ResponseBuilder as HttpResponseBuilder;
@ -190,15 +194,14 @@ pub mod dev {
#[doc(hidden)]
#[inline(always)]
pub fn __assert_handler<Err, Fun, Fut, Res>(
pub fn __assert_handler<Err, Fun, Fut>(
f: Fun,
) -> impl Factory<(), Fut, Res, Err>
) -> impl Factory<(), Err, Future = Fut, Result = Fut::Output>
where
Err: super::ErrorRenderer,
Fun: Fn() -> Fut + Clone + 'static,
Fut: std::future::Future<Output = Res>,
Res: super::Responder<Err>,
// <Res as super::Responder<Err>>::Error: Into<Err::Container>,
Fut: std::future::Future + 'static,
Fut::Output: super::Responder<Err>,
{
f
}
@ -206,17 +209,15 @@ pub mod dev {
macro_rules! assert_handler ({ $name:ident, $($T:ident),+} => {
#[doc(hidden)]
#[inline(always)]
pub fn $name<Err, Fun, Fut, Res, $($T,)+>(
pub fn $name<Err, Fun, Fut, $($T,)+>(
f: Fun,
) -> impl Factory<($($T,)+), Fut, Res, Err>
) -> impl Factory<($($T,)+), Err, Future = Fut, Result = Fut::Output>
where
Err: $crate::web::ErrorRenderer,
Fun: Fn($($T,)+) -> Fut + Clone + 'static,
Fut: std::future::Future<Output = Res>,
Res: $crate::web::Responder<Err>,
// <Res as $crate::web::Responder<Err>>::Error: Into<Err::Container>,
$($T: $crate::web::FromRequest<Err>),+,
// $(<$T as $crate::web::FromRequest<Err>>::Error: Into<Err::Container>),+
Fut: std::future::Future + 'static,
Fut::Output: $crate::web::Responder<Err>,
$($T: $crate::web::FromRequest<Err>),+,
{
f
}

View file

@ -229,14 +229,12 @@ where
/// # async fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
/// App::new().service(web::resource("/").route(web::route().to(index)));
/// ```
pub fn to<F, I, R, U>(mut self, handler: F) -> Self
pub fn to<F, Args>(mut self, handler: F) -> Self
where
F: Factory<I, R, U, Err>,
I: FromRequest<Err> + 'static,
<I as FromRequest<Err>>::Error: Into<Err::Container>,
R: Future<Output = U> + 'static,
U: Responder<Err> + 'static,
<U as Responder<Err>>::Error: Into<Err::Container>,
F: Factory<Args, Err>,
Args: FromRequest<Err> + 'static,
Args::Error: Into<Err::Container>,
<F::Result as Responder<Err>>::Error: Into<Err::Container>,
{
self.routes.push(Route::new().to(handler));
self

View file

@ -1,4 +1,3 @@
use std::future::Future;
use std::rc::Rc;
use std::task::{Context, Poll};
@ -180,30 +179,18 @@ impl<Err: ErrorRenderer> Route<Err> {
/// );
/// }
/// ```
pub fn to<F, T, R, U>(mut self, handler: F) -> Self
pub fn to<F, Args>(mut self, handler: F) -> Self
where
F: Factory<T, R, U, Err>,
T: FromRequest<Err> + 'static,
<T as FromRequest<Err>>::Error: Into<Err::Container>,
R: Future<Output = U> + 'static,
U: Responder<Err> + 'static,
<U as Responder<Err>>::Error: Into<Err::Container>,
F: Factory<Args, Err>,
Args: FromRequest<Err> + 'static,
Args::Error: Into<Err::Container>,
<F::Result as Responder<Err>>::Error: Into<Err::Container>,
{
self.handler = Box::new(Handler::new(handler));
self
}
}
// fn call(&mut self, req: WebRequest<Err>) -> Self::Future {
// self.service
// .call(req)
// .map(|res| match res {
// Ok(res) => Ok(res),
// Err((e, _)) => Err(e),
// })
// .boxed_local()
// }
#[cfg(test)]
mod tests {
use std::time::Duration;

View file

@ -1,6 +1,5 @@
//! Essentials helper functions and types for application registration.
use std::fmt;
use std::future::Future;
use ntex_router::IntoPattern;
@ -222,15 +221,13 @@ pub fn method<Err: ErrorRenderer>(method: Method) -> Route<Err> {
/// web::resource("/").route(web::to(index))
/// );
/// ```
pub fn to<F, I, R, U, Err>(handler: F) -> Route<Err>
pub fn to<F, Args, Err>(handler: F) -> Route<Err>
where
F: Factory<I, R, U, Err>,
I: FromRequest<Err> + 'static,
R: Future<Output = U> + 'static,
U: Responder<Err> + 'static,
F: Factory<Args, Err>,
Args: FromRequest<Err> + 'static,
Err: ErrorRenderer,
Err::Container: From<<I as FromRequest<Err>>::Error>,
Err::Container: From<<U as Responder<Err>>::Error>,
Err::Container: From<Args::Error>,
Err::Container: From<<F::Result as Responder<Err>>::Error>,
{
Route::new().to(handler)
}