(server: &str, tls: &TlsOptions)
| 339 | } |
| 340 | |
| 341 | pub async fn build_channel(server: &str, tls: &TlsOptions) -> Result<Channel> { |
| 342 | if server.starts_with("http://") { |
| 343 | let endpoint = Endpoint::from_shared(server.to_string()) |
| 344 | .into_diagnostic()? |
| 345 | .connect_timeout(Duration::from_secs(10)) |
| 346 | .http2_adaptive_window(true) |
| 347 | .http2_keep_alive_interval(Duration::from_secs(10)) |
| 348 | .keep_alive_while_idle(true); |
| 349 | return endpoint.connect().await.into_diagnostic(); |
| 350 | } |
| 351 | |
| 352 | // When Cloudflare edge bearer auth is active and the server is HTTPS, |
| 353 | // route traffic through a local WebSocket tunnel proxy instead. |
| 354 | // OIDC tokens bypass the tunnel — they connect directly. |
| 355 | if tls.edge_token.is_some() && server.starts_with("https://") { |
| 356 | let token = tls |
| 357 | .edge_token |
| 358 | .as_deref() |
| 359 | .ok_or_else(|| miette::miette!("edge token required for tunnel"))?; |
| 360 | let local_addr = edge_tunnel_addr(server, token).await?; |
| 361 | |
| 362 | // Connect to the local tunnel proxy over plaintext HTTP/2. |
| 363 | let local_url = format!("http://{local_addr}"); |
| 364 | let endpoint = Endpoint::from_shared(local_url) |
| 365 | .into_diagnostic()? |
| 366 | .connect_timeout(Duration::from_secs(10)) |
| 367 | .http2_adaptive_window(true) |
| 368 | .http2_keep_alive_interval(Duration::from_secs(10)) |
| 369 | .keep_alive_while_idle(true); |
| 370 | return endpoint.connect().await.into_diagnostic(); |
| 371 | } |
| 372 | |
| 373 | if tls.gateway_insecure && server.starts_with("https://") { |
| 374 | tracing::warn!("TLS certificate verification is disabled — do not use in production"); |
| 375 | let rustls_config = build_insecure_rustls_config()?; |
| 376 | let tls_connector = tokio_rustls::TlsConnector::from(std::sync::Arc::new(rustls_config)); |
| 377 | let connector = InsecureTlsConnector { tls_connector }; |
| 378 | // Use http:// so tonic does not layer its own TLS on top — our |
| 379 | // connector performs TLS with the insecure config. |
| 380 | let http_uri = server.replacen("https://", "http://", 1); |
| 381 | let endpoint = Endpoint::from_shared(http_uri) |
| 382 | .into_diagnostic()? |
| 383 | .connect_timeout(Duration::from_secs(10)) |
| 384 | .http2_keep_alive_interval(Duration::from_secs(10)) |
| 385 | .keep_alive_while_idle(true); |
| 386 | return endpoint |
| 387 | .connect_with_connector(connector) |
| 388 | .await |
| 389 | .into_diagnostic(); |
| 390 | } |
| 391 | |
| 392 | let mut endpoint = Endpoint::from_shared(server.to_string()) |
| 393 | .into_diagnostic()? |
| 394 | .connect_timeout(Duration::from_secs(10)) |
| 395 | .http2_adaptive_window(true) |
| 396 | .http2_keep_alive_interval(Duration::from_secs(10)) |
| 397 | .keep_alive_while_idle(true); |
| 398 |
no test coverage detected