Parameter passing issues in the tonic encapsulation middleware

⚓ rust    📅 2025-06-03    👤 surdeus    👁️ 1      

surdeus

---------------Original code---------------------

use axum::{extract::Request, http::StatusCode, middleware::Next, response::Response};
use tonic::transport::Server as TServer;

async fn auth(req: Request, next: Next) -> Result<Response, StatusCode> {
    Ok(next.run(req).await)
}

struct GrpcLogic {}
impl GrpcLogic {
    fn new() -> Self {
        Self {}
    }
}
#[tonic::async_trait]
impl xxx for GrpcLogic {
    // ...Implement the service specified in the proto file
}

#[tokio::main]
async fn main() {
    let address = "[::1]:4000".to_string().parse().unwrap();

    // AccountServer # tonic_build is the server-side code generated based on the proto file
    let svc = AccountServer::new(GrpcLogic::new());

    let layer = tower::ServiceBuilder::new()
        .layer(axum::middleware::from_fn(auth))
        .into_inner();

    TServer::builder()
        .layer(layer)
        .add_service(svc)
        .serve(address)
        .await
        .unwrap();
}

---------------Encapsulation code---------------------

use axum::{extract::Request, http::StatusCode, middleware::Next, response::Response};
use axum::{response::IntoResponse, routing::Route};
use std::convert::Infallible;
use tonic::transport::Server as TServer;
use tonic::{body::Body, server::NamedService};
use tower_layer::Layer;
use tower_service::Service;

async fn auth(req: Request, next: Next) -> Result<Response, StatusCode> {
    Ok(next.run(req).await)
}

struct GrpcLogic {}
impl GrpcLogic {
    fn new() -> Self {
        Self {}
    }
}
#[tonic::async_trait]
impl xxx for GrpcLogic {
    // ...Implement the service specified in the proto file
}

#[tokio::main]
async fn main() {
    let layer = tower::ServiceBuilder::new()
        .layer(axum::middleware::from_fn(auth))
        .into_inner();

    GrpcServer::new(AccountServer::new(GrpcLogic::new()))
        .address("[::1]:4000")
        .layer(layer)
        .start()
        .await
}

struct GrpcServer<L, S> {
    address: String,
    layer: Option<L>,
    service: S,
}
impl<L, S> GrpcServer<L, S>
where
    L: Layer<Route> + Clone + Send + Sync + 'static,
    L::Service: Service<Request> + Clone + Send + Sync + 'static,
    <L::Service as Service<Request>>::Response: IntoResponse + 'static,
    <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
    <L::Service as Service<Request>>::Future: Send + 'static,
    // ---
    S: Service<Request<Body>, Error = Infallible> + NamedService + Clone + Send + Sync + 'static,
    S::Response: axum::response::IntoResponse,
    S::Future: Send + 'static,
{
    fn new(srv: S) -> Self {
        Self {
            address: "[::1]:4000".to_string(),
            layer: None,
            service: srv,
        }
    }

    fn address(mut self, a: &str) -> Self {
        self.address = a.to_string();
        self
    }

    fn layer(mut self, layer: L) -> Self {
        self.layer = Some(layer);
        self
    }

    async fn start(&self) -> Result<(), &str> {
        let address = self.address.parse().unwrap();

        let layer = self.layer.unwrap();

        // let layer = tower::ServiceBuilder::new()
        //     .layer(axum::middleware::from_fn(auth))
        //     .into_inner();

        TServer::builder()
            .layer(layer)
            .add_service(self.service.clone())
            .serve(address)
            .await
            .unwrap();

        Ok(())
    }
}

Problem description: In the encapsulated code, under the start method
Use let layer = self.layer.unwrap(); An error will be reported. The error code is as follows:


error[E0277]: the trait bound `L: Layer<Routes>` is not satisfied
  --> src\transport\grpc\mod.rs:57:14
   |
57 |             .serve(address)
   |              ^^^^^ the trait `Layer<Routes>` is not implemented for `L`
   |
   = note: required for `Stack<L, tower_layer::Identity>` to implement `Layer<Routes>`

Comment out let layer = self.layer.unwrap(); Use tower::ServiceBuilder instead.


        let layer = tower::ServiceBuilder::new()
            .layer(DemoLayer::new())
            .into_inner();

It's normal. This indicates that there is a problem with self.layer, but we still can't find a solution, so we come to seek help from everyone

1 post - 1 participant

Read full topic

🏷️ rust_feed