fix(examples): Fix tower examples (#624)

Doing

```rust
let clone = self.inner.clone();
Box::pin(async move {
    let response = clone.call(request).await?;
    Ok(response)
})
```

If `self.inner` is (or contains) a `tower::buffer::Buffer` might panic.

That is because cloning a `Buffer` drops the permit that was acquired in
`poll_ready`, meaning it is no longer ready and panic in `call`.

The solution is to use `mem::replace` to take the ready service and pass
that into the async block.

Fixes https://github.com/hyperium/tonic/issues/545
This commit is contained in:
David Pedersen
2021-05-07 09:45:35 +02:00
committed by GitHub
parent 4b26e78109
commit 4a917a32f0
2 changed files with 15 additions and 5 deletions
+7 -2
View File
@@ -56,12 +56,17 @@ mod service {
}
fn call(&mut self, req: Request<BoxBody>) -> Self::Future {
let mut channel = self.inner.clone();
// This is necessary because tonic internally uses `tower::buffer::Buffer`.
// See https://github.com/tower-rs/tower/issues/547#issuecomment-767629149
// for details on why this is necessary
let clone = self.inner.clone();
let mut inner = std::mem::replace(&mut self.inner, clone);
Box::pin(async move {
// Do extra async work here...
let response = inner.call(req).await?;
channel.call(req).await.map_err(Into::into)
Ok(response)
})
}
}
+8 -3
View File
@@ -71,12 +71,17 @@ where
}
fn call(&mut self, req: HyperRequest<Body>) -> Self::Future {
let mut svc = self.inner.clone();
// This is necessary because tonic internally uses `tower::buffer::Buffer`.
// See https://github.com/tower-rs/tower/issues/547#issuecomment-767629149
// for details on why this is necessary
let clone = self.inner.clone();
let mut inner = std::mem::replace(&mut self.inner, clone);
Box::pin(async move {
// Do async work here....
// Do extra async work here...
let response = inner.call(req).await?;
svc.call(req).await
Ok(response)
})
}
}