Remove buffer from BoxRoute (#270)

Boxing a service normally means using `tower::util::BoxService`. That
doesn't implement `Clone` however so normally I had been combining it
with `Buffer` to get that.

But recently I discovered https://github.com/dtolnay/dyn-clone which
makes it possible to clone trait objects. So this adds a new internal
utility called `CloneBoxService` which replaces the previous
`BoxService` + `Buffer` combo in `BoxRoute`.

I'll investigate upstreaming that to tower. I think it makes sense there
since box + clone is quite a common need.
This commit is contained in:
David Pedersen
2021-08-26 06:34:53 +00:00
committed by GitHub
parent 20f6c3b509
commit 552d69e5d4
7 changed files with 96 additions and 219 deletions
+12 -15
View File
@@ -3,13 +3,12 @@
use self::future::{BoxRouteFuture, EmptyRouterFuture, NestedFuture, RouteFuture};
use crate::{
body::{box_body, BoxBody},
buffer::MpscBuffer,
extract::{
connect_info::{Connected, IntoMakeServiceWithConnectInfo},
OriginalUri,
},
service::HandleError,
util::ByteStr,
util::{ByteStr, CloneBoxService},
BoxError,
};
use bytes::Bytes;
@@ -24,10 +23,7 @@ use std::{
sync::Arc,
task::{Context, Poll},
};
use tower::{
util::{BoxService, ServiceExt},
ServiceBuilder,
};
use tower::{util::ServiceExt, ServiceBuilder};
use tower_http::map_response_body::MapResponseBodyLayer;
use tower_layer::Layer;
use tower_service::Service;
@@ -256,7 +252,7 @@ impl<S> Router<S> {
/// routes.
pub fn boxed<ReqBody, ResBody>(self) -> Router<BoxRoute<ReqBody, S::Error>>
where
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Send + 'static,
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone + Send + 'static,
S::Error: Into<BoxError> + Send,
S::Future: Send,
ReqBody: Send + 'static,
@@ -265,9 +261,8 @@ impl<S> Router<S> {
{
self.map(|svc| {
ServiceBuilder::new()
.layer_fn(BoxRoute)
.layer_fn(MpscBuffer::new)
.layer(BoxService::layer())
.layer_fn(|inner| BoxRoute { inner })
.layer_fn(CloneBoxService::new)
.layer(MapResponseBodyLayer::new(box_body))
.service(svc)
})
@@ -833,13 +828,15 @@ type Captures = Vec<(String, String)>;
/// A boxed route trait object.
///
/// See [`Router::boxed`] for more details.
pub struct BoxRoute<B = crate::body::Body, E = Infallible>(
MpscBuffer<BoxService<Request<B>, Response<BoxBody>, E>, Request<B>>,
);
pub struct BoxRoute<B = crate::body::Body, E = Infallible> {
inner: CloneBoxService<Request<B>, Response<BoxBody>, E>,
}
impl<B, E> Clone for BoxRoute<B, E> {
fn clone(&self) -> Self {
Self(self.0.clone())
BoxRoute {
inner: self.inner.clone(),
}
}
}
@@ -865,7 +862,7 @@ where
#[inline]
fn call(&mut self, req: Request<B>) -> Self::Future {
BoxRouteFuture {
inner: self.0.clone().oneshot(req),
inner: self.inner.clone().oneshot(req),
}
}
}