mirror of
https://github.com/tokio-rs/axum.git
synced 2025-03-26 08:32:48 +01:00
Accept S::Response: IntoResponse
everywhere (#1165)
This commit is contained in:
parent
643909af6d
commit
b243e171fd
11 changed files with 96 additions and 99 deletions
|
@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning].
|
|||
|
||||
- **added:** Add `RouterExt::route_with_tsr` for adding routes with an
|
||||
additional "trailing slash redirect" route ([#1119])
|
||||
- **changed:** For methods that accept some `S: Service`, the bounds have been
|
||||
relaxed so the response type must implement `IntoResponse` rather than being a
|
||||
literal `Response`
|
||||
|
||||
[#1119]: https://github.com/tokio-rs/axum/pull/1119
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use axum::{
|
||||
handler::Handler,
|
||||
http::Request,
|
||||
response::{Redirect, Response},
|
||||
response::{IntoResponse, Redirect},
|
||||
Router,
|
||||
};
|
||||
use std::{convert::Infallible, future::ready};
|
||||
|
@ -161,7 +161,8 @@ pub trait RouterExt<B>: sealed::Sealed {
|
|||
/// ```
|
||||
fn route_with_tsr<T>(self, path: &str, service: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = Infallible> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse,
|
||||
T::Future: Send + 'static,
|
||||
Self: Sized;
|
||||
}
|
||||
|
@ -252,7 +253,8 @@ where
|
|||
|
||||
fn route_with_tsr<T>(mut self, path: &str, service: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = Infallible> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse,
|
||||
T::Future: Send + 'static,
|
||||
Self: Sized,
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@ use axum::{
|
|||
body::Body,
|
||||
handler::Handler,
|
||||
http::Request,
|
||||
response::Response,
|
||||
response::IntoResponse,
|
||||
routing::{delete, get, on, post, MethodFilter},
|
||||
Router,
|
||||
};
|
||||
|
@ -141,7 +141,8 @@ where
|
|||
/// The routes will be nested at `/{resource_name}/:{resource_name}_id`.
|
||||
pub fn nest<T>(mut self, svc: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = Infallible> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse,
|
||||
T::Future: Send + 'static,
|
||||
{
|
||||
let path = self.show_update_destroy_path();
|
||||
|
@ -154,7 +155,8 @@ where
|
|||
/// The routes will be nested at `/{resource_name}`.
|
||||
pub fn nest_collection<T>(mut self, svc: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = Infallible> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse,
|
||||
T::Future: Send + 'static,
|
||||
{
|
||||
let path = self.index_create_path();
|
||||
|
@ -172,7 +174,8 @@ where
|
|||
|
||||
fn route<T>(mut self, path: &str, svc: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = Infallible> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse,
|
||||
T::Future: Send + 'static,
|
||||
{
|
||||
self.router = self.router.route(path, svc);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use axum::{
|
||||
body::{Body, HttpBody},
|
||||
error_handling::HandleError,
|
||||
response::Response,
|
||||
response::IntoResponse,
|
||||
routing::{get_service, Route},
|
||||
Router,
|
||||
};
|
||||
|
@ -150,8 +150,8 @@ impl<B, T, F> SpaRouter<B, T, F> {
|
|||
impl<B, F, T> From<SpaRouter<B, T, F>> for Router<B>
|
||||
where
|
||||
F: Clone + Send + 'static,
|
||||
HandleError<Route<B, io::Error>, F, T>:
|
||||
Service<Request<B>, Response = Response, Error = Infallible>,
|
||||
HandleError<Route<B, io::Error>, F, T>: Service<Request<B>, Error = Infallible>,
|
||||
<HandleError<Route<B, io::Error>, F, T> as Service<Request<B>>>::Response: IntoResponse + Send,
|
||||
<HandleError<Route<B, io::Error>, F, T> as Service<Request<B>>>::Future: Send,
|
||||
B: HttpBody + Send + 'static,
|
||||
T: 'static,
|
||||
|
|
|
@ -29,6 +29,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- **added:** Support any middleware response that implements `IntoResponse` ([#1152])
|
||||
- **breaking:** Require middleware added with `Handler::layer` to have
|
||||
`Infallible` as the error type ([#1152])
|
||||
- **changed:** For methods that accept some `S: Service`, the bounds have been
|
||||
relaxed so the response type must implement `IntoResponse` rather than being a
|
||||
literal `Response`
|
||||
|
||||
[#1171]: https://github.com/tokio-rs/axum/pull/1171
|
||||
[#1077]: https://github.com/tokio-rs/axum/pull/1077
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#![doc = include_str!("../docs/error_handling.md")]
|
||||
|
||||
use crate::{
|
||||
body::{boxed, Bytes, HttpBody},
|
||||
body::boxed,
|
||||
extract::{FromRequest, RequestParts},
|
||||
http::{Request, StatusCode},
|
||||
response::{IntoResponse, Response},
|
||||
BoxError,
|
||||
};
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
|
@ -114,17 +113,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, F, ReqBody, ResBody, Fut, Res> Service<Request<ReqBody>> for HandleError<S, F, ()>
|
||||
impl<S, F, ReqBody, Fut, Res> Service<Request<ReqBody>> for HandleError<S, F, ()>
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||
S: Service<Request<ReqBody>> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + Send,
|
||||
S::Error: Send,
|
||||
S::Future: Send,
|
||||
F: FnOnce(S::Error) -> Fut + Clone + Send + 'static,
|
||||
Fut: Future<Output = Res> + Send,
|
||||
Res: IntoResponse,
|
||||
ReqBody: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
type Response = Response;
|
||||
type Error = Infallible;
|
||||
|
@ -142,7 +140,7 @@ where
|
|||
|
||||
let future = Box::pin(async move {
|
||||
match inner.oneshot(req).await {
|
||||
Ok(res) => Ok(res.map(boxed)),
|
||||
Ok(res) => Ok(res.into_response()),
|
||||
Err(err) => Ok(f(err).await.into_response()),
|
||||
}
|
||||
});
|
||||
|
@ -154,10 +152,11 @@ where
|
|||
#[allow(unused_macros)]
|
||||
macro_rules! impl_service {
|
||||
( $($ty:ident),* $(,)? ) => {
|
||||
impl<S, F, ReqBody, ResBody, Res, Fut, $($ty,)*> Service<Request<ReqBody>>
|
||||
impl<S, F, ReqBody, Res, Fut, $($ty,)*> Service<Request<ReqBody>>
|
||||
for HandleError<S, F, ($($ty,)*)>
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||
S: Service<Request<ReqBody>> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + Send,
|
||||
S::Error: Send,
|
||||
S::Future: Send,
|
||||
F: FnOnce($($ty),*, S::Error) -> Fut + Clone + Send + 'static,
|
||||
|
@ -165,8 +164,6 @@ macro_rules! impl_service {
|
|||
Res: IntoResponse,
|
||||
$( $ty: FromRequest<ReqBody> + Send,)*
|
||||
ReqBody: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
type Response = Response;
|
||||
type Error = Infallible;
|
||||
|
@ -202,7 +199,7 @@ macro_rules! impl_service {
|
|||
};
|
||||
|
||||
match inner.oneshot(req).await {
|
||||
Ok(res) => Ok(res.map(boxed)),
|
||||
Ok(res) => Ok(res.into_response()),
|
||||
Err(err) => Ok(f($($ty),*, err).await.into_response().map(boxed)),
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use crate::{
|
||||
body::{Bytes, HttpBody},
|
||||
extract::{FromRequest, RequestParts},
|
||||
response::{IntoResponse, Response},
|
||||
BoxError,
|
||||
};
|
||||
use futures_util::{future::BoxFuture, ready};
|
||||
use http::Request;
|
||||
|
@ -90,6 +88,8 @@ use tower_service::Service;
|
|||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
///
|
||||
/// [`Bytes`]: bytes::Bytes
|
||||
pub fn from_extractor<E>() -> FromExtractorLayer<E> {
|
||||
FromExtractorLayer(PhantomData)
|
||||
}
|
||||
|
@ -166,13 +166,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, E, ReqBody, ResBody> Service<Request<ReqBody>> for FromExtractor<S, E>
|
||||
impl<S, E, ReqBody> Service<Request<ReqBody>> for FromExtractor<S, E>
|
||||
where
|
||||
E: FromRequest<ReqBody> + 'static,
|
||||
ReqBody: Default + Send + 'static,
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
S: Service<Request<ReqBody>> + Clone,
|
||||
S::Response: IntoResponse,
|
||||
{
|
||||
type Response = Response;
|
||||
type Error = S::Error;
|
||||
|
@ -225,13 +224,12 @@ pin_project! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<ReqBody, S, E, ResBody> Future for ResponseFuture<ReqBody, S, E>
|
||||
impl<ReqBody, S, E> Future for ResponseFuture<ReqBody, S, E>
|
||||
where
|
||||
E: FromRequest<ReqBody>,
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>>,
|
||||
S: Service<Request<ReqBody>>,
|
||||
S::Response: IntoResponse,
|
||||
ReqBody: Default,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
type Output = Result<Response, S::Error>;
|
||||
|
||||
|
@ -259,7 +257,7 @@ where
|
|||
StateProj::Call { future } => {
|
||||
return future
|
||||
.poll(cx)
|
||||
.map(|result| result.map(|response| response.map(crate::body::boxed)));
|
||||
.map(|result| result.map(IntoResponse::into_response));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use crate::{
|
||||
body::{self, Bytes, HttpBody},
|
||||
response::{IntoResponse, Response},
|
||||
BoxError,
|
||||
};
|
||||
use crate::response::{IntoResponse, Response};
|
||||
use axum_core::extract::{FromRequest, RequestParts};
|
||||
use futures_util::future::BoxFuture;
|
||||
use http::Request;
|
||||
|
@ -16,7 +12,6 @@ use std::{
|
|||
task::{Context, Poll},
|
||||
};
|
||||
use tower::{util::BoxCloneService, ServiceBuilder};
|
||||
use tower_http::ServiceBuilderExt;
|
||||
use tower_layer::Layer;
|
||||
use tower_service::Service;
|
||||
|
||||
|
@ -256,20 +251,19 @@ where
|
|||
macro_rules! impl_service {
|
||||
( $($ty:ident),* $(,)? ) => {
|
||||
#[allow(non_snake_case)]
|
||||
impl<F, Fut, Out, S, ReqBody, ResBody, $($ty,)*> Service<Request<ReqBody>> for FromFn<F, S, ($($ty,)*)>
|
||||
impl<F, Fut, Out, S, ReqBody, $($ty,)*> Service<Request<ReqBody>> for FromFn<F, S, ($($ty,)*)>
|
||||
where
|
||||
F: FnMut($($ty),*, Next<ReqBody>) -> Fut + Clone + Send + 'static,
|
||||
$( $ty: FromRequest<ReqBody> + Send, )*
|
||||
Fut: Future<Output = Out> + Send + 'static,
|
||||
Out: IntoResponse + 'static,
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>, Error = Infallible>
|
||||
S: Service<Request<ReqBody>, Error = Infallible>
|
||||
+ Clone
|
||||
+ Send
|
||||
+ 'static,
|
||||
S::Response: IntoResponse,
|
||||
S::Future: Send + 'static,
|
||||
ReqBody: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
type Response = Response;
|
||||
type Error = Infallible;
|
||||
|
@ -296,7 +290,7 @@ macro_rules! impl_service {
|
|||
|
||||
let inner = ServiceBuilder::new()
|
||||
.boxed_clone()
|
||||
.map_response_body(body::boxed)
|
||||
.map_response(IntoResponse::into_response)
|
||||
.service(ready_inner);
|
||||
let next = Next { inner };
|
||||
|
||||
|
@ -370,7 +364,7 @@ impl fmt::Debug for ResponseFuture {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{body::Empty, routing::get, Router};
|
||||
use crate::{body::Body, routing::get, Router};
|
||||
use http::{HeaderMap, StatusCode};
|
||||
use tower::ServiceExt;
|
||||
|
||||
|
@ -392,12 +386,7 @@ mod tests {
|
|||
.layer(from_fn(insert_header));
|
||||
|
||||
let res = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.uri("/")
|
||||
.body(body::boxed(Empty::new()))
|
||||
.unwrap(),
|
||||
)
|
||||
.oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
|
|
|
@ -7,7 +7,6 @@ use crate::{
|
|||
http::{Method, Request, StatusCode},
|
||||
response::Response,
|
||||
routing::{future::RouteFuture, Fallback, MethodFilter, Route},
|
||||
BoxError,
|
||||
};
|
||||
use axum_core::response::IntoResponse;
|
||||
use bytes::BytesMut;
|
||||
|
@ -17,7 +16,7 @@ use std::{
|
|||
marker::PhantomData,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use tower::{service_fn, util::MapResponseLayer, ServiceBuilder, ServiceExt};
|
||||
use tower::{service_fn, util::MapResponseLayer, ServiceBuilder};
|
||||
use tower_layer::Layer;
|
||||
use tower_service::Service;
|
||||
|
||||
|
@ -76,12 +75,11 @@ macro_rules! top_level_service_fn {
|
|||
$name:ident, $method:ident
|
||||
) => {
|
||||
$(#[$m])+
|
||||
pub fn $name<S, ReqBody, ResBody>(svc: S) -> MethodRouter<ReqBody, S::Error>
|
||||
pub fn $name<S, ReqBody>(svc: S) -> MethodRouter<ReqBody, S::Error>
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||
S: Service<Request<ReqBody>> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + 'static,
|
||||
S::Future: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
on_service(MethodFilter::$method, svc)
|
||||
}
|
||||
|
@ -208,15 +206,14 @@ macro_rules! chained_service_fn {
|
|||
$name:ident, $method:ident
|
||||
) => {
|
||||
$(#[$m])+
|
||||
pub fn $name<S, ResBody>(self, svc: S) -> Self
|
||||
pub fn $name<S>(self, svc: S) -> Self
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>, Error = E>
|
||||
S: Service<Request<ReqBody>, Error = E>
|
||||
+ Clone
|
||||
+ Send
|
||||
+ 'static,
|
||||
S::Response: IntoResponse + 'static,
|
||||
S::Future: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
self.on_service(MethodFilter::$method, svc)
|
||||
}
|
||||
|
@ -316,15 +313,11 @@ top_level_service_fn!(trace_service, TRACE);
|
|||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
pub fn on_service<S, ReqBody, ResBody>(
|
||||
filter: MethodFilter,
|
||||
svc: S,
|
||||
) -> MethodRouter<ReqBody, S::Error>
|
||||
pub fn on_service<S, ReqBody>(filter: MethodFilter, svc: S) -> MethodRouter<ReqBody, S::Error>
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||
S: Service<Request<ReqBody>> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + 'static,
|
||||
S::Future: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
MethodRouter::new().on_service(filter, svc)
|
||||
}
|
||||
|
@ -382,12 +375,11 @@ where
|
|||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
pub fn any_service<S, ReqBody, ResBody>(svc: S) -> MethodRouter<ReqBody, S::Error>
|
||||
pub fn any_service<S, ReqBody>(svc: S) -> MethodRouter<ReqBody, S::Error>
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
|
||||
S: Service<Request<ReqBody>> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + 'static,
|
||||
S::Future: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
MethodRouter::new().fallback(svc).skip_allow_header()
|
||||
}
|
||||
|
@ -684,17 +676,13 @@ impl<ReqBody, E> MethodRouter<ReqBody, E> {
|
|||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
pub fn on_service<S, ResBody>(self, filter: MethodFilter, svc: S) -> Self
|
||||
pub fn on_service<S>(self, filter: MethodFilter, svc: S) -> Self
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>, Error = E>
|
||||
+ Clone
|
||||
+ Send
|
||||
+ 'static,
|
||||
S: Service<Request<ReqBody>, Error = E> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + 'static,
|
||||
S::Future: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
self.on_service_boxed_response_body(filter, svc.map_response(|res| res.map(boxed)))
|
||||
self.on_service_boxed_response_body(filter, svc)
|
||||
}
|
||||
|
||||
chained_service_fn!(delete_service, DELETE);
|
||||
|
@ -707,23 +695,20 @@ impl<ReqBody, E> MethodRouter<ReqBody, E> {
|
|||
chained_service_fn!(trace_service, TRACE);
|
||||
|
||||
#[doc = include_str!("../docs/method_routing/fallback.md")]
|
||||
pub fn fallback<S, ResBody>(mut self, svc: S) -> Self
|
||||
pub fn fallback<S>(mut self, svc: S) -> Self
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>, Error = E>
|
||||
+ Clone
|
||||
+ Send
|
||||
+ 'static,
|
||||
S: Service<Request<ReqBody>, Error = E> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + 'static,
|
||||
S::Future: Send + 'static,
|
||||
ResBody: HttpBody<Data = Bytes> + Send + 'static,
|
||||
ResBody::Error: Into<BoxError>,
|
||||
{
|
||||
self.fallback = Fallback::Custom(Route::new(svc.map_response(|res| res.map(boxed))));
|
||||
self.fallback = Fallback::Custom(Route::new(svc));
|
||||
self
|
||||
}
|
||||
|
||||
fn fallback_boxed_response_body<S>(mut self, svc: S) -> Self
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response, Error = E> + Clone + Send + 'static,
|
||||
S: Service<Request<ReqBody>, Error = E> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + 'static,
|
||||
S::Future: Send + 'static,
|
||||
{
|
||||
self.fallback = Fallback::Custom(Route::new(svc));
|
||||
|
@ -886,9 +871,10 @@ impl<ReqBody, E> MethodRouter<ReqBody, E> {
|
|||
pub fn handle_error<F, T>(self, f: F) -> MethodRouter<ReqBody, Infallible>
|
||||
where
|
||||
F: Clone + Send + 'static,
|
||||
HandleError<Route<ReqBody, E>, F, T>:
|
||||
Service<Request<ReqBody>, Response = Response, Error = Infallible>,
|
||||
HandleError<Route<ReqBody, E>, F, T>: Service<Request<ReqBody>, Error = Infallible>,
|
||||
<HandleError<Route<ReqBody, E>, F, T> as Service<Request<ReqBody>>>::Future: Send,
|
||||
<HandleError<Route<ReqBody, E>, F, T> as Service<Request<ReqBody>>>::Response:
|
||||
IntoResponse + Send,
|
||||
T: 'static,
|
||||
E: 'static,
|
||||
ReqBody: 'static,
|
||||
|
@ -898,7 +884,8 @@ impl<ReqBody, E> MethodRouter<ReqBody, E> {
|
|||
|
||||
fn on_service_boxed_response_body<S>(self, filter: MethodFilter, svc: S) -> Self
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response, Error = E> + Clone + Send + 'static,
|
||||
S: Service<Request<ReqBody>, Error = E> + Clone + Send + 'static,
|
||||
S::Response: IntoResponse + 'static,
|
||||
S::Future: Send + 'static,
|
||||
{
|
||||
macro_rules! set_service {
|
||||
|
@ -1319,14 +1306,22 @@ mod tests {
|
|||
|
||||
async fn call<S>(method: Method, svc: &mut S) -> (StatusCode, HeaderMap, String)
|
||||
where
|
||||
S: Service<Request<Body>, Response = Response, Error = Infallible>,
|
||||
S: Service<Request<Body>, Error = Infallible>,
|
||||
S::Response: IntoResponse,
|
||||
{
|
||||
let request = Request::builder()
|
||||
.uri("/")
|
||||
.method(method)
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
let response = svc.ready().await.unwrap().call(request).await.unwrap();
|
||||
let response = svc
|
||||
.ready()
|
||||
.await
|
||||
.unwrap()
|
||||
.call(request)
|
||||
.await
|
||||
.unwrap()
|
||||
.into_response();
|
||||
let (parts, body) = response.into_parts();
|
||||
let body = String::from_utf8(hyper::body::to_bytes(body).await.unwrap().to_vec()).unwrap();
|
||||
(parts.status, parts.headers, body)
|
||||
|
|
|
@ -122,7 +122,8 @@ where
|
|||
#[doc = include_str!("../docs/routing/route.md")]
|
||||
pub fn route<T>(mut self, path: &str, service: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = Infallible> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse,
|
||||
T::Future: Send + 'static,
|
||||
{
|
||||
if path.is_empty() {
|
||||
|
@ -176,7 +177,8 @@ where
|
|||
#[doc = include_str!("../docs/routing/nest.md")]
|
||||
pub fn nest<T>(mut self, mut path: &str, svc: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = Infallible> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse,
|
||||
T::Future: Send + 'static,
|
||||
{
|
||||
if path.is_empty() {
|
||||
|
@ -368,7 +370,8 @@ where
|
|||
#[doc = include_str!("../docs/routing/fallback.md")]
|
||||
pub fn fallback<T>(mut self, svc: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = Infallible> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse,
|
||||
T::Future: Send + 'static,
|
||||
{
|
||||
self.fallback = Fallback::Custom(Route::new(svc));
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::{
|
|||
body::{boxed, Body, Empty, HttpBody},
|
||||
response::Response,
|
||||
};
|
||||
use axum_core::response::IntoResponse;
|
||||
use bytes::Bytes;
|
||||
use http::{
|
||||
header::{self, CONTENT_LENGTH},
|
||||
|
@ -30,10 +31,13 @@ pub struct Route<B = Body, E = Infallible>(BoxCloneService<Request<B>, Response,
|
|||
impl<B, E> Route<B, E> {
|
||||
pub(super) fn new<T>(svc: T) -> Self
|
||||
where
|
||||
T: Service<Request<B>, Response = Response, Error = E> + Clone + Send + 'static,
|
||||
T: Service<Request<B>, Error = E> + Clone + Send + 'static,
|
||||
T::Response: IntoResponse + 'static,
|
||||
T::Future: Send + 'static,
|
||||
{
|
||||
Self(BoxCloneService::new(svc))
|
||||
Self(BoxCloneService::new(
|
||||
svc.map_response(IntoResponse::into_response),
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn oneshot_inner(
|
||||
|
|
Loading…
Add table
Reference in a new issue