hyperium / tonic

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

Get the server's port/local_addr #351

Closed mariogemoll closed 3 years ago

mariogemoll commented 4 years ago

Feature Request

Crates

tonic

Motivation

For testing purposes it would be good if there was a way to retrieve the port a server is listening on when it was started without a specified port (ie. with port 0).

Proposal

Add functionality to obtain the port/local_addr a server is listening on (similar to https://docs.rs/hyper/0.13.5/hyper/server/struct.Server.html#method.local_addr).

gabrielrussoc commented 4 years ago

This is also very useful when there are multiple servers on the same host, where it is usual to let the OS find a free port by specifying :0.

kinosang commented 4 years ago

https://github.com/hyperium/tonic/blob/f6ecaff0de76de16cb1f680dc3473c8cf2bbaddd/examples/src/autoreload/server.rs#L39-L41

It may helps.

let addr: SocketAddr = "0.0.0.0:0".parse()?;

let mut listener = tokio::net::TcpListener::bind(addr).await?;
mariogemoll commented 4 years ago

Great, that worked, thanks!

gabrielrussoc commented 4 years ago

Can we reopen this? Although there is a workaround, it would be great to support this out of the box.

davidpdrsn commented 3 years ago

I don't quite see how to add a more convenient way could be added. Once the server (Router) has been bound to an address or an "incoming" it is no longer accessible. All the methods that do this consume self.

Hyper's server gets around that by making the server itself a Future whereas tonic users async fns.

I'm personally fine with requiring users to create the TcpListener to get the address and passing it in with server_with_incoming.

LucioFranco commented 3 years ago

Yeah, I don't think its worth making things more complicated to support this feature. Going to close for now.

Raphiiko commented 1 year ago

Would it be possible to reopen this issue? I try to find a free port by setting :0 as the port, and I'm looking to find the port it picked.

The workaround in https://github.com/hyperium/tonic/issues/351#issuecomment-638346513 no longer seems to be an option, as incoming is no longer available on tokio::net::TcpListener in recent versions of tokio.

Edit: You can use this workaround instead:

let addr: SocketAddr = "127.0.0.1:0".parse()?;
let listener = match tokio::net::TcpListener::bind(addr).await?;
println!("Server listening on {}", listener.local_addr().unwrap());
let stream = tokio_stream::wrappers::TcpListenerStream::new(listener);
server.serve_with_incoming(stream).await?;