diff --git a/.github/workflows/showcase.yaml b/.github/workflows/showcase.yaml index 3325dfadcc3a..6c1f135d0703 100644 --- a/.github/workflows/showcase.yaml +++ b/.github/workflows/showcase.yaml @@ -61,7 +61,22 @@ jobs: curl --location https://github.com/googleapis/gapic-showcase/releases/download/v${SHOWCASE_VERSION}/gapic-showcase-${SHOWCASE_VERSION}-linux-amd64.tar.gz --output /usr/src/showcase/showcase-${SHOWCASE_VERSION}-linux-amd64.tar.gz cd /usr/src/showcase/ tar -xf showcase-* + # Start standard insecure showcase server on default port 7469 for standard integration tests ./gapic-showcase run & + # Start secure TLS showcase server on port 7470 for PQC TLS integration tests + ./gapic-showcase run --port 7470 --tls --ca-cert-output-file /tmp/showcase-ca.pem & + # Wait deterministically for both background showcase servers to finish binding ports 7469/7470 + # and writing /tmp/showcase-ca.pem. Starting TLS requires RSA key generation and disk I/O, + # which can cause race conditions if tests start before /tmp/showcase-ca.pem is created. + for i in $(seq 1 30); do + if (echo > /dev/tcp/127.0.0.1/7469) 2>/dev/null && \ + (echo > /dev/tcp/127.0.0.1/7470) 2>/dev/null && \ + [ -f /tmp/showcase-ca.pem ]; then + echo "Showcase servers (ports 7469, 7470) and CA cert ready in attempt $i." + break + fi + sleep 0.2 + done cd - - name: Showcase integration tests working-directory: java-showcase @@ -166,7 +181,22 @@ jobs: curl --location https://github.com/googleapis/gapic-showcase/releases/download/v${SHOWCASE_VERSION}/gapic-showcase-${SHOWCASE_VERSION}-linux-amd64.tar.gz --output /usr/src/showcase/showcase-${SHOWCASE_VERSION}-linux-amd64.tar.gz cd /usr/src/showcase/ tar -xf showcase-* + # Start standard insecure showcase server on default port 7469 for standard integration tests ./gapic-showcase run & + # Start secure TLS showcase server on port 7470 for PQC TLS integration tests + ./gapic-showcase run --port 7470 --tls --ca-cert-output-file /tmp/showcase-ca.pem & + # Wait deterministically for both background showcase servers to finish binding ports 7469/7470 + # and writing /tmp/showcase-ca.pem. Starting TLS requires RSA key generation and disk I/O, + # which can cause race conditions if tests start before /tmp/showcase-ca.pem is created. + for i in $(seq 1 30); do + if (echo > /dev/tcp/127.0.0.1/7469) 2>/dev/null && \ + (echo > /dev/tcp/127.0.0.1/7470) 2>/dev/null && \ + [ -f /tmp/showcase-ca.pem ]; then + echo "Showcase servers (ports 7469, 7470) and CA cert ready in attempt $i." + break + fi + sleep 0.2 + done cd - - name: Showcase integration tests working-directory: java-showcase diff --git a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITPostQuantumCryptography.java b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITPostQuantumCryptography.java new file mode 100644 index 000000000000..5a4526289954 --- /dev/null +++ b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITPostQuantumCryptography.java @@ -0,0 +1,266 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.showcase.v1beta1.it; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.httpjson.HttpJsonMetadata; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.showcase.v1beta1.EchoClient; +import com.google.showcase.v1beta1.EchoRequest; +import com.google.showcase.v1beta1.EchoResponse; +import com.google.showcase.v1beta1.EchoSettings; +import com.google.showcase.v1beta1.it.util.HttpJsonCapturingClientInterceptor; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.Provider; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.util.Collections; +import java.util.List; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.TrustManagerFactory; +import org.conscrypt.Conscrypt; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +/** + * Integration tests to verify Post-Quantum Cryptography (PQC) TLS negotiation for HTTP/JSON (REST) + * clients. + * + *

These tests execute calls against a local secure (TLS-enabled) Showcase server. During the TLS + * handshake, the client and server negotiate cipher suites and key exchange groups. Showcase + * injects information about the negotiated TLS connection parameters into custom headers: + * + *

+ * + *

Verification cases: + * + *

    + *
  1. {@code testHttpJsonPqc}: Verifies that HTTP/JSON transport defaults to Conscrypt and + * negotiates the hybrid post-quantum group {@code X25519MLKEM768}. + *
  2. {@code testHttpJsonPqc_withExplicitSecurityProvider}: Verifies that overriding the + * transport's SSLSocketFactory to explicitly use standard JDK JSSE provider (SunJSSE) falls + * back gracefully to classical key exchange ({@code X25519}) instead of crashing. + *
+ */ +public class ITPostQuantumCryptography { + + // TLS response header names from Showcase server + private static final String TLS_GROUP_HEADER = "x-showcase-tls-group"; + private static final String TLS_SUPPORTED_GROUPS_HEADER = + "x-showcase-tls-client-supported-groups"; + + // Expected TLS parameters + private static final String EXPECTED_PQC_GROUP = "X25519MLKEM768"; + + private static final String DEFAULT_CA_CERT_PATH = getCaCertPath(); + + /** + * Resolves the absolute path to the Showcase server's CA certificate PEM file. + * + * @return absolute path to the CA certificate file + */ + private static String getCaCertPath() { + String prop = System.getProperty("showcase.ca.cert.path"); + if (prop != null) { + return prop; + } + if (new File("/tmp/showcase-ca.pem").isFile()) { + return "/tmp/showcase-ca.pem"; + } + return "target/showcase-ca.pem"; + } + + private static final String SECURE_ENDPOINT = + System.getProperty("showcase.secure.endpoint", "localhost:7470"); + + @BeforeAll + static void setUp() { + File certFile = new File(DEFAULT_CA_CERT_PATH); + assertWithMessage("CA certificate file not found at " + DEFAULT_CA_CERT_PATH) + .that(certFile.isFile()) + .isTrue(); + } + + @Test + void testHttpJsonPqc() throws Exception { + + NetHttpTransport transport = + new NetHttpTransport.Builder() + .setSecurityProvider(Conscrypt.newProvider()) + .setSslSocketConfigurator( + socket -> { + if (Conscrypt.isConscrypt(socket)) { + Conscrypt.setNamedGroups( + socket, InstantiatingHttpJsonChannelProvider.DEFAULT_PQC_GROUPS); + } + }) + .trustCertificates(null, loadCaCert(DEFAULT_CA_CERT_PATH), "") + .build(); + + HttpJsonCapturingClientInterceptor interceptor = new HttpJsonCapturingClientInterceptor(); + + InstantiatingHttpJsonChannelProvider transportChannelProvider = + EchoSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(transport) + .setEndpoint("https://" + SECURE_ENDPOINT) + .setInterceptorProvider(() -> Collections.singletonList(interceptor)) + .build(); + + EchoSettings settings = + EchoSettings.newHttpJsonBuilder() + .setCredentialsProvider(NoCredentialsProvider.create()) + .setTransportChannelProvider(transportChannelProvider) + .build(); + + try (EchoClient client = EchoClient.create(settings)) { + EchoResponse response = + client.echo(EchoRequest.newBuilder().setContent("pqc-httpjson-test").build()); + assertThat(response.getContent()).isEqualTo("pqc-httpjson-test"); + + HttpJsonMetadata capturedHeaders = interceptor.metadata; + assertThat(capturedHeaders).isNotNull(); + + String negotiatedGroup = getSingleHeaderString(capturedHeaders, TLS_GROUP_HEADER); + assertThat(negotiatedGroup).isEqualTo(EXPECTED_PQC_GROUP); + + String supportedGroups = getSingleHeaderString(capturedHeaders, TLS_SUPPORTED_GROUPS_HEADER); + assertThat(supportedGroups).isNotNull(); + } + } + + @Test + void testHttpJsonPqc_withExplicitSecurityProviderNoPqcGroups() throws Exception { + // Explicitly use SunJSSE (JDK default) instead of Conscrypt + Provider sunJsseProvider = Security.getProvider("SunJSSE"); + assertThat(sunJsseProvider).isNotNull(); + + // Initialize SSLContext and TrustManagerFactory explicitly with SunJSSE provider to trust the + // CA + SSLContext sslContext = SSLContext.getInstance("TLS", sunJsseProvider); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm(), sunJsseProvider); + tmf.init(loadCaCert(DEFAULT_CA_CERT_PATH)); + sslContext.init(null, tmf.getTrustManagers(), null); + + // This test verifies client transport behavior when PQC algorithms are not offered. + // Future Java versions (e.g. JDK 27+) will enable PQC (ML-KEM) by default in standard JDK JSSE. + // Explicitly setting named groups to classical algorithms ensures that this test reliably + // tests the non-PQC classical TLS connection path regardless of underlying JDK defaults. + NetHttpTransport transport = + new NetHttpTransport.Builder() + .setSslSocketFactory(sslContext.getSocketFactory()) + .setSslSocketConfigurator( + socket -> { + try { + SSLParameters params = socket.getSSLParameters(); + params.setNamedGroups(new String[] {"X25519", "SecP256r1"}); + socket.setSSLParameters(params); + } catch (Exception e) { + // For JDK 8-19, SSLParameters.setNamedGroups() is unsupported, and JSSE + // naturally + // defaults to classical algorithms. Setting classical named groups is primarily + // for + // JDK 20+ when PQC becomes the default in standard JSSE. + } + }) + .build(); + + HttpJsonCapturingClientInterceptor interceptor = new HttpJsonCapturingClientInterceptor(); + + InstantiatingHttpJsonChannelProvider transportChannelProvider = + EchoSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(transport) + .setEndpoint("https://" + SECURE_ENDPOINT) + .setInterceptorProvider(() -> Collections.singletonList(interceptor)) + .build(); + + EchoSettings settings = + EchoSettings.newHttpJsonBuilder() + .setCredentialsProvider(NoCredentialsProvider.create()) + .setTransportChannelProvider(transportChannelProvider) + .build(); + + try (EchoClient client = EchoClient.create(settings)) { + EchoResponse response = + client.echo( + EchoRequest.newBuilder().setContent("pqc-httpjson-explicit-provider-test").build()); + assertThat(response.getContent()).isEqualTo("pqc-httpjson-explicit-provider-test"); + + HttpJsonMetadata capturedHeaders = interceptor.metadata; + assertThat(capturedHeaders).isNotNull(); + + String negotiatedGroup = getSingleHeaderString(capturedHeaders, TLS_GROUP_HEADER); + // Under classical non-PQC configuration, negotiated group is a classical curve + assertThat(negotiatedGroup).isAnyOf("X25519", "SecP256r1", "CurveP256"); + assertThat(negotiatedGroup).isNotEqualTo(EXPECTED_PQC_GROUP); + } + } + + /** + * Extracts the first string value of a specified HTTP response header from metadata. + * + * @param metadata the HTTP metadata containing response headers + * @param name the case-insensitive header key name + * @return header value string, or {@code null} if not found + */ + private static String getSingleHeaderString(HttpJsonMetadata metadata, String name) { + Object valueObj = metadata.getHeaders().get(name); + if (valueObj instanceof List) { + List list = (List) valueObj; + if (!list.isEmpty()) { + return String.valueOf(list.get(0)); + } + } else if (valueObj != null) { + return String.valueOf(valueObj); + } + return null; + } + + /** + * Loads an X.509 CA certificate file from disk into a new KeyStore instance. + * + * @param certPath path to the X.509 certificate file + * @return initialized KeyStore containing the certificate entry + * @throws Exception if reading or parsing the certificate fails + */ + private static KeyStore loadCaCert(String certPath) throws Exception { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + try (InputStream is = Files.newInputStream(Paths.get(certPath))) { + Certificate cert = cf.generateCertificate(is); + trustStore.setCertificateEntry("showcase-ca", cert); + } + return trustStore; + } +} diff --git a/sdk-platform-java/gax-java/gax-httpjson/pom.xml b/sdk-platform-java/gax-java/gax-httpjson/pom.xml index de839fe6e074..d70dbfe4459b 100644 --- a/sdk-platform-java/gax-java/gax-httpjson/pom.xml +++ b/sdk-platform-java/gax-java/gax-httpjson/pom.xml @@ -104,6 +104,11 @@ error_prone_annotations ${errorprone.version} + + org.conscrypt + conscrypt-openjdk-uber + ${conscrypt.version} + diff --git a/sdk-platform-java/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonTransportUtils.java b/sdk-platform-java/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonTransportUtils.java new file mode 100644 index 000000000000..ed46d9ad581c --- /dev/null +++ b/sdk-platform-java/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonTransportUtils.java @@ -0,0 +1,123 @@ +/* + * Copyright 2026 Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.google.api.gax.httpjson; + +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.core.InternalApi; +import java.security.Provider; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.conscrypt.Conscrypt; + +/** + * Utility class for creating and configuring {@link NetHttpTransport} instances with Post-Quantum + * Cryptography (PQC) Conscrypt support. + */ +@InternalApi +public class HttpJsonTransportUtils { + + private static final Logger LOG = Logger.getLogger(HttpJsonTransportUtils.class.getName()); + + /** + * Default TLS 1.3 Post-Quantum Cryptography (PQC) named groups configured when Conscrypt security + * provider is present: + * + * + */ + public static final String[] DEFAULT_PQC_GROUPS = + new String[] {"X25519MLKEM768", "SecP256r1MLKEM768", "X25519"}; + + /** + * Lazy initialization holder for Conscrypt {@link Provider}. + * + *

Caches the Conscrypt {@link Provider} instance (or {@code null} if initialization fails) to + * avoid repeated expensive JNI initialization operations on every transport creation. + * + *

Returns {@code null} on failure so that transport creation can fall back to default JDK TLS, + * ensuring that setting Conscrypt as the default security provider does not cause breaking + * failures for customers running on environments where Conscrypt is unsupported or unavailable. + */ + private static class ConscryptProviderHolder { + private static final Provider INSTANCE = createProvider(); + + private static Provider createProvider() { + try { + return Conscrypt.newProvider(); + } catch (Throwable t) { + LOG.log( + Level.WARNING, "Conscrypt native libraries not available. Falling back to JDK TLS.", t); + return null; + } + } + } + + /** + * Creates a {@link NetHttpTransport.Builder} pre-configured with Conscrypt as the security + * provider by default if Conscrypt is available. Users can customize the {@link + * NetHttpTransport.Builder} to use a different security provider. + */ + public static NetHttpTransport.Builder createConscryptHttpTransportBuilder() { + NetHttpTransport.Builder builder = new NetHttpTransport.Builder(); + Provider conscryptProvider = ConscryptProviderHolder.INSTANCE; + if (conscryptProvider == null) { + return builder; + } + return builder + .setSecurityProvider(conscryptProvider) + .setSslSocketConfigurator( + socket -> { + if (!Conscrypt.isConscrypt(socket)) { + return; + } + try { + Conscrypt.setNamedGroups(socket, DEFAULT_PQC_GROUPS); + } catch (Throwable t) { + // Catch runtime socket configuration errors (e.g. version mismatch or unexpected + // socket implementation) to gracefully fall back to Conscrypt's default TLS groups + // without failing transport creation. + LOG.log( + Level.WARNING, + "Failed to set PQC named groups on Conscrypt socket. Falling back to" + + " Conscrypt default TLS groups.", + t); + } + }); + } + + private HttpJsonTransportUtils() {} +} diff --git a/sdk-platform-java/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProvider.java b/sdk-platform-java/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProvider.java index 495fec1ed450..b31904d64a6a 100644 --- a/sdk-platform-java/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProvider.java +++ b/sdk-platform-java/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProvider.java @@ -191,16 +191,19 @@ public TransportChannelProvider withCredentials(Credentials credentials) { } HttpTransport createHttpTransport() throws IOException, GeneralSecurityException { - if (mtlsProvider == null) { - return null; - } - if (certificateBasedAccess.useMtlsClientCertificate()) { + NetHttpTransport.Builder builder = HttpJsonTransportUtils.createConscryptHttpTransportBuilder(); + return configureMtls(builder).build(); + } + + private NetHttpTransport.Builder configureMtls(NetHttpTransport.Builder builder) + throws IOException, GeneralSecurityException { + if (mtlsProvider != null && certificateBasedAccess.useMtlsClientCertificate()) { KeyStore mtlsKeyStore = mtlsProvider.getKeyStore(); if (mtlsKeyStore != null) { - return new NetHttpTransport.Builder().trustCertificates(null, mtlsKeyStore, "").build(); + builder.trustCertificates(null, mtlsKeyStore, ""); } } - return null; + return builder; } private HttpJsonTransportChannel createChannel() throws IOException, GeneralSecurityException { @@ -364,7 +367,8 @@ public InstantiatingHttpJsonChannelProvider build() { "DefaultMtlsProviderFactory encountered unexpected IOException: " + e.getMessage()); LOG.log( Level.WARNING, - "mTLS configuration was detected on the device, but mTLS failed to initialize. Falling back to non-mTLS channel."); + "mTLS configuration was detected on the device, but mTLS failed to initialize." + + " Falling back to non-mTLS channel."); } } } diff --git a/sdk-platform-java/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProviderTest.java b/sdk-platform-java/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProviderTest.java index 17ad9f2cbf2b..255628759ad7 100644 --- a/sdk-platform-java/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProviderTest.java +++ b/sdk-platform-java/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProviderTest.java @@ -32,6 +32,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.gax.rpc.HeaderProvider; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.api.gax.rpc.mtls.AbstractMtlsTransportChannelTest; @@ -192,6 +193,27 @@ protected Object getMtlsObjectFromTransportChannel( .setHeaderProvider(Mockito.mock(HeaderProvider.class)) .setExecutor(Mockito.mock(Executor.class)) .build(); - return channelProvider.createHttpTransport(); + NetHttpTransport transport = (NetHttpTransport) channelProvider.createHttpTransport(); + return (transport != null && transport.isMtls()) ? transport : null; + } + + @Test + void testCreateHttpTransport_returnsValidTransport() throws Exception { + InstantiatingHttpJsonChannelProvider channelProvider = + InstantiatingHttpJsonChannelProvider.newBuilder() + .setEndpoint("localhost:8080") + .setHeaderProvider(Mockito.mock(HeaderProvider.class)) + .setExecutor(Mockito.mock(Executor.class)) + .build(); + NetHttpTransport transport = (NetHttpTransport) channelProvider.createHttpTransport(); + assertThat(transport).isNotNull(); + } + + @Test + void testDefaultPqcGroups_containsExpectedGroups() { + assertThat(HttpJsonTransportUtils.DEFAULT_PQC_GROUPS) + .asList() + .containsExactly("X25519MLKEM768", "SecP256r1MLKEM768", "X25519") + .inOrder(); } } diff --git a/sdk-platform-java/java-core/google-cloud-core-http/pom.xml b/sdk-platform-java/java-core/google-cloud-core-http/pom.xml index 9bcac047678b..ee8beb09cbf0 100644 --- a/sdk-platform-java/java-core/google-cloud-core-http/pom.xml +++ b/sdk-platform-java/java-core/google-cloud-core-http/pom.xml @@ -75,6 +75,11 @@ error_prone_annotations + + org.conscrypt + conscrypt-openjdk-uber + + org.junit.platform diff --git a/sdk-platform-java/java-core/google-cloud-core-http/src/main/java/com/google/cloud/http/HttpTransportOptions.java b/sdk-platform-java/java-core/google-cloud-core-http/src/main/java/com/google/cloud/http/HttpTransportOptions.java index f5ad54532f66..31222d114494 100644 --- a/sdk-platform-java/java-core/google-cloud-core-http/src/main/java/com/google/cloud/http/HttpTransportOptions.java +++ b/sdk-platform-java/java-core/google-cloud-core-http/src/main/java/com/google/cloud/http/HttpTransportOptions.java @@ -22,10 +22,10 @@ import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpRequestInitializer; import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.gax.core.GaxProperties; import com.google.api.gax.httpjson.HttpHeadersUtils; import com.google.api.gax.httpjson.HttpJsonStatusCode; +import com.google.api.gax.httpjson.HttpJsonTransportUtils; import com.google.api.gax.rpc.ApiClientHeaderProvider; import com.google.api.gax.rpc.EndpointContext; import com.google.api.gax.rpc.HeaderProvider; @@ -41,6 +41,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.util.Objects; +import java.util.logging.Logger; /** Class representing service options for those services that use HTTP as the transport layer. */ public class HttpTransportOptions implements TransportOptions { @@ -54,6 +55,7 @@ public class HttpTransportOptions implements TransportOptions { public static class DefaultHttpTransportFactory implements HttpTransportFactory { + private static final Logger LOG = Logger.getLogger(DefaultHttpTransportFactory.class.getName()); private static final HttpTransportFactory INSTANCE = new DefaultHttpTransportFactory(); @Override @@ -66,7 +68,8 @@ public HttpTransport create() { // Maybe not on App Engine } } - return new NetHttpTransport(); + + return HttpJsonTransportUtils.createConscryptHttpTransportBuilder().build(); } }