Skip to content

Commit

Permalink
feat: make pub Channel fns that allow creating it from a custom con…
Browse files Browse the repository at this point in the history
…nector (#2015)

* feat: make pub `Channel` fns that allow creating it from a custom connector

The connector is required to be a `Service` that accepts a `http::Uri` and
returns a connection implementing hyper's IO traits, which is a very reasonable
requirement that can be fulfilled by advanced users that need to customize any
mechanics that don't fit into the paved path for HTTP and HTTPS with tonic.

One such requirement is customizing `rustls::ClientConfig`, which has come up
for a number of users. They have been pointed in the direction of a custom
connector, but the APIs on `Endpoint` are not always suitable:

`Enedpoint::connect_(lazy_)with_connector` always wraps the provided connector
with `transport::channel::service::Connector`. This wrapper validates if the
scheme is HTTPS, the TLS feature is enabled, and TLS was not configured on the
endpoint, and raises an error `HttpsUriWithoutTlsSupport` in this situation.
This is a good safety feature in general, but not if the wrapped connector is
taking care of TLS.

As a side bonus, `tonic::transport::channel::service::io::BoxedIo` can be
avoided.

* chore: remove redundant bound on connections
  • Loading branch information
shikhar authored Oct 22, 2024
1 parent 9989968 commit d61a55f
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions tonic/src/transport/channel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use http::{
uri::{InvalidUri, Uri},
Request, Response,
};
use hyper_util::client::legacy::connect::Connection as HyperConnection;
use std::{
fmt,
future::Future,
Expand Down Expand Up @@ -144,12 +143,15 @@ impl Channel {
(Self::balance(list, DEFAULT_BUFFER_SIZE, executor), tx)
}

pub(crate) fn new<C>(connector: C, endpoint: Endpoint) -> Self
/// Create a new [`Channel`] using a custom connector to the provided [Endpoint].
///
/// This is a lower level API, prefer to use [`Endpoint::connect_lazy`] if you are not using a custom connector.
pub fn new<C>(connector: C, endpoint: Endpoint) -> Self
where
C: Service<Uri> + Send + 'static,
C::Error: Into<crate::BoxError> + Send,
C::Future: Send,
C::Response: rt::Read + rt::Write + HyperConnection + Unpin + Send + 'static,
C::Response: rt::Read + rt::Write + Unpin + Send + 'static,
{
let buffer_size = endpoint.buffer_size.unwrap_or(DEFAULT_BUFFER_SIZE);
let executor = endpoint.executor.clone();
Expand All @@ -162,12 +164,15 @@ impl Channel {
Channel { svc }
}

pub(crate) async fn connect<C>(connector: C, endpoint: Endpoint) -> Result<Self, super::Error>
/// Connect to the provided [`Endpoint`] using the provided connector, and return a new [`Channel`].
///
/// This is a lower level API, prefer to use [`Endpoint::connect`] if you are not using a custom connector.
pub async fn connect<C>(connector: C, endpoint: Endpoint) -> Result<Self, super::Error>
where
C: Service<Uri> + Send + 'static,
C::Error: Into<crate::BoxError> + Send,
C::Future: Unpin + Send,
C::Response: rt::Read + rt::Write + HyperConnection + Unpin + Send + 'static,
C::Response: rt::Read + rt::Write + Unpin + Send + 'static,
{
let buffer_size = endpoint.buffer_size.unwrap_or(DEFAULT_BUFFER_SIZE);
let executor = endpoint.executor.clone();
Expand Down

0 comments on commit d61a55f

Please sign in to comment.