hyperium / tonic

A native gRPC client & server implementation with async/await support.
https://docs.rs/tonic
MIT License
9.72k stars 992 forks source link

calling grpc server hosted on cloud run with https fails with transport error #1817

Closed codeBehindMe closed 1 month ago

codeBehindMe commented 1 month ago

Bug Report

Version

tonic v0.12.1 tonic-build v0.12.1

Platform

Linux 3c99df5b0cc4 5.15.133.1-microsoft-standard-WSL2 # 1 SMP Thu Oct 5 21:02:42 UTC 2023 x86_64 GNU/Linux

Description

Steps to reproduce

  1. Following the documentation, create a simple grpc client and server using tonic.
  2. Build server.rs and deploy the service to Google Cloud Run using gcloud deploy. Retrieve the URL.
  3. Invoke the a method in the service using the url https://project-id-randomstring-ts.a.run.app:443 using the client.rs file

I tried this code:

use hello_world::greeter_client::GreeterClient;
use hello_world::HelloRequest;

pub mod hello_world {
    tonic::include_proto!("helloworld");
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = GreeterClient::connect("https://project-id-randomstring-ts.a.run.app:443").await?;

    let request = tonic::Request::new(HelloRequest {
        name: "Tonic".into(),
    });

    let response = client.say_hello(request).await?;

    println!("RESPONSE={:?}", response);

    Ok(())
}

Expected Behaviour: Return the response from the method

Instead, this happened: Error: tonic::transport::Error(Transport, ConnectError(HttpsUriWithoutTlsSupport(())))

alexrudy commented 1 month ago

HttpsUriWithoutTlsSupport means that you have not enabled the tls feature for tonic, and so it can't connect viahttps://, only http://. However, your endpoint probably expects HTTPS (since it is on port 443).

You'll want to enable the tls feature, and then configure your endpoint using Endpoint::tls_config. You should take a look at the tls-roots and tls-webpki-roots features as well, which provide easy ways to configure your channel's TLS settings so that it can verify certificates.

codeBehindMe commented 1 month ago

Thanks @alexrudy , indeed adding tls-roots to features and then updating the code to the following fixed the issue.

let endpoint = Channel::from_static("https://project-id-randomstring-ts.a.run.app:443")
        .tls_config(tonic::transport::ClientTlsConfig::new().with_native_roots())?
        .http2_keep_alive_interval(std::time::Duration::from_secs(10))
        .connect()
        .await?;