Parameter passing issues in the tonic encapsulation middleware
- 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
Assessment
This issue has not been assessed yet.