Aakash Jain
Aakash Jain

Reputation: 1973

Google Cloud Java clients: forcing HTTP when setting a custom endpoint

I am using Google's LanguageServiceClient from com.google.cloud:google-cloud-vision:1.16.0, and ImageAnnotatorClient from com.google.cloud:google-cloud-language:1.16.0.

They are used in a project that runs inside a private VPN. The company's infrastructure dictates that accessing external services must be done through a forward proxy. Furthermore, all forward proxies in the VPN are mandated to be on HTTP, not HTTPS.

So I have a forward proxy xx.xx.xx.xx, and all requests like http://xx.xx.xx.xx/somePath get forwarded to https://language.googleapis.com/somePath. I tested this with some curl requests and they way work correctly.

I have changed the endpoint as follows:

LanguageServiceSettings serviceSettings = LanguageServiceSettings.newBuilder()
                .setEndpoint("xx.xx.xx.xx:80")
                //the default value of this is "language.googleapis.com:443"
                .build();
languageServiceClient = LanguageServiceClient.create(serviceSettings);

However, the client seems to be hitting the new endpoint via HTTPS. I can't figure out how to set the scheme. Any help would be appreciated.

Upvotes: 0

Views: 481

Answers (1)

Aakash Jain
Aakash Jain

Reputation: 1973

Turns out that even getting a forward proxy on HTTPS would not have worked, since the library rejects requests upon seeing a mismatch between the SSL certificate domain (language.googleapis.com) and the request URL (the forward proxy IP).

Instead, I stuck with the HTTP proxies and made it work as follows:

HttpHost proxy = new HttpHost("xx.xx.xx.xx", 80);

HttpTransportFactory transportFactory = () -> new ApacheHttpTransport.Builder()
                .setProxy(proxy)
                .build();

CredentialsProvider credentialsProvider = () -> GoogleCredentials.getApplicationDefault(transportFactory);

LanguageServiceSettings serviceSettings = LanguageServiceSettings.newBuilder()
                .setCredentialsProvider(credentialsProvider)
                .build();

LanguageServiceClient languageServiceClient = LanguageServiceClient.create(serviceSettings);

This takes care of the auth step, however, the actual request is still being made to language.googleapis.com.

This cannot be similarly overriden since the request is made using GRPC instead of Google Http. GRPC does not have any provision for setting a proxy in code, as far as I can tell. One way around this is to set this environment variable:

export GRPC_PROXY_EXP=xx.xx.xx.xx:80

Caveats:

  • The GRPC_PROXY_EXP variable will affect all requests in your application that use GRPC.
  • Your proxy must support CONNECT requests in order for the GRPC_PROXY_EXP variable to work
  • As of writing this answer, google-cloud-vision/language are at 1.20.0, and use version 1.9.0 of GRPC. This version of GRPC has a bug that causes GRPC_PROXY_EXP to not work correctly. Version 1.10.0 also has the same bug. The only version that works is 1.9.1. You will have to go through all dependencies of the google cloud library, and for every io.grpc:*:1.9.0 package that you find, add a dependency on version 1.9.1 of that package to your project.

Upvotes: 2

Related Questions