I implemented a middleware layer for my GRPC server in Rust like this:
use std::{
pin::Pin,
task::{Context, Poll},
};
use tonic::transport::Body;
use tonic::{body::BoxBody, Request};
use tower_layer::Layer;
use tower_service::Service;
#[derive(Debug, Clone, Default)]
pub struct MiddlewareLayer;
impl<S> Layer<S> for MiddlewareLayer {
type Service = Middleware<S>;
fn layer(&self, service: S) -> Self::Service {
Middleware { service }
}
}
#[derive(Debug, Clone)]
pub struct Middleware<S> {
service: S,
}
type BoxFuture<'a, T> = Pin<Box<dyn std::future::Future<Output = T> + Send + 'a>>;
impl<S> Service<Request<Body>> for Middleware<S>
where
S: Service<Request<Body>, Response = tonic::Response<BoxBody>> + Clone + Send + 'static,
S::Future: Send + 'static,
{
type Response = S::Response;
type Error = S::Error;
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}
fn call(&mut self, req: Request<Body>) -> Self::Future {
println!("Request body: {:?}", req);
//self.service.call(req)
let clone = self.service.clone();
let mut service = std::mem::replace(&mut self.service, clone);
Box::pin(async move {
println!("Before");
let response = service.call(req).await?;
println!("After");
Ok(response)
})
}
}
I then add this middleware to my server:
let layer = tower::ServiceBuilder::new()
.layer(MiddlewareLayer::default())
.into_inner();
Server::builder()
.layer(layer)
.add_service(PermissionServiceServer::new(permission_service))
.add_service(reflection)
.serve(server_address)
.await?;
However, when I try to run my program I get this error message, which is driving my crazy by now, because I have no idea how to solve it:
error[E0277]: the trait bound `Middleware<Routes>: Service<request::Request<tonic::transport::Body>>` is not satisfied
--> src/main.rs:96:10
|
96 | .serve(server_address)
| ^^^^^ the trait `Service<request::Request<tonic::transport::Body>>` is not implemented for `Middleware<Routes>`
|
= help: the trait `Service<tonic::Request<tonic::transport::Body>>` is implemented for `Middleware<S>`