From a128a672a165b413a6e31da7d0f75b77505d8d9d Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Mon, 16 Aug 2021 09:19:37 +0200 Subject: [PATCH] Remove allocation when calling handler (#190) `Handler::call` already returns a boxed future so we don't have to box it again. --- src/handler/future.rs | 11 ++++++++--- src/handler/mod.rs | 12 ++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/handler/future.rs b/src/handler/future.rs index 3c78cb42..d921494c 100644 --- a/src/handler/future.rs +++ b/src/handler/future.rs @@ -1,7 +1,8 @@ //! Handler future types. use crate::body::{box_body, BoxBody}; -use futures_util::future::{BoxFuture, Either}; +use crate::util::{Either, EitherProj}; +use futures_util::{future::BoxFuture, ready}; use http::{Method, Request, Response}; use http_body::Empty; use pin_project_lite::pin_project; @@ -21,7 +22,7 @@ pin_project! { { #[pin] pub(super) inner: Either< - BoxFuture<'static, Result, F::Error>>, + BoxFuture<'static, Response>, Oneshot>, >, pub(super) req_method: Method, @@ -36,7 +37,11 @@ where fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); - let response = futures_util::ready!(this.inner.poll(cx))?; + 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)) diff --git a/src/handler/mod.rs b/src/handler/mod.rs index cda572da..b740453c 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -6,10 +6,10 @@ use crate::{ response::IntoResponse, routing::{EmptyRouter, MethodFilter}, service::{HandleError, HandleErrorFromRouter}, + util::Either, }; use async_trait::async_trait; use bytes::Bytes; -use futures_util::future::Either; use http::{Request, Response}; use std::{ convert::Infallible, @@ -601,15 +601,11 @@ where let req_method = req.method().clone(); let fut = if self.method.matches(req.method()) { - let handler = self.handler.clone(); - let fut = Box::pin(async move { - let res = Handler::call(handler, req).await; - Ok::<_, F::Error>(res) - }) as futures_util::future::BoxFuture<'static, _>; - Either::Left(fut) + let fut = Handler::call(self.handler.clone(), req); + Either::A { inner: fut } } else { let fut = self.fallback.clone().oneshot(req); - Either::Right(fut) + Either::B { inner: fut } }; future::OnMethodFuture {