mirror of
https://github.com/tokio-rs/axum.git
synced 2025-03-13 19:27:53 +01:00
Fix for service as bottom handler (#27)
Would previously fail because of a mismatch in error types.
This commit is contained in:
parent
c4d266e94d
commit
3cd4a1d6a6
5 changed files with 60 additions and 26 deletions
|
@ -206,7 +206,7 @@ where
|
|||
OnMethod {
|
||||
method,
|
||||
svc: handler.into_service(),
|
||||
fallback: EmptyRouter,
|
||||
fallback: EmptyRouter::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -679,13 +679,13 @@ pub mod prelude {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if `description` doesn't start with `/`.
|
||||
pub fn route<S, B>(description: &str, service: S) -> Route<S, EmptyRouter>
|
||||
pub fn route<S, B>(description: &str, service: S) -> Route<S, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
use routing::RoutingDsl;
|
||||
|
||||
routing::EmptyRouter.route(description, service)
|
||||
routing::EmptyRouter::new().route(description, service)
|
||||
}
|
||||
|
||||
mod sealed {
|
||||
|
|
|
@ -12,6 +12,7 @@ use std::{
|
|||
convert::Infallible,
|
||||
fmt,
|
||||
future::Future,
|
||||
marker::PhantomData,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
|
@ -362,17 +363,36 @@ fn insert_url_params<B>(req: &mut Request<B>, params: Vec<(String, String)>) {
|
|||
///
|
||||
/// This is used as the bottom service in a router stack. You shouldn't have to
|
||||
/// use to manually.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct EmptyRouter;
|
||||
pub struct EmptyRouter<E = Infallible>(PhantomData<fn() -> E>);
|
||||
|
||||
impl RoutingDsl for EmptyRouter {}
|
||||
impl<E> EmptyRouter<E> {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::sealed::Sealed for EmptyRouter {}
|
||||
impl<E> Clone for EmptyRouter<E> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> Service<Request<B>> for EmptyRouter {
|
||||
impl<E> Copy for EmptyRouter<E> {}
|
||||
|
||||
impl<E> fmt::Debug for EmptyRouter<E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("EmptyRouter").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> RoutingDsl for EmptyRouter<E> {}
|
||||
|
||||
impl<E> crate::sealed::Sealed for EmptyRouter<E> {}
|
||||
|
||||
impl<B, E> Service<Request<B>> for EmptyRouter<E> {
|
||||
type Response = Response<BoxBody>;
|
||||
type Error = Infallible;
|
||||
type Future = EmptyRouterFuture;
|
||||
type Error = E;
|
||||
type Future = EmptyRouterFuture<E>;
|
||||
|
||||
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
|
@ -387,8 +407,8 @@ impl<B> Service<Request<B>> for EmptyRouter {
|
|||
|
||||
opaque_future! {
|
||||
/// Response future for [`EmptyRouter`].
|
||||
pub type EmptyRouterFuture =
|
||||
future::Ready<Result<Response<BoxBody>, Infallible>>;
|
||||
pub type EmptyRouterFuture<E> =
|
||||
future::Ready<Result<Response<BoxBody>, E>>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -744,14 +764,14 @@ where
|
|||
/// If necessary you can use [`RoutingDsl::boxed`] to box a group of routes
|
||||
/// making the type easier to name. This is sometimes useful when working with
|
||||
/// `nest`.
|
||||
pub fn nest<S, B>(description: &str, svc: S) -> Nested<S, EmptyRouter>
|
||||
pub fn nest<S, B>(description: &str, svc: S) -> Nested<S, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
Nested {
|
||||
pattern: PathPattern::new(description),
|
||||
svc,
|
||||
fallback: EmptyRouter,
|
||||
fallback: EmptyRouter::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ pub mod future;
|
|||
/// Route requests to the given service regardless of the HTTP method.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn any<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn any<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -119,7 +119,7 @@ where
|
|||
/// Route `CONNECT` requests to the given service.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn connect<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn connect<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -129,7 +129,7 @@ where
|
|||
/// Route `DELETE` requests to the given service.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn delete<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn delete<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -156,7 +156,7 @@ where
|
|||
/// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
pub fn get<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn get<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -166,7 +166,7 @@ where
|
|||
/// Route `HEAD` requests to the given service.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn head<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn head<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -176,7 +176,7 @@ where
|
|||
/// Route `OPTIONS` requests to the given service.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn options<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn options<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -186,7 +186,7 @@ where
|
|||
/// Route `PATCH` requests to the given service.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn patch<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn patch<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -196,7 +196,7 @@ where
|
|||
/// Route `POST` requests to the given service.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn post<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn post<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -206,7 +206,7 @@ where
|
|||
/// Route `PUT` requests to the given service.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn put<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn put<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -216,7 +216,7 @@ where
|
|||
/// Route `TRACE` requests to the given service.
|
||||
///
|
||||
/// See [`get`] for an example.
|
||||
pub fn trace<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn trace<S, B>(svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -243,7 +243,10 @@ where
|
|||
/// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
pub fn on<S, B>(method: MethodFilter, svc: S) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter>
|
||||
pub fn on<S, B>(
|
||||
method: MethodFilter,
|
||||
svc: S,
|
||||
) -> OnMethod<BoxResponseBody<S, B>, EmptyRouter<S::Error>>
|
||||
where
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
|
@ -253,7 +256,7 @@ where
|
|||
inner: svc,
|
||||
_request_body: PhantomData,
|
||||
},
|
||||
fallback: EmptyRouter,
|
||||
fallback: EmptyRouter::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
11
src/tests.rs
11
src/tests.rs
|
@ -653,6 +653,17 @@ async fn different_request_body_types() {
|
|||
assert_eq!(body, "foo");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn service_in_bottom() {
|
||||
async fn handler(_req: Request<hyper::Body>) -> Result<Response<hyper::Body>, hyper::Error> {
|
||||
Ok(Response::new(hyper::Body::empty()))
|
||||
}
|
||||
|
||||
let app = route("/", service::get(service_fn(handler)));
|
||||
|
||||
run_in_background(app).await;
|
||||
}
|
||||
|
||||
/// Run a `tower::Service` in the background and get a URI for it.
|
||||
async fn run_in_background<S, ResBody>(svc: S) -> SocketAddr
|
||||
where
|
||||
|
|
Loading…
Add table
Reference in a new issue