mirror of
https://github.com/ntex-rs/ntex.git
synced 2025-04-01 20:07:39 +03:00
refactor Factory trait
This commit is contained in:
parent
d2edbdf9f1
commit
c1607f1698
16 changed files with 96 additions and 108 deletions
|
@ -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" }
|
||||
|
|
|
@ -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]
|
|
@ -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,
|
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -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" }))
|
||||
})
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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,)+)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue