hyperium / tonic

A native gRPC client & server implementation with async/await support.
https://docs.rs/tonic
MIT License
9.76k stars 997 forks source link

URI path is not respected in Endpoint #1314

Open j-chmielewski opened 1 year ago

j-chmielewski commented 1 year ago

Bug Report

Version

tonic v0.8.3 tonic-build v0.8.4

Platform

Linux blade 6.2.2-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 03 Mar 2023 15:58:31 +0000 x86_64 GNU/Linux

Description

Tonic client does not respect endpoint path.

Trying to proxy my grpc service via nginx, I have the following nginx configuration:

http {
    server {
        listen 50050 http2;
        server_name main;

    location /grpc {
        grpc_pass grpc://core:50055;
        }
    }
}

And the client builds the endopoint like so:

let endpoint = Endpoint::from_static("http://localhost:50050/grpc");

I expected the request to go to /grpc path but it does not. Nginx logs show that POST requests go to / instead of /grpc. I also verified that changing nginx configuration to location / does work even though the client-side endpoint still indicates the /grpc path.

LucioFranco commented 1 year ago

Yeah, that seems like a bug here https://github.com/hyperium/tonic/blob/master/tonic/src/client/grpc.rs#L380 and maybe also on the server side. I would accept a PR that fixed this.

democ98 commented 10 months ago

I also encountered the same problem, I don't know whether it is a server or client problem. Can someone explain it in detail? thanks

steebchen commented 2 months ago

Looks like this part is the issue:

https://github.com/hyperium/tonic/blob/e2c506aca5810ceeb6d41190779b7291fcf19d90/tonic/src/client/grpc.rs#L51

So if your Channel has a fully qualified URL including a path, it still defaults to /. Users could use the with_origin method, but then you'd have to define it twice which wouldn't make much sense I think.

I'd love to send a PR for this, but I'm just learning Rust; any guidance is appreciated.

Is there any way to get the URL/path from inner? I couldn't figure that out.

// in grpc.rs
pub fn new(inner: T) -> Self {
  Self::with_origin(inner, inner.get_url_somehow()) // ?
}