Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gRPC-web CORS issue #1678

Open
Emulator000 opened this issue Apr 9, 2024 · 0 comments
Open

gRPC-web CORS issue #1678

Emulator000 opened this issue Apr 9, 2024 · 0 comments

Comments

@Emulator000
Copy link

Emulator000 commented Apr 9, 2024

Bug Report

Version

❯ cargo tree | grep tonic
│   │   │   │   └── tonic v0.11.0
│   │   │   └── tonic v0.11.0 (*)
│   │   │   ├── tonic v0.11.0 (*)
│   │   │   └── tonic-reflection v0.11.0
│   │   │       └── tonic v0.11.0 (*)
│   │   │   └── tonic-build v0.11.0
│   ├── tonic v0.11.0 (*)
├── tonic v0.11.0 (*)
├── tonic-web v0.11.0
│   ├── tonic v0.11.0 (*)

Platform

Linux

Crates

tonic-web

Description

I'm trying to use gRPC-web example provided here but I'm getting a CORS error into the browser during the API call:
image

I resolved in the past this problem with this modified example configuration:

use tonic::{transport::Server, Request, Response, Status};

use hello_world::greeter_server::{Greeter, GreeterServer};
use hello_world::{HelloReply, HelloRequest};
use once_cell::sync::Lazy;

const DEFAULT_MAX_AGE: Duration = Duration::from_secs(24 * 60 * 60);
const DEFAULT_EXPOSED_HEADERS: [HeaderName; 3] = [
    HeaderName::from_static("grpc-status"),
    HeaderName::from_static("grpc-message"),
    HeaderName::from_static("grpc-status-details-bin"),
];

static GRPC_WEB_CORS: Lazy<CorsLayer> = Lazy::new(|| {
    CorsLayer::new()
        .allow_origin(AllowOrigin::mirror_request())
        .allow_headers(AllowHeaders::mirror_request())
        .allow_methods(AllowMethods::mirror_request())
        .allow_credentials(true)
        .max_age(DEFAULT_MAX_AGE)
        .expose_headers(ExposeHeaders::from(DEFAULT_EXPOSED_HEADERS))
});

pub mod hello_world {
    tonic::include_proto!("helloworld");
}

#[derive(Default)]
pub struct MyGreeter {}

#[tonic::async_trait]
impl Greeter for MyGreeter {
    async fn say_hello(
        &self,
        request: Request<HelloRequest>,
    ) -> Result<Response<HelloReply>, Status> {
        println!("Got a request from {:?}", request.remote_addr());

        let reply = hello_world::HelloReply {
            message: format!("Hello {}!", request.into_inner().name),
        };
        Ok(Response::new(reply))
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    tracing_subscriber::fmt::init();

    let addr = "127.0.0.1:3000".parse().unwrap();

    let greeter = MyGreeter::default();
    let greeter = GreeterServer::new(greeter);

    println!("GreeterServer listening on {}", addr);

    Server::builder()
        // GrpcWeb is over http1 so we must enable it.
        .accept_http1(true)
        .layer(GrpcWebLayer::new())
        .layer(GRPC_WEB_CORS)
        .add_service(tonic_web::enable(greeter))
        .serve(addr)
        .await?;

    Ok(())
}

but within the new version I'm getting this compiler error:

    |
104 |         .serve(
    |          ^^^^^ the trait `Service<http::request::Request<tonic::transport::Body>>` is not implemented for `Cors<Routes>`, which is required by `Stack<GrpcWebLayer, tower::layer::util::Identity>: Layer<Cors<Routes>>`
    |
    = help: the trait `Service<http::Request<ReqBody>>` is implemented for `Cors<S>`
    = note: required for `GrpcWebLayer` to implement `Layer<Cors<Routes>>`
    = note: 1 redundant requirement hidden
    = note: required for `Stack<GrpcWebLayer, tower::layer::util::Identity>` to implement `Layer<Cors<Routes>>`

so I can't use it anymore and I've to relay entirely into the tonic_web::enable feature that is designed for the gRPC-web CORS problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant