//! Handler future types. use crate::body::{box_body, BoxBody}; use crate::util::{Either, EitherProj}; use futures_util::{ future::{BoxFuture, Map}, ready, }; use http::{Method, Request, Response}; use http_body::Empty; use pin_project_lite::pin_project; use std::{ convert::Infallible, fmt, future::Future, pin::Pin, task::{Context, Poll}, }; use tower::util::Oneshot; use tower_service::Service; pin_project! { /// The response future for [`OnMethod`](super::OnMethod). pub struct OnMethodFuture where F: Service> { #[pin] pub(super) inner: Either< BoxFuture<'static, Response>, Oneshot>, >, pub(super) req_method: Method, } } impl Future for OnMethodFuture where F: Service, Response = Response>, { type Output = Result, F::Error>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let response = match this.inner.project() { EitherProj::A { inner } => ready!(inner.poll(cx)), EitherProj::B { inner } => ready!(inner.poll(cx))?, }; if this.req_method == &Method::HEAD { let response = response.map(|_| box_body(Empty::new())); Poll::Ready(Ok(response)) } else { Poll::Ready(Ok(response)) } } } impl fmt::Debug for OnMethodFuture where F: Service>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OnMethodFuture").finish() } } opaque_future! { /// The response future for [`IntoService`](super::IntoService). pub type IntoServiceFuture = Map< BoxFuture<'static, Response>, fn(Response) -> Result, Infallible>, >; }