diff --git a/examples/src/autoreload/server.rs b/examples/src/autoreload/server.rs index a181f75ec..4fdef8c49 100644 --- a/examples/src/autoreload/server.rs +++ b/examples/src/autoreload/server.rs @@ -1,4 +1,7 @@ -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/cancellation/server.rs b/examples/src/cancellation/server.rs index 32d93e7d7..e0bb7574e 100644 --- a/examples/src/cancellation/server.rs +++ b/examples/src/cancellation/server.rs @@ -1,7 +1,10 @@ use std::future::Future; use tokio_util::sync::CancellationToken; -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/codec_buffers/server.rs b/examples/src/codec_buffers/server.rs index b30c797d3..e598d71b8 100644 --- a/examples/src/codec_buffers/server.rs +++ b/examples/src/codec_buffers/server.rs @@ -5,7 +5,10 @@ //! The generated code assumes that a module `crate::common` exists which defines //! `SmallBufferCodec`, and `SmallBufferCodec` must have a Default implementation. -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; pub mod common; diff --git a/examples/src/compression/server.rs b/examples/src/compression/server.rs index fd035d218..176833b97 100644 --- a/examples/src/compression/server.rs +++ b/examples/src/compression/server.rs @@ -1,4 +1,7 @@ -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/dynamic/server.rs b/examples/src/dynamic/server.rs index 14e0bee3e..c10d8a736 100644 --- a/examples/src/dynamic/server.rs +++ b/examples/src/dynamic/server.rs @@ -1,5 +1,9 @@ use std::env; -use tonic::{service::RoutesBuilder, transport::Server, Request, Response, Status}; +use tonic::{ + service::RoutesBuilder, + transport::{RequestExt, Server}, + Request, Response, Status, +}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/grpc-web/server.rs b/examples/src/grpc-web/server.rs index 7734a7663..5a86341fd 100644 --- a/examples/src/grpc-web/server.rs +++ b/examples/src/grpc-web/server.rs @@ -1,4 +1,7 @@ -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/h2c/server.rs b/examples/src/h2c/server.rs index a66b1e881..24f742ad3 100644 --- a/examples/src/h2c/server.rs +++ b/examples/src/h2c/server.rs @@ -4,7 +4,7 @@ use hyper_util::rt::{TokioExecutor, TokioIo}; use hyper_util::server::conn::auto::Builder; use hyper_util::service::TowerToHyperService; use tokio::net::TcpListener; -use tonic::{service::Routes, Request, Response, Status}; +use tonic::{service::Routes, transport::RequestExt, Request, Response, Status}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/health/server.rs b/examples/src/health/server.rs index 7b12e8668..995a241f0 100644 --- a/examples/src/health/server.rs +++ b/examples/src/health/server.rs @@ -1,4 +1,7 @@ -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/helloworld/server.rs b/examples/src/helloworld/server.rs index c6398bb61..4a62132c2 100644 --- a/examples/src/helloworld/server.rs +++ b/examples/src/helloworld/server.rs @@ -1,4 +1,7 @@ -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/json-codec/server.rs b/examples/src/json-codec/server.rs index 1029b0bf9..b0aec8aaa 100644 --- a/examples/src/json-codec/server.rs +++ b/examples/src/json-codec/server.rs @@ -4,7 +4,10 @@ //! in the `examples/build.rs` file. As defined there, the generated code assumes that a module //! `crate::common` exists which defines `HelloRequest`, `HelloResponse`, and `JsonCodec`. -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; pub mod common; use common::{HelloRequest, HelloResponse}; diff --git a/examples/src/reflection/server.rs b/examples/src/reflection/server.rs index 4bcd5d2d9..7d3ca2461 100644 --- a/examples/src/reflection/server.rs +++ b/examples/src/reflection/server.rs @@ -1,4 +1,4 @@ -use tonic::transport::Server; +use tonic::transport::{RequestExt, Server}; use tonic::{Request, Response, Status}; mod proto { diff --git a/examples/src/richer-error/server.rs b/examples/src/richer-error/server.rs index 235f8c157..e0baa79bd 100644 --- a/examples/src/richer-error/server.rs +++ b/examples/src/richer-error/server.rs @@ -1,4 +1,7 @@ -use tonic::{transport::Server, Code, Request, Response, Status}; +use tonic::{ + transport::{server::RequestExt, Server}, + Code, Request, Response, Status, +}; use tonic_types::{ErrorDetails, StatusExt}; use hello_world::greeter_server::{Greeter, GreeterServer}; diff --git a/examples/src/richer-error/server_vec.rs b/examples/src/richer-error/server_vec.rs index 80093e55f..a72a034a0 100644 --- a/examples/src/richer-error/server_vec.rs +++ b/examples/src/richer-error/server_vec.rs @@ -1,4 +1,7 @@ -use tonic::{transport::Server, Code, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Code, Request, Response, Status, +}; use tonic_types::{BadRequest, Help, LocalizedMessage, StatusExt}; use hello_world::greeter_server::{Greeter, GreeterServer}; diff --git a/examples/src/streaming/server.rs b/examples/src/streaming/server.rs index ab841075b..6348446a1 100644 --- a/examples/src/streaming/server.rs +++ b/examples/src/streaming/server.rs @@ -5,7 +5,10 @@ pub mod pb { use std::{error::Error, io::ErrorKind, net::ToSocketAddrs, pin::Pin, time::Duration}; use tokio::sync::mpsc; use tokio_stream::{wrappers::ReceiverStream, Stream, StreamExt}; -use tonic::{transport::Server, Request, Response, Status, Streaming}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, Streaming, +}; use pb::{EchoRequest, EchoResponse}; diff --git a/examples/src/timeout/server.rs b/examples/src/timeout/server.rs index 2d5b1fa2e..4f450a823 100644 --- a/examples/src/timeout/server.rs +++ b/examples/src/timeout/server.rs @@ -1,6 +1,9 @@ use std::time::Duration; use tokio::time::sleep; -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{ + transport::{RequestExt, Server}, + Request, Response, Status, +}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; diff --git a/examples/src/tls/server.rs b/examples/src/tls/server.rs index 5d2935fd8..1cfb554d4 100644 --- a/examples/src/tls/server.rs +++ b/examples/src/tls/server.rs @@ -6,7 +6,7 @@ use pb::{EchoRequest, EchoResponse}; use tonic::{ transport::{ server::{TcpConnectInfo, TlsConnectInfo}, - Identity, Server, ServerTlsConfig, + Identity, RequestExt, Server, ServerTlsConfig, }, Request, Response, Status, }; diff --git a/examples/src/tls_client_auth/server.rs b/examples/src/tls_client_auth/server.rs index 224620523..beae7d579 100644 --- a/examples/src/tls_client_auth/server.rs +++ b/examples/src/tls_client_auth/server.rs @@ -3,7 +3,7 @@ pub mod pb { } use pb::{EchoRequest, EchoResponse}; -use tonic::transport::{Certificate, Identity, Server, ServerTlsConfig}; +use tonic::transport::{Certificate, Identity, RequestExt, Server, ServerTlsConfig}; use tonic::{Request, Response, Status}; type EchoResult = Result, Status>; diff --git a/examples/src/tower/server.rs b/examples/src/tower/server.rs index a4f9f4237..56d919968 100644 --- a/examples/src/tower/server.rs +++ b/examples/src/tower/server.rs @@ -3,7 +3,11 @@ use std::{ task::{Context, Poll}, time::Duration, }; -use tonic::{body::BoxBody, transport::Server, Request, Response, Status}; +use tonic::{ + body::BoxBody, + transport::{RequestExt, Server}, + Request, Response, Status, +}; use tower::{Layer, Service}; use hello_world::greeter_server::{Greeter, GreeterServer}; diff --git a/tests/integration_tests/tests/connect_info.rs b/tests/integration_tests/tests/connect_info.rs index e87bb858f..27d62c3a4 100644 --- a/tests/integration_tests/tests/connect_info.rs +++ b/tests/integration_tests/tests/connect_info.rs @@ -2,7 +2,7 @@ use integration_tests::pb::{test_client, test_server, Input, Output}; use std::time::Duration; use tokio::sync::oneshot; use tonic::{ - transport::{server::TcpConnectInfo, Endpoint, Server}, + transport::{server::TcpConnectInfo, Endpoint, RequestExt, Server}, Request, Response, Status, }; @@ -60,7 +60,7 @@ pub mod unix { }; use tokio_stream::wrappers::UnixListenerStream; use tonic::{ - transport::{server::UdsConnectInfo, Endpoint, Server, Uri}, + transport::{server::UdsConnectInfo, Endpoint, RequestExt, Server, Uri}, Request, Response, Status, }; use tower::service_fn; diff --git a/tonic/src/request.rs b/tonic/src/request.rs index 592d71576..8b5aadb1a 100644 --- a/tonic/src/request.rs +++ b/tonic/src/request.rs @@ -1,18 +1,10 @@ -use crate::metadata::{MetadataMap, MetadataValue}; -#[cfg(feature = "server")] -use crate::transport::server::TcpConnectInfo; -#[cfg(all(feature = "server", feature = "tls"))] -use crate::transport::server::TlsConnectInfo; -use http::Extensions; -#[cfg(feature = "server")] -use std::net::SocketAddr; -#[cfg(all(feature = "server", feature = "tls"))] -use std::sync::Arc; use std::time::Duration; -#[cfg(all(feature = "server", feature = "tls"))] -use tokio_rustls::rustls::pki_types::CertificateDer; + +use http::Extensions; use tokio_stream::Stream; +use crate::metadata::{MetadataMap, MetadataValue}; + /// A gRPC request and metadata from an RPC call. #[derive(Debug)] pub struct Request { @@ -206,63 +198,6 @@ impl Request { } } - /// Get the local address of this connection. - /// - /// This will return `None` if the `IO` type used - /// does not implement `Connected` or when using a unix domain socket. - /// This currently only works on the server side. - #[cfg(feature = "server")] - pub fn local_addr(&self) -> Option { - let addr = self - .extensions() - .get::() - .and_then(|i| i.local_addr()); - - #[cfg(feature = "tls")] - let addr = addr.or_else(|| { - self.extensions() - .get::>() - .and_then(|i| i.get_ref().local_addr()) - }); - - addr - } - - /// Get the remote address of this connection. - /// - /// This will return `None` if the `IO` type used - /// does not implement `Connected` or when using a unix domain socket. - /// This currently only works on the server side. - #[cfg(feature = "server")] - pub fn remote_addr(&self) -> Option { - let addr = self - .extensions() - .get::() - .and_then(|i| i.remote_addr()); - - #[cfg(feature = "tls")] - let addr = addr.or_else(|| { - self.extensions() - .get::>() - .and_then(|i| i.get_ref().remote_addr()) - }); - - addr - } - - /// Get the peer certificates of the connected client. - /// - /// This is used to fetch the certificates from the TLS session - /// and is mostly used for mTLS. This currently only returns - /// `Some` on the server side of the `transport` server with - /// TLS enabled connections. - #[cfg(all(feature = "server", feature = "tls"))] - pub fn peer_certs(&self) -> Option>>> { - self.extensions() - .get::>() - .and_then(|i| i.peer_certs()) - } - /// Set the max duration the request is allowed to take. /// /// Requires the server to support the `grpc-timeout` metadata, which Tonic does. diff --git a/tonic/src/transport/mod.rs b/tonic/src/transport/mod.rs index c81208d0e..5788c9bce 100644 --- a/tonic/src/transport/mod.rs +++ b/tonic/src/transport/mod.rs @@ -105,7 +105,7 @@ pub use self::channel::{Channel, Endpoint}; pub use self::error::Error; #[doc(inline)] #[cfg(feature = "server")] -pub use self::server::Server; +pub use self::server::{RequestExt, Server}; /// Deprecated. Please use [`crate::status::TimeoutExpired`] instead. pub use crate::status::TimeoutExpired; diff --git a/tonic/src/transport/server/mod.rs b/tonic/src/transport/server/mod.rs index 62006e1a6..b642bf5ba 100644 --- a/tonic/src/transport/server/mod.rs +++ b/tonic/src/transport/server/mod.rs @@ -2,6 +2,7 @@ mod conn; mod incoming; +mod request_ext; mod service; #[cfg(feature = "tls")] mod tls; @@ -25,6 +26,8 @@ pub use tls::ServerTlsConfig; #[cfg(feature = "tls")] pub use conn::TlsConnectInfo; +pub use self::request_ext::RequestExt; + #[cfg(feature = "tls")] use self::service::TlsAcceptor; diff --git a/tonic/src/transport/server/request_ext.rs b/tonic/src/transport/server/request_ext.rs new file mode 100644 index 000000000..36c5764ae --- /dev/null +++ b/tonic/src/transport/server/request_ext.rs @@ -0,0 +1,84 @@ +use std::net::SocketAddr; +#[cfg(feature = "tls")] +use std::sync::Arc; + +#[cfg(feature = "tls")] +use tokio_rustls::rustls::pki_types::CertificateDer; + +use super::TcpConnectInfo; +#[cfg(feature = "tls")] +use super::TlsConnectInfo; +use crate::Request; + +mod sealed { + pub trait Sealed {} +} + +impl sealed::Sealed for Request {} + +/// An extension trait adding utility methods to [`Request`]. +pub trait RequestExt: sealed::Sealed { + /// Get the local address of this connection. + /// + /// This will return `None` if the `IO` type used + /// does not implement `Connected` or when using a unix domain socket. + /// This currently only works on the server side. + fn local_addr(&self) -> Option; + + /// Get the remote address of this connection. + /// + /// This will return `None` if the `IO` type used + /// does not implement `Connected` or when using a unix domain socket. + /// This currently only works on the server side. + fn remote_addr(&self) -> Option; + + /// Get the peer certificates of the connected client. + /// + /// This is used to fetch the certificates from the TLS session + /// and is mostly used for mTLS. This currently only returns + /// `Some` on the server side of the `transport` server with + /// TLS enabled connections. + #[cfg(feature = "tls")] + fn peer_certs(&self) -> Option>>>; +} + +impl RequestExt for Request { + fn local_addr(&self) -> Option { + let addr = self + .extensions() + .get::() + .and_then(|i| i.local_addr()); + + #[cfg(feature = "tls")] + let addr = addr.or_else(|| { + self.extensions() + .get::>() + .and_then(|i| i.get_ref().local_addr()) + }); + + addr + } + + fn remote_addr(&self) -> Option { + let addr = self + .extensions() + .get::() + .and_then(|i| i.remote_addr()); + + #[cfg(feature = "tls")] + let addr = addr.or_else(|| { + self.extensions() + .get::>() + .and_then(|i| i.get_ref().remote_addr()) + }); + + addr + } + + #[cfg(feature = "tls")] + fn peer_certs(&self) -> Option>>> { + self.extensions() + .get::>() + .and_then(|i| i.peer_certs()) + } +}