tower-rs / tower

async fn(Request) -> Result<Response, Error>
https://docs.rs/tower
MIT License
3.46k stars 274 forks source link

How to set tower middleware dynamically #774

Open tgy3300 opened 2 months ago

tgy3300 commented 2 months ago
use demo_server::{api::demo_server::DemoServer, MyGreeter};
use http::{Request, Response};
use std::{convert::Infallible, time::Duration};
use tonic::{body::BoxBody, server::NamedService, service::Routes, transport::Server};
use tower::Service;
use tower_http::{cors::CorsLayer, timeout::TimeoutLayer, trace::TraceLayer};
use tower_layer::Layer;

#[tokio::main]
async fn main() {
    let trace_layer = TraceLayer::new_for_grpc();
    let cors_layer = CorsLayer::new();
    let time_layer = TimeoutLayer::new(Duration::from_secs(5));

    let layer = tower::ServiceBuilder::new()
        .layer(trace_layer)
        .layer(cors_layer)
        .layer(time_layer)
        .into_inner();

    run(layer).await;
}

async fn run<L>(layer: L)
where
    L: Layer<Routes> + Clone + Send + Sync + 'static,
    L::Service: Service<Request<BoxBody>, Response = Response<BoxBody>, Error = Infallible>
        + NamedService
        + Clone
        + Send
        + Sync
        + 'static,
    <L::Service as Service<Request<BoxBody>>>::Future: Send + Sync + 'static,
{
    let addr = "[::1]:50051".parse().unwrap();
    println!("grpc listening on {}", addr);

    let greeter = MyGreeter::default();
    let svc = DemoServer::new(greeter);

    Server::builder()
        .layer(layer)
        .add_service(svc)
        .serve(addr)
        .await
        .unwrap();
}

Report an error:

error[E0271]: type mismatch resolving `<Trace<Cors<Timeout<Routes>>, SharedClassifier<GrpcErrorsAsFailures>> as Service<Request<UnsyncBoxBody<Bytes, Status>>>>::Response == Response<UnsyncBoxBody<Bytes, Status>>`
  --> demo_server\src/main.rs:21:5
   |
21 |     run(layer).await;
   |     ^^^^^^^^^^ expected `Response<UnsyncBoxBody<Bytes, ...>>`, found `Response<ResponseBody<..., ...>>`
   |
   = note: expected struct `http::Response<http_body_util::combinators::box_body::UnsyncBoxBody<_, _>>`
              found struct `http::Response<tower_http::trace::ResponseBody<http_body_util::combinators::box_body::UnsyncBoxBody<_, _>, GrpcEosErrorsAsFailures>>`
note: required by a bound in `run`
  --> demo_server\src/main.rs:27:43
   |
24 | async fn run<L>(layer: L)
   |          --- required by a bound in this function
...
27 |     L::Service: Service<Request<BoxBody>, Response = Response<BoxBody>, Error = Infallible>
   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `run`
monadbobo commented 5 days ago

i have the same problem