Skip to content

[Rust] Proxied gRPC channel ignores ClientTlsConfig → InvalidContentType on every TLS endpoint #388

Description

@yogihardi

SDK

Rust

SDK Version

rust v2.2.2 and Go v1.2.0

Operating System

Linux 6.17.0-29-generic (Ubuntu)

Description

When the zerobus-sdk Rust core builds a gRPC channel through a proxy (HTTPS_PROXY or GRPC_PROXY), the endpoint's ClientTlsConfig is not applied on top of the tunneled stream. The HTTP CONNECT to the Zerobus host succeeds, but the client then speaks plaintext HTTP/2 to a TLS-only server through the tunnel, and the server's response is rejected as:

ZerobusError: Failed to create stream: code: 'The service is currently unavailable',
message: "received corrupt message of type InvalidContentType",
source: tonic::transport::Error(Transport, ConnectError(Custom { kind: InvalidData,
        error: InvalidMessage(InvalidContentType) }))

A direct (non-proxied) connection with the same credentials connects fine. Proxying — the whole point of the feature — is non-functional for real (TLS) Databricks endpoints. Because every language SDK wraps this Rust core, all of them are affected.

Reproduction

  1. Create a Zerobus Ingest client with valid creds (workspaceUrl, zerobusServerUrl, catalog, schema, table, clientId, clientSecret).
  2. Set GRPC_PROXY (or HTTPS_PROXY) to http://<any-working-http-proxy>:<port> — a corporate Squid, or a trivial CONNECT proxy that tunnels to the internet.
  3. Attempt to open the stream.
  4. Stream creation fails with InvalidContentType. The proxy logs show CONNECT <zerobusServerUrl>:443 was received — i.e. routing works; the TLS-over-tunnel layer is what fails.

Matrix (all proxied combinations fail identically; only direct works)

Connection Result
Direct (no proxy) ✅ connects
GRPC_PROXY via mock CONNECT proxy InvalidContentType
GRPC_PROXY via real Squid InvalidContentType
HTTPS_PROXY via mock CONNECT proxy InvalidContentType
HTTPS_PROXY via real Squid InvalidContentType
no_proxy matches host (→ bypass → direct) ✅ connects

Expected behavior

When a proxy is configured (HTTPS_PROXY or GRPC_PROXY), the SDK should establish a gRPC channel that is functionally equivalent to the direct path:

  1. CONNECT tunnel is opened through the proxy to :443 — (already works).
  2. TLS handshake runs on top of the tunneled stream, using the endpoint's ClientTlsConfig (SecureTlsConfig / native roots), with SNI and certificate verification against the Zerobus host.
  3. HTTP/2 + gRPC are spoken over the TLS session, not over the raw tunnel.
  4. Stream creation succeeds and the client reports credentials verified / Connected, identically to the no-proxy case.
  5. No InvalidContentType (or any other TLS/plaintext-mismatch error) is produced when the server is TLS-only.

Equivalently: the connect_with_connector_lazy(proxy_connector) path must honor ClientTlsConfig the same way connect_lazy() does today. Proxied and direct connections should be indistinguishable to the
Zerobus server.

Is it a regression?

No

Logs

Additional context

Impact

  • Any user behind a forward proxy (the common enterprise case, e.g. corporate Squid via HTTPS_PROXY) cannot use the Zerobus SDK. Only direct egress works.
  • Affects every proxy type and every language SDK that depends on the shared Rust core.

Suggested fix

Apply the endpoint's TLS to the proxied connection — e.g. wrap the proxy connector so tonic's TLS layer runs on top of the tunneled stream, or build the channel so ClientTlsConfig is honored on the connect_with_connector path.

Add a regression test that uses SecureTlsConfig against a real TLS server through a CONNECT proxy (not NoTlsConfig / plaintext), so this path stops being silently untested.

Workaround

None for proxied egress. Only direct connectivity, or a no_proxy bypass for the Zerobus host, works.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions