tonic icon indicating copy to clipboard operation
tonic copied to clipboard

feat: Add http proxy support

Open victornguen opened this issue 7 months ago • 4 comments

Motivation

Resolves #2298

This PR adds support for HTTP proxying to Tonic clients

Solution

This PR implements HTTP proxy support for Tonic clients by leveraging [hyper-util]'s built-in proxy functionality, specifically the Tunnel type for HTTP CONNECT proxying. The solution includes:

  • Proxy configuration API:

    • Endpoint::proxy_uri() allows explicit proxy configuration.
    • Endpoint::proxy_from_env(true) enables automatic proxy detection via environment variables (http_proxy, https_proxy, no_proxy).
  • Proxy resolution logic:

    • Explicit proxy configuration takes precedence over environment variables.
    • no_proxy is respected for bypassing the proxy for specific hosts.
  • Tests:

    • Tests verify explicit proxy configuration, environment variable detection, no_proxy bypass, and precedence rules.
    • Tests use a mock proxy server to ensure actual proxy connections are made or bypassed as expected.
    • Test isolation is enforced to avoid environment variable leakage between tests.

This change is backward compatible.

victornguen avatar Jul 06 '25 11:07 victornguen

@dfawley @LucioFranco please take a look

victornguen avatar Jul 10 '25 20:07 victornguen

@victornguen i also want this feature. i using Endpoint.connect_with_connector. but got error can't resolve.

    async fn connect(endpoint: Endpoint) -> Result<TonicChannel, tonic::transport::Error> {
        let channel = endpoint.connect().await?;
        Ok(channel)
        // get the https_proxy env var
        if let Ok(proxy) = std::env::var("HTTPS_PROXY") {
            let proxy = {
                let proxy_uri = proxy.parse().unwrap();
                let proxy = Proxy::new(Intercept::All, proxy_uri);
                let connector = HttpConnector::new();
                let proxy_connector = ProxyConnector::from_proxy(connector, proxy).unwrap();
                proxy_connector
            };
            let channel = endpoint.connect_with_connector(proxy).await?;
            Ok(channel)
        } else {
            let channel = endpoint.connect().await?;
            Ok(channel)
        }
    }

TonicTransport(tonic::transport::Error(Transport, ConnectError(Custom { kind: InvalidData, error: InvalidMessage(InvalidContentType) })))

ganluo960214 avatar Jul 21 '25 14:07 ganluo960214

@victornguen Were there any updates on this review? I need to use Tonic over an HTTP proxy

LeoCBS avatar Sep 24 '25 11:09 LeoCBS

@victornguen Were there any updates on this review? I need to use Tonic over an HTTP proxy

Still waiting for a review from the maintainers.

@tottoto please take a look

victornguen avatar Nov 29 '25 21:11 victornguen