grpc / grpc/grpc-rust

Parameter passing issues in the tonic encapsulation middleware

Open
#2,292 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
12.5k
Forks
1.3k
Avg merge
4d 7h
Merged PRs (30d)
24

Description

---------------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 {
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 {
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 {
address: String,
layer: Option,
service: S,
}
impl GrpcServer
where
L: Layer + Clone + Send + Sync + 'static,
L::Service: Service + Clone + Send + Sync + 'static,
>::Response: IntoResponse + 'static,
>::Error: Into + 'static,
>::Future: Send + 'static,
// ---
S: Service, 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` is not satisfied
--> src\transport\grpc\mod.rs:57:14
|
57 | .serve(address)
| ^^^^^ the trait `Layer` is not implemented for `L`
|
= note: required for `Stack` to implement `Layer`
```

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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.