mirror of
https://github.com/tokio-rs/axum.git
synced 2024-10-23 17:36:39 +02:00
WIP
This commit is contained in:
parent
978ae63358
commit
b8e1aad4d6
10 changed files with 89 additions and 84 deletions
5
axum-core/src/layer.rs
Normal file
5
axum-core/src/layer.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
trait Layer<S> {
|
||||||
|
type Service;
|
||||||
|
|
||||||
|
fn layer(&self, inner: S) -> Self::Service;
|
||||||
|
}
|
|
@ -48,13 +48,19 @@
|
||||||
#![allow(elided_lifetimes_in_paths, clippy::type_complexity)]
|
#![allow(elided_lifetimes_in_paths, clippy::type_complexity)]
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
#![cfg_attr(test, allow(clippy::float_cmp))]
|
#![cfg_attr(test, allow(clippy::float_cmp))]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub(crate) mod macros;
|
pub(crate) mod macros;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod ext_traits;
|
mod ext_traits;
|
||||||
|
//mod layer;
|
||||||
|
mod service;
|
||||||
|
|
||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
|
pub use self::ext_traits::{request::RequestExt, request_parts::RequestPartsExt};
|
||||||
|
pub use self::service::Service;
|
||||||
|
|
||||||
pub mod body;
|
pub mod body;
|
||||||
pub mod extract;
|
pub mod extract;
|
||||||
|
@ -62,5 +68,3 @@ pub mod response;
|
||||||
|
|
||||||
/// Alias for a type-erased error type.
|
/// Alias for a type-erased error type.
|
||||||
pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
|
pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
|
||||||
|
|
||||||
pub use self::ext_traits::{request::RequestExt, request_parts::RequestPartsExt};
|
|
||||||
|
|
39
axum-core/src/service.rs
Normal file
39
axum-core/src/service.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#![allow(missing_docs)] // temporary
|
||||||
|
|
||||||
|
use http::Request;
|
||||||
|
use std::{
|
||||||
|
convert::Infallible,
|
||||||
|
future::Future,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
use tower_service::Service as TowerService;
|
||||||
|
|
||||||
|
use crate::response::{IntoResponse, Response};
|
||||||
|
|
||||||
|
pub trait Service<S, ReqBody> {
|
||||||
|
type Future: Future<Output = Response>;
|
||||||
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<()>;
|
||||||
|
fn call(&mut self, req: Request<ReqBody>, state: &S) -> Self::Future;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, S, ReqBody, Resp> Service<S, ReqBody> for T
|
||||||
|
where
|
||||||
|
T: TowerService<Request<ReqBody>, Response = Resp, Error = Infallible>,
|
||||||
|
Resp: IntoResponse,
|
||||||
|
{
|
||||||
|
type Future = impl Future<Output = Response>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<()> {
|
||||||
|
TowerService::poll_ready(self, cx).map(|result| result.unwrap_or_else(|e| match e {}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, req: Request<ReqBody>, _state: &S) -> Self::Future {
|
||||||
|
let fut = TowerService::call(self, req);
|
||||||
|
async move {
|
||||||
|
match fut.await {
|
||||||
|
Ok(res) => res.into_response(),
|
||||||
|
Err(e) => match e {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -145,7 +145,7 @@ pub trait Handler<T, S, B = Body>: Clone + Send + Sized + 'static {
|
||||||
fn layer<L, NewReqBody>(self, layer: L) -> Layered<L, Self, T, S, B, NewReqBody>
|
fn layer<L, NewReqBody>(self, layer: L) -> Layered<L, Self, T, S, B, NewReqBody>
|
||||||
where
|
where
|
||||||
L: Layer<HandlerService<Self, T, S, B>> + Clone,
|
L: Layer<HandlerService<Self, T, S, B>> + Clone,
|
||||||
L::Service: Service<Request<NewReqBody>>,
|
L::Service: crate::Service<S, NewReqBody>,
|
||||||
{
|
{
|
||||||
Layered {
|
Layered {
|
||||||
layer,
|
layer,
|
||||||
|
|
|
@ -487,7 +487,7 @@ pub use self::typed_header::TypedHeader;
|
||||||
pub use self::form::Form;
|
pub use self::form::Form;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use axum_core::{BoxError, Error, RequestExt, RequestPartsExt};
|
pub use axum_core::{BoxError, Error, RequestExt, RequestPartsExt, Service};
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
pub use axum_macros::debug_handler;
|
pub use axum_macros::debug_handler;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
extract::FromRequestParts,
|
extract::FromRequestParts,
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
|
Service,
|
||||||
};
|
};
|
||||||
use futures_util::{future::BoxFuture, ready};
|
use futures_util::{future::BoxFuture, ready};
|
||||||
use http::Request;
|
use http::Request;
|
||||||
|
@ -13,7 +14,6 @@ use std::{
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
use tower_layer::Layer;
|
use tower_layer::Layer;
|
||||||
use tower_service::Service;
|
|
||||||
|
|
||||||
/// Create a middleware from an extractor.
|
/// Create a middleware from an extractor.
|
||||||
///
|
///
|
||||||
|
@ -90,16 +90,8 @@ use tower_service::Service;
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`Bytes`]: bytes::Bytes
|
/// [`Bytes`]: bytes::Bytes
|
||||||
pub fn from_extractor<E>() -> FromExtractorLayer<E, ()> {
|
pub fn from_extractor<E>() -> FromExtractorLayer<E> {
|
||||||
from_extractor_with_state(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a middleware from an extractor with the given state.
|
|
||||||
///
|
|
||||||
/// See [`State`](crate::extract::State) for more details about accessing state.
|
|
||||||
pub fn from_extractor_with_state<E, S>(state: S) -> FromExtractorLayer<E, S> {
|
|
||||||
FromExtractorLayer {
|
FromExtractorLayer {
|
||||||
state,
|
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,45 +102,32 @@ pub fn from_extractor_with_state<E, S>(state: S) -> FromExtractorLayer<E, S> {
|
||||||
/// See [`from_extractor`] for more details.
|
/// See [`from_extractor`] for more details.
|
||||||
///
|
///
|
||||||
/// [`Layer`]: tower::Layer
|
/// [`Layer`]: tower::Layer
|
||||||
pub struct FromExtractorLayer<E, S> {
|
pub struct FromExtractorLayer<E> {
|
||||||
state: S,
|
|
||||||
_marker: PhantomData<fn() -> E>,
|
_marker: PhantomData<fn() -> E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, S> Clone for FromExtractorLayer<E, S>
|
impl<E> Clone for FromExtractorLayer<E> {
|
||||||
where
|
|
||||||
S: Clone,
|
|
||||||
{
|
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: self.state.clone(),
|
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, S> fmt::Debug for FromExtractorLayer<E, S>
|
impl<E> fmt::Debug for FromExtractorLayer<E> {
|
||||||
where
|
|
||||||
S: fmt::Debug,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("FromExtractorLayer")
|
f.debug_struct("FromExtractorLayer")
|
||||||
.field("state", &self.state)
|
|
||||||
.field("extractor", &format_args!("{}", std::any::type_name::<E>()))
|
.field("extractor", &format_args!("{}", std::any::type_name::<E>()))
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, T, S> Layer<T> for FromExtractorLayer<E, S>
|
impl<E, T> Layer<T> for FromExtractorLayer<E> {
|
||||||
where
|
type Service = FromExtractor<T, E>;
|
||||||
S: Clone,
|
|
||||||
{
|
|
||||||
type Service = FromExtractor<T, E, S>;
|
|
||||||
|
|
||||||
fn layer(&self, inner: T) -> Self::Service {
|
fn layer(&self, inner: T) -> Self::Service {
|
||||||
FromExtractor {
|
FromExtractor {
|
||||||
inner,
|
inner,
|
||||||
state: self.state.clone(),
|
|
||||||
_extractor: PhantomData,
|
_extractor: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,66 +136,58 @@ where
|
||||||
/// Middleware that runs an extractor and discards the value.
|
/// Middleware that runs an extractor and discards the value.
|
||||||
///
|
///
|
||||||
/// See [`from_extractor`] for more details.
|
/// See [`from_extractor`] for more details.
|
||||||
pub struct FromExtractor<T, E, S> {
|
pub struct FromExtractor<T, E> {
|
||||||
inner: T,
|
inner: T,
|
||||||
state: S,
|
|
||||||
_extractor: PhantomData<fn() -> E>,
|
_extractor: PhantomData<fn() -> E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn traits() {
|
fn traits() {
|
||||||
use crate::test_helpers::*;
|
use crate::test_helpers::*;
|
||||||
assert_send::<FromExtractor<(), NotSendSync, ()>>();
|
assert_send::<FromExtractor<(), NotSendSync>>();
|
||||||
assert_sync::<FromExtractor<(), NotSendSync, ()>>();
|
assert_sync::<FromExtractor<(), NotSendSync>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, E, S> Clone for FromExtractor<T, E, S>
|
impl<T, E> Clone for FromExtractor<T, E>
|
||||||
where
|
where
|
||||||
T: Clone,
|
T: Clone,
|
||||||
S: Clone,
|
|
||||||
{
|
{
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: self.inner.clone(),
|
inner: self.inner.clone(),
|
||||||
state: self.state.clone(),
|
|
||||||
_extractor: PhantomData,
|
_extractor: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, E, S> fmt::Debug for FromExtractor<T, E, S>
|
impl<T, E> fmt::Debug for FromExtractor<T, E>
|
||||||
where
|
where
|
||||||
T: fmt::Debug,
|
T: fmt::Debug,
|
||||||
S: fmt::Debug,
|
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("FromExtractor")
|
f.debug_struct("FromExtractor")
|
||||||
.field("inner", &self.inner)
|
.field("inner", &self.inner)
|
||||||
.field("state", &self.state)
|
|
||||||
.field("extractor", &format_args!("{}", std::any::type_name::<E>()))
|
.field("extractor", &format_args!("{}", std::any::type_name::<E>()))
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, E, B, S> Service<Request<B>> for FromExtractor<T, E, S>
|
impl<T, E, B, S> Service<S, B> for FromExtractor<T, E>
|
||||||
where
|
where
|
||||||
E: FromRequestParts<S> + 'static,
|
E: FromRequestParts<S> + 'static,
|
||||||
B: Send + 'static,
|
B: Send + 'static,
|
||||||
T: Service<Request<B>> + Clone,
|
T: Service<S, B> + Clone,
|
||||||
T::Response: IntoResponse,
|
|
||||||
S: Clone + Send + Sync + 'static,
|
S: Clone + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
type Response = Response;
|
|
||||||
type Error = T::Error;
|
|
||||||
type Future = ResponseFuture<B, T, E, S>;
|
type Future = ResponseFuture<B, T, E, S>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<()> {
|
||||||
self.inner.poll_ready(cx)
|
self.inner.poll_ready(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Request<B>) -> Self::Future {
|
fn call(&mut self, req: Request<B>, st: &S) -> Self::Future {
|
||||||
let state = self.state.clone();
|
let state = st.to_owned();
|
||||||
let extract_future = Box::pin(async move {
|
let extract_future = Box::pin(async move {
|
||||||
let (mut parts, body) = req.into_parts();
|
let (mut parts, body) = req.into_parts();
|
||||||
let extracted = E::from_request_parts(&mut parts, &state).await;
|
let extracted = E::from_request_parts(&mut parts, &state).await;
|
||||||
|
@ -226,6 +197,7 @@ where
|
||||||
|
|
||||||
ResponseFuture {
|
ResponseFuture {
|
||||||
state: State::Extracting {
|
state: State::Extracting {
|
||||||
|
st: st.clone(),
|
||||||
future: extract_future,
|
future: extract_future,
|
||||||
},
|
},
|
||||||
svc: Some(self.inner.clone()),
|
svc: Some(self.inner.clone()),
|
||||||
|
@ -239,7 +211,7 @@ pin_project! {
|
||||||
pub struct ResponseFuture<B, T, E, S>
|
pub struct ResponseFuture<B, T, E, S>
|
||||||
where
|
where
|
||||||
E: FromRequestParts<S>,
|
E: FromRequestParts<S>,
|
||||||
T: Service<Request<B>>,
|
T: Service<S, B>,
|
||||||
{
|
{
|
||||||
#[pin]
|
#[pin]
|
||||||
state: State<B, T, E, S>,
|
state: State<B, T, E, S>,
|
||||||
|
@ -252,9 +224,10 @@ pin_project! {
|
||||||
enum State<B, T, E, S>
|
enum State<B, T, E, S>
|
||||||
where
|
where
|
||||||
E: FromRequestParts<S>,
|
E: FromRequestParts<S>,
|
||||||
T: Service<Request<B>>,
|
T: Service<S, B>,
|
||||||
{
|
{
|
||||||
Extracting {
|
Extracting {
|
||||||
|
st: S,
|
||||||
future: BoxFuture<'static, (Request<B>, Result<E, E::Rejection>)>,
|
future: BoxFuture<'static, (Request<B>, Result<E, E::Rejection>)>,
|
||||||
},
|
},
|
||||||
Call { #[pin] future: T::Future },
|
Call { #[pin] future: T::Future },
|
||||||
|
@ -264,35 +237,32 @@ pin_project! {
|
||||||
impl<B, T, E, S> Future for ResponseFuture<B, T, E, S>
|
impl<B, T, E, S> Future for ResponseFuture<B, T, E, S>
|
||||||
where
|
where
|
||||||
E: FromRequestParts<S>,
|
E: FromRequestParts<S>,
|
||||||
T: Service<Request<B>>,
|
T: Service<S, B>,
|
||||||
T::Response: IntoResponse,
|
|
||||||
{
|
{
|
||||||
type Output = Result<Response, T::Error>;
|
type Output = Response;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
loop {
|
loop {
|
||||||
let mut this = self.as_mut().project();
|
let mut this = self.as_mut().project();
|
||||||
|
|
||||||
let new_state = match this.state.as_mut().project() {
|
let new_state = match this.state.as_mut().project() {
|
||||||
StateProj::Extracting { future } => {
|
StateProj::Extracting { future, st } => {
|
||||||
let (req, extracted) = ready!(future.as_mut().poll(cx));
|
let (req, extracted) = ready!(future.as_mut().poll(cx));
|
||||||
|
|
||||||
match extracted {
|
match extracted {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let mut svc = this.svc.take().expect("future polled after completion");
|
let mut svc = this.svc.take().expect("future polled after completion");
|
||||||
let future = svc.call(req);
|
let future = svc.call(req, st);
|
||||||
State::Call { future }
|
State::Call { future }
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let res = err.into_response();
|
let res = err.into_response();
|
||||||
return Poll::Ready(Ok(res));
|
return Poll::Ready(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StateProj::Call { future } => {
|
StateProj::Call { future } => {
|
||||||
return future
|
return future.poll(cx);
|
||||||
.poll(cx)
|
|
||||||
.map(|result| result.map(IntoResponse::into_response));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -346,10 +316,7 @@ mod tests {
|
||||||
async fn handler() {}
|
async fn handler() {}
|
||||||
|
|
||||||
let state = Secret("secret");
|
let state = Secret("secret");
|
||||||
let app = Router::new().route(
|
let app = Router::new().route("/", get(handler.layer(from_extractor())));
|
||||||
"/",
|
|
||||||
get(handler.layer(from_extractor_with_state::<RequireAuth, _>(state))),
|
|
||||||
);
|
|
||||||
|
|
||||||
let client = TestClient::new(app);
|
let client = TestClient::new(app);
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,7 @@ mod from_fn;
|
||||||
mod map_request;
|
mod map_request;
|
||||||
mod map_response;
|
mod map_response;
|
||||||
|
|
||||||
pub use self::from_extractor::{
|
pub use self::from_extractor::{from_extractor, FromExtractor, FromExtractorLayer};
|
||||||
from_extractor, from_extractor_with_state, FromExtractor, FromExtractorLayer,
|
|
||||||
};
|
|
||||||
pub use self::from_fn::{from_fn, from_fn_with_state, FromFn, FromFnLayer, Next};
|
pub use self::from_fn::{from_fn, from_fn_with_state, FromFn, FromFnLayer, Next};
|
||||||
pub use self::map_request::{
|
pub use self::map_request::{
|
||||||
map_request, map_request_with_state, IntoMapRequestResult, MapRequest, MapRequestLayer,
|
map_request, map_request_with_state, IntoMapRequestResult, MapRequest, MapRequestLayer,
|
||||||
|
|
|
@ -919,10 +919,8 @@ where
|
||||||
pub fn layer<L, NewReqBody, NewError>(self, layer: L) -> MethodRouter<S, NewReqBody, NewError>
|
pub fn layer<L, NewReqBody, NewError>(self, layer: L) -> MethodRouter<S, NewReqBody, NewError>
|
||||||
where
|
where
|
||||||
L: Layer<Route<B, E>> + Clone + Send + 'static,
|
L: Layer<Route<B, E>> + Clone + Send + 'static,
|
||||||
L::Service: Service<Request<NewReqBody>> + Clone + Send + 'static,
|
L::Service: crate::Service<S, NewReqBody> + Clone + Send + 'static,
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Response: IntoResponse + 'static,
|
<L::Service as crate::Service<S, NewReqBody>>::Future: Send + 'static,
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Error: Into<NewError> + 'static,
|
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Future: Send + 'static,
|
|
||||||
E: 'static,
|
E: 'static,
|
||||||
S: 'static,
|
S: 'static,
|
||||||
NewReqBody: HttpBody + 'static,
|
NewReqBody: HttpBody + 'static,
|
||||||
|
|
|
@ -314,10 +314,8 @@ where
|
||||||
pub fn layer<L, NewReqBody>(self, layer: L) -> Router<S, NewReqBody>
|
pub fn layer<L, NewReqBody>(self, layer: L) -> Router<S, NewReqBody>
|
||||||
where
|
where
|
||||||
L: Layer<Route<B>> + Clone + Send + 'static,
|
L: Layer<Route<B>> + Clone + Send + 'static,
|
||||||
L::Service: Service<Request<NewReqBody>> + Clone + Send + 'static,
|
L::Service: crate::Service<S, NewReqBody> + Clone + Send + 'static,
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Response: IntoResponse + 'static,
|
<L::Service as crate::Service<S, NewReqBody>>::Future: Send + 'static,
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Error: Into<Infallible> + 'static,
|
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Future: Send + 'static,
|
|
||||||
NewReqBody: HttpBody + 'static,
|
NewReqBody: HttpBody + 'static,
|
||||||
{
|
{
|
||||||
let routes = self
|
let routes = self
|
||||||
|
@ -688,10 +686,8 @@ where
|
||||||
fn layer<L, NewReqBody>(self, layer: L) -> Endpoint<S, NewReqBody>
|
fn layer<L, NewReqBody>(self, layer: L) -> Endpoint<S, NewReqBody>
|
||||||
where
|
where
|
||||||
L: Layer<Route<B>> + Clone + Send + 'static,
|
L: Layer<Route<B>> + Clone + Send + 'static,
|
||||||
L::Service: Service<Request<NewReqBody>> + Clone + Send + 'static,
|
L::Service: crate::Service<S, NewReqBody> + Clone + Send + 'static,
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Response: IntoResponse + 'static,
|
<L::Service as crate::Service<S, NewReqBody>>::Future: Send + 'static,
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Error: Into<Infallible> + 'static,
|
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Future: Send + 'static,
|
|
||||||
NewReqBody: HttpBody + 'static,
|
NewReqBody: HttpBody + 'static,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -51,10 +51,8 @@ impl<B, E> Route<B, E> {
|
||||||
pub(crate) fn layer<L, NewReqBody, NewError>(self, layer: L) -> Route<NewReqBody, NewError>
|
pub(crate) fn layer<L, NewReqBody, NewError>(self, layer: L) -> Route<NewReqBody, NewError>
|
||||||
where
|
where
|
||||||
L: Layer<Route<B, E>> + Clone + Send + 'static,
|
L: Layer<Route<B, E>> + Clone + Send + 'static,
|
||||||
L::Service: Service<Request<NewReqBody>> + Clone + Send + 'static,
|
L::Service: crate::Service<S, NewReqBody> + Clone + Send + 'static,
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Response: IntoResponse + 'static,
|
<L::Service as crate::Service<S, NewReqBody>>::Future: Send + 'static,
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Error: Into<NewError> + 'static,
|
|
||||||
<L::Service as Service<Request<NewReqBody>>>::Future: Send + 'static,
|
|
||||||
NewReqBody: 'static,
|
NewReqBody: 'static,
|
||||||
NewError: 'static,
|
NewError: 'static,
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue