Repository: googleapis/google-api-java-client (java)

Issue:
Start using core5 and client5 libraries as core(4) and client(4) haven't changed since 2022
Thanks for stopping by to let us know something could be better!

**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response.

Please run down the following list and make sure you've tried the usual "quick fixes":

  - Search the issues already opened: https://github.com/googleapis/google-api-java-client/issues
  - Check for answers on StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform

If you are still having issues, please include as much information as possible:

#### Environment details

1. Specify the API at the beginning of the title. For example, "BigQuery: ...").
   General, Core, and Other are also allowed as types
`com.google.api-client:google-api-client:2.5.0`
2. OS type and version: NA
3. Java version: NA
4.  version(s): 2.5.0

#### 

You're currently dependent on 

- client https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
- core https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore

You should move to 

- client5 https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5
- core5 https://mvnrepository.com/artifact/org.apache.httpcomponents.core5/httpcore5

Automated dependency upgrade tools are not aware of the redirect `This artifact was moved to: xyz` , and you're currently not being alerted on your renovate dashboard to the new artifact series.

Pull request:
feat: Provide HttpTransport support for google certificates with apache HTTP client v5 (#2497)

Fixes #2497 ☕️

Patch:
diff --git a/docs/component-modules.md b/docs/component-modules.md
index 7277febc..ad780053 100644
--- a/docs/component-modules.md
+++ b/docs/component-modules.md
@@ -55,4 +55,13 @@ XML extensions to the Google API Client Library for Java
 (`google-api-client-xml`). This module depends on `google-api-client` and
 `google-http-client-xml`.
 
+## google-api-client-apache-v5
+
+Provides Apache extension to the Google HTTP Client Library for Java (`google-api-client-apache-v5`) that
+returns an implementation of `HttpTransport` based on the Apache HTTP Client (v5) with Google certificates loaded in
+truststore. This module depends on `google-http-client`.
+
+Please note this is the preferred Apache extension to be used, over the GoogleApacheHttpTransport included
+in `google-api-client` module. The previous google transport utilizes the EOL Apache HTTP Client v4.
+
 [protobuf]: https://developers.google.com/protocol-buffers/docs/overview
diff --git a/google-api-client-apache-v5/pom.xml b/google-api-client-apache-v5/pom.xml
new file mode 100644
index 00000000..8c5350d7
--- /dev/null
+++ b/google-api-client-apache-v5/pom.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.google.api-client</groupId>
+        <artifactId>google-api-client-parent</artifactId>
+        <version>2.6.1-SNAPSHOT</version>
+    </parent>
+    <artifactId>google-api-client-apache-v5</artifactId>
+    <name>Apache extensions to the Google APIs Client Library for Java</name>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>resources</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <links>
+                        <link>https://docs.oracle.com/javase/8/docs/api/</link>
+                        <link>https://cloud.google.com/appengine/docs/standard/java/javadoc/</link>
+                        <link>https://googleapis.dev/java/google-http-client/${project.http.version}/</link>
+                        <link>https://googleapis.dev/java/google-oauth-client/${project.oauth.version}/</link>
+                    </links>
+                    <doctitle>${project.name} ${project.version}</doctitle>
+                    <windowtitle>${project.artifactId} ${project.version}</windowtitle>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                        <manifest>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                        </manifest>
+                        <manifestEntries>
+                            <Automatic-Module-Name>google.api.client</Automatic-Module-Name>
+                        </manifestEntries>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>5.1.9</version>
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <instructions>
+                        <Bundle-DocURL>https://developers.google.com/api-client-library/java/</Bundle-DocURL>
+                        <Bundle-Description>Google HTTP transport wrapper for the Apache 5 Http Client.
+                        </Bundle-Description>
+                        <Bundle-SymbolicName>com.google.api.client.googleapis.apache</Bundle-SymbolicName>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>source-jar</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>validate-google-style</id>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>check</goal>
+                        </goals>
+                        <configuration>
+                            <configLocation>google_checks.xml</configLocation>
+                            <suppressionsLocation>src/checkstyle/checkstyle-suppressions.xml</suppressionsLocation>
+                            <includeTestSourceDirectory>true</includeTestSourceDirectory>
+                            <failOnViolation>true</failOnViolation>
+                            <violationSeverity>warning</violationSeverity>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+            <resource>
+                <directory>src/main/properties</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.api-client</groupId>
+            <artifactId>google-api-client</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpcore</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpclient</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.google.http-client</groupId>
+            <artifactId>google-http-client-apache-v5</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents.client5</groupId>
+            <artifactId>httpclient5</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents.core5</groupId>
+            <artifactId>httpcore5</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.http-client</groupId>
+            <artifactId>google-http-client</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpcore</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpclient</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.google.api-client</groupId>
+            <artifactId>google-api-client</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+            <version> ${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/google-api-client-apache-v5/src/checkstyle/checkstyle-suppressions.xml b/google-api-client-apache-v5/src/checkstyle/checkstyle-suppressions.xml
new file mode 100644
index 00000000..812319b6
--- /dev/null
+++ b/google-api-client-apache-v5/src/checkstyle/checkstyle-suppressions.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE suppressions PUBLIC
+        "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
+        "https://checkstyle.org/dtds/suppressions_1_2.dtd">
+<suppressions>
+    <!-- Test checkstyle suppressions -->
+    <suppress checks="MissingJavadocType" files=".*Test.java"/>
+    <suppress checks="AbbreviationAsWordInName" files=".*Test.java"/>
+    <suppress checks="VariableDeclarationUsageDistance" files=".*Test.java"/>
+</suppressions>
diff --git a/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransport.java b/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransport.java
new file mode 100644
index 00000000..00a7673b
--- /dev/null
+++ b/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransport.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2024 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
+ *
+ * http://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.api.client.googleapis.apache.v5;
+
+import com.google.api.client.googleapis.GoogleUtils;
+import com.google.api.client.googleapis.mtls.MtlsProvider;
+import com.google.api.client.googleapis.mtls.MtlsUtils;
+import com.google.api.client.googleapis.util.Utils;
+import com.google.api.client.http.apache.v5.Apache5HttpTransport;
+import com.google.api.client.util.SslUtils;
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import java.io.IOException;
+import java.net.ProxySelector;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
+import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner;
+import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
+import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
+import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
+import org.apache.hc.core5.http.config.Registry;
+import org.apache.hc.core5.http.config.RegistryBuilder;
+
+/**
+ * Utilities for Google APIs based on {@link Apache5HttpTransport}.
+ *
+ * @since 2.6.1
+ */
+public final class GoogleApache5HttpTransport {
+
+  /**
+   * Returns a new instance of {@link Apache5HttpTransport} that uses {@link
+   * GoogleUtils#getCertificateTrustStore()} for the trusted certificates. If
+   * `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true", and the default
+   * client certificate key store from {@link Utils#loadDefaultMtlsKeyStore()} is not null, then the
+   * transport uses the default client certificate and is mutual TLS.
+   */
+  public static Apache5HttpTransport newTrustedTransport()
+      throws GeneralSecurityException, IOException {
+    return newTrustedTransport(MtlsUtils.getDefaultMtlsProvider());
+  }
+
+  /**
+   * {@link Beta} <br>
+   * Returns a new instance of {@link Apache5HttpTransport} that uses {@link
+   * GoogleUtils#getCertificateTrustStore()} for the trusted certificates. mtlsProvider can be used
+   * to configure mutual TLS for the transport.
+   *
+   * @param mtlsProvider MtlsProvider to configure mutual TLS for the transport
+   */
+  @Beta
+  public static Apache5HttpTransport newTrustedTransport(MtlsProvider mtlsProvider)
+      throws GeneralSecurityException, IOException {
+
+    SocketFactoryRegistryHandler handler = new SocketFactoryRegistryHandler(mtlsProvider);
+
+    PoolingHttpClientConnectionManager connectionManager =
+        new PoolingHttpClientConnectionManager(handler.getSocketFactoryRegistry());
+    connectionManager.setMaxTotal(200);
+    connectionManager.setDefaultMaxPerRoute(20);
+    connectionManager.setDefaultConnectionConfig(
+        ConnectionConfig.custom()
+            .setTimeToLive(-1, TimeUnit.MILLISECONDS)
+            .setValidateAfterInactivity(-1L, TimeUnit.MILLISECONDS)
+            .build());
+
+    CloseableHttpClient client =
+        HttpClients.custom()
+            .useSystemProperties()
+            .setConnectionManager(connectionManager)
+            .setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault()))
+            .disableRedirectHandling()
+            .disableAutomaticRetries()
+            .build();
+
+    return new Apache5HttpTransport(client, handler.isMtls());
+  }
+
+  @VisibleForTesting
+  static class SocketFactoryRegistryHandler {
+    private final Registry<ConnectionSocketFactory> socketFactoryRegistry;
+    private final boolean isMtls;
+
+    public SocketFactoryRegistryHandler(MtlsProvider mtlsProvider)
+        throws GeneralSecurityException, IOException {
+      KeyStore mtlsKeyStore = null;
+      String mtlsKeyStorePassword = null;
+      if (mtlsProvider.useMtlsClientCertificate()) {
+        mtlsKeyStore = mtlsProvider.getKeyStore();
+        mtlsKeyStorePassword = mtlsProvider.getKeyStorePassword();
+      }
+
+      // Use the included trust store
+      KeyStore trustStore = GoogleUtils.getCertificateTrustStore();
+      SSLContext sslContext = SslUtils.getTlsSslContext();
+
+      if (mtlsKeyStore != null && mtlsKeyStorePassword != null) {
+        this.isMtls = true;
+        SslUtils.initSslContext(
+            sslContext,
+            trustStore,
+            SslUtils.getPkixTrustManagerFactory(),
+            mtlsKeyStore,
+            mtlsKeyStorePassword,
+            SslUtils.getDefaultKeyManagerFactory());
+      } else {
+        this.isMtls = false;
+        SslUtils.initSslContext(sslContext, trustStore, SslUtils.getPkixTrustManagerFactory());
+      }
+      LayeredConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
+
+      this.socketFactoryRegistry =
+          RegistryBuilder.<ConnectionSocketFactory>create()
+              .register("http", PlainConnectionSocketFactory.getSocketFactory())
+              .register("https", socketFactory)
+              .build();
+    }
+
+    public Registry<ConnectionSocketFactory> getSocketFactoryRegistry() {
+      return this.socketFactoryRegistry;
+    }
+
+    public boolean isMtls() {
+      return this.isMtls;
+    }
+  }
+
+  private GoogleApache5HttpTransport() {}
+}
diff --git a/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/package-info.java b/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/package-info.java
new file mode 100644
index 00000000..f4a1e913
--- /dev/null
+++ b/google-api-client-apache-v5/src/main/java/com/google/api/client/googleapis/apache/v5/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024 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
+ *
+ * http://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.
+ */
+
+/**
+ * Google APIs support based on the Apache HTTP Client v5.
+ *
+ * @since 2.6.1
+ */
+package com.google.api.client.googleapis.apache.v5;
diff --git a/google-api-client/pom.xml b/google-api-client/pom.xml
index 8d73dbad..d42452c6 100644
--- a/google-api-client/pom.xml
+++ b/google-api-client/pom.xml
@@ -87,6 +87,18 @@
               <goal>jar</goal>
             </goals>
           </execution>
+          <execution>
+            <id>Jar Tests Package</id>
+            <phase>package</phase>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+            <configuration>
+              <includes>
+                <include>**/Mtls/**</include>
+              </includes>
+            </configuration>
+          </execution>
         </executions>
       </plugin>
       <plugin>
diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/mtls/MtlsProvider.java b/google-api-client/src/main/java/com/google/api/client/googleapis/mtls/MtlsProvider.java
index cb0813b4..abec44b7 100644
--- a/google-api-client/src/main/java/com/google/api/client/googleapis/mtls/MtlsProvider.java
+++ b/google-api-client/src/main/java/com/google/api/client/googleapis/mtls/MtlsProvider.java
@@ -22,7 +22,8 @@ import java.security.KeyStore;
 /**
  * {@link Beta} <br>
  * Provider interface for mutual TLS. It is used in {@link
- * GoogleApacheHttpTransport#newTrustedTransport(MtlsProvider)} and {@link
+ * GoogleApacheHttpTransport#newTrustedTransport(MtlsProvider)}, {@link
+ * GoogleApache5HttpTransport#newTrustedTransport(MtlsProvider)} and {@link
  * GoogleNetHttpTransport#newTrustedTransport(MtlsProvider)} to configure the mutual TLS in the
  * transport.
  *
diff --git a/pom.xml b/pom.xml
index 1d332f0f..5fa6a62d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,6 +80,7 @@
     <module>google-api-client-jackson2</module>
     <module>google-api-client-protobuf</module>
     <module>google-api-client-xml</module>
+    <module>google-api-client-apache-v5</module>
   </modules>
 
   <pluginRepositories>
@@ -241,6 +242,21 @@
         <version>${gson.version}</version>
         <scope>test</scope>
       </dependency>
+      <dependency>
+        <groupId>org.apache.httpcomponents.client5</groupId>
+        <artifactId>httpclient5</artifactId>
+        <version>${project.httpclient5.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.httpcomponents.core5</groupId>
+        <artifactId>httpcore5</artifactId>
+        <version>${project.httpcore5.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.google.http-client</groupId>
+        <artifactId>google-http-client-apache-v5</artifactId>
+        <version>${project.http.version}</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
@@ -513,9 +529,11 @@
   </build>
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <project.http.version>1.44.2</project.http.version>
+    <project.http.version>1.45.0</project.http.version>
     <project.httpcore.version>4.4.16</project.httpcore.version>
     <project.httpclient.version>4.5.14</project.httpclient.version>
+    <project.httpcore5.version>5.2.4</project.httpcore5.version>
+    <project.httpclient5.version>5.3.1</project.httpclient5.version>
     <project.commons-codec.version>1.17.0</project.commons-codec.version>
     <project.oauth.version>1.36.0</project.oauth.version>
     <project.auth.version>1.23.0</project.auth.version>


Test patch:
diff --git a/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransportTest.java b/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransportTest.java
new file mode 100644
index 00000000..07728325
--- /dev/null
+++ b/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/GoogleApache5HttpTransportTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 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
+ *
+ * http://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.api.client.googleapis.apache.v5;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.api.client.googleapis.mtls.MtlsProvider;
+import com.google.api.client.googleapis.mtls.MtlsTransportBaseTest;
+import com.google.api.client.http.HttpTransport;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import org.junit.Test;
+
+public class GoogleApache5HttpTransportTest extends MtlsTransportBaseTest {
+  @Override
+  protected HttpTransport buildTrustedTransport(MtlsProvider mtlsProvider)
+      throws GeneralSecurityException, IOException {
+    return GoogleApache5HttpTransport.newTrustedTransport(mtlsProvider);
+  }
+
+  @Test
+  public void socketFactoryRegistryHandlerTest() throws GeneralSecurityException, IOException {
+    MtlsProvider mtlsProvider = new TestMtlsProvider(true, createTestMtlsKeyStore(), "", false);
+    GoogleApache5HttpTransport.SocketFactoryRegistryHandler handler =
+        new GoogleApache5HttpTransport.SocketFactoryRegistryHandler(mtlsProvider);
+    assertNotNull(handler.getSocketFactoryRegistry().lookup("http"));
+    assertNotNull(handler.getSocketFactoryRegistry().lookup("https"));
+    assertTrue(handler.isMtls());
+  }
+}
diff --git a/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/ITGoogleApache5HttpTransportTest.java b/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/ITGoogleApache5HttpTransportTest.java
new file mode 100644
index 00000000..f8e9cbed
--- /dev/null
+++ b/google-api-client-apache-v5/src/test/java/com/google/api/client/googleapis/apache/v5/ITGoogleApache5HttpTransportTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2024 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
+ *
+ * http://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.api.client.googleapis.apache.v5;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import com.google.api.client.http.apache.v5.Apache5HttpTransport;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import javax.net.ssl.SSLHandshakeException;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.junit.Test;
+
+public class ITGoogleApache5HttpTransportTest {
+
+  @Test
+  public void testHttpRequestFailsWhenMakingRequestToSiteWithoutGoogleCerts()
+      throws GeneralSecurityException, IOException {
+    Apache5HttpTransport apache5HttpTransport = GoogleApache5HttpTransport.newTrustedTransport();
+    HttpGet httpGet = new HttpGet("https://maven.com/");
+    Exception exception = null;
+    try {
+      apache5HttpTransport
+          .getHttpClient()
+          .execute(
+              httpGet,
+              new HttpClientResponseHandler<Void>() {
+                @Override
+                public Void handleResponse(ClassicHttpResponse response) {
+                  fail("Should not have been able to complete SSL request on non google site.");
+                  return null;
+                }
+              });
+      fail("Expected SSLHandshakeException was not thrown");
+    } catch (SSLHandshakeException e) {
+      exception = e;
+    }
+
+    assertNotNull(exception);
+    assertEquals(exception.getClass(), SSLHandshakeException.class);
+  }
+
+  @Test
+  public void testHttpRequestPassesWhenMakingRequestToGoogleSite() throws Exception {
+    Apache5HttpTransport apache5HttpTransport = GoogleApache5HttpTransport.newTrustedTransport();
+    HttpGet httpGet = new HttpGet("https://www.google.com/");
+
+    apache5HttpTransport
+        .getHttpClient()
+        .execute(
+            httpGet,
+            new HttpClientResponseHandler<Void>() {
+              @Override
+              public Void handleResponse(ClassicHttpResponse response) {
+                assertEquals(200, response.getCode());
+                return null;
+              }
+            });
+  }
+}
diff --git a/google-api-client/src/test/java/com/google/api/client/googleapis/mtls/MtlsTransportBaseTest.java b/google-api-client/src/test/java/com/google/api/client/googleapis/mtls/MtlsTransportBaseTest.java
index 096ff4ab..87b44fdf 100644
--- a/google-api-client/src/test/java/com/google/api/client/googleapis/mtls/MtlsTransportBaseTest.java
+++ b/google-api-client/src/test/java/com/google/api/client/googleapis/mtls/MtlsTransportBaseTest.java
@@ -35,11 +35,11 @@ public abstract class MtlsTransportBaseTest {
     return SecurityUtils.createMtlsKeyStore(certAndKey);
   }
 
-  protected static class TestMtlsProvider implements MtlsProvider {
-    private boolean useClientCertificate;
-    private KeyStore keyStore;
-    private String keyStorePassword;
-    private boolean throwExceptionForGetKeyStore;
+  public static class TestMtlsProvider implements MtlsProvider {
+    private final boolean useClientCertificate;
+    private final KeyStore keyStore;
+    private final String keyStorePassword;
+    private final boolean throwExceptionForGetKeyStore;
 
     public TestMtlsProvider(
         boolean useClientCertificate,