[java-shib-shared] branch main updated: JSSH-16: Update to Apache HttpClient 5.x
Brent Putman
putmanb at georgetown.edu
Tue Feb 21 19:31:04 UTC 2023
This is an automated email from the git hooks/post-receive script.
putmanb pushed a commit to branch main
in repository java-shib-shared.
View the commit online:
http://git.shibboleth.net/view/?p=java-shib-shared.git;a=commit;h=0c2baf83366be65ce07d21240dd3b8dc63dfe01e
The following commit(s) were added to refs/heads/main by this push:
new 0c2baf83 JSSH-16: Update to Apache HttpClient 5.x
0c2baf83 is described below
commit 0c2baf83366be65ce07d21240dd3b8dc63dfe01e
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Wed Oct 12 21:46:28 2022 -0400
JSSH-16: Update to Apache HttpClient 5.x
Initial refactor.
---
shib-networking-spring/pom.xml | 12 +-
.../factory/FileCachingHttpClientFactoryBean.java | 2 +-
.../httpclient/factory/HttpClientFactoryBean.java | 2 +-
.../InMemoryCachingHttpClientFactoryBean.java | 2 +-
.../resource/FileBackedHTTPResource.java | 8 +-
.../spring/httpclient/resource/HTTPResource.java | 44 +-
.../resource/ConditionalResourceTest.java | 14 +-
.../resource/FileBackedHTTPResourceTest.java | 2 +-
.../httpclient/resource/HTTPResourceTest.java | 22 +-
.../httpclient/resource/TestHTTPResource.java | 6 +-
shib-networking/pom.xml | 12 +-
.../shared/httpclient/AbstractHttpClient.java | 181 +++++++
.../httpclient/ContextHandlingHttpClient.java | 75 ++-
.../httpclient/FileCachingHttpClientBuilder.java | 62 +--
.../shared/httpclient/HttpClientBuilder.java | 602 +++++++++++++--------
.../httpclient/HttpClientContextHandler.java | 8 +-
.../shared/httpclient/HttpClientSupport.java | 24 +-
.../shared/httpclient/IdleConnectionSweeper.java | 131 -----
.../InMemoryCachingHttpClientBuilder.java | 10 +-
.../httpclient/LocalAddressProxyRoutePlanner.java | 58 ++
.../httpclient/LocalAddressRoutePlanner.java | 56 ++
.../httpclient/LocalAddressSystemRoutePlanner.java | 58 ++
.../shared/httpclient/RequestConnectionClose.java | 42 +-
.../shared/httpclient/TLSSocketFactory.java | 25 +-
.../java/support/httpclient/HttpClientSupport.java | 9 +-
.../httpclient/ContextHandlingHttpClientTest.java | 232 ++++----
.../FileCachingHttpClientBuilderTest.java | 2 +-
.../shared/httpclient/HttpClientBuilderTest.java | 10 +-
.../shared/httpclient/HttpClientSupportTest.java | 8 +-
.../httpclient/IdleConectionSweeperTest.java | 101 ----
.../InMemoryCachingHttpClientBuilderTest.java | 2 +-
31 files changed, 1043 insertions(+), 779 deletions(-)
diff --git a/shib-networking-spring/pom.xml b/shib-networking-spring/pom.xml
index a0d269e6..10c87792 100644
--- a/shib-networking-spring/pom.xml
+++ b/shib-networking-spring/pom.xml
@@ -38,16 +38,16 @@
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpcore</artifactId>
+ <groupId>${httpclient.httpcore.groupId}</groupId>
+ <artifactId>${httpclient.httpcore.artifactId}</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
+ <groupId>${httpclient.groupId}</groupId>
+ <artifactId>${httpclient.artifactId}</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient-cache</artifactId>
+ <groupId>${httpclient.groupId}</groupId>
+ <artifactId>${httpclient.cache.artifactId}</artifactId>
</dependency>
<dependency>
diff --git a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/FileCachingHttpClientFactoryBean.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/FileCachingHttpClientFactoryBean.java
index c74705f0..6dca47dd 100644
--- a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/FileCachingHttpClientFactoryBean.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/FileCachingHttpClientFactoryBean.java
@@ -19,7 +19,7 @@ package net.shibboleth.shared.spring.httpclient.factory;
import javax.annotation.Nullable;
-import org.apache.http.client.HttpClient;
+import org.apache.hc.client5.http.classic.HttpClient;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
diff --git a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/HttpClientFactoryBean.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/HttpClientFactoryBean.java
index aab7794f..ca16c281 100644
--- a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/HttpClientFactoryBean.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/HttpClientFactoryBean.java
@@ -19,7 +19,7 @@ package net.shibboleth.shared.spring.httpclient.factory;
import javax.annotation.Nullable;
-import org.apache.http.client.HttpClient;
+import org.apache.hc.client5.http.classic.HttpClient;
import org.springframework.beans.factory.FactoryBean;
import net.shibboleth.shared.httpclient.HttpClientBuilder;
diff --git a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/InMemoryCachingHttpClientFactoryBean.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/InMemoryCachingHttpClientFactoryBean.java
index 357395e0..1ff55f7e 100644
--- a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/InMemoryCachingHttpClientFactoryBean.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/factory/InMemoryCachingHttpClientFactoryBean.java
@@ -19,7 +19,7 @@ package net.shibboleth.shared.spring.httpclient.factory;
import javax.annotation.Nullable;
-import org.apache.http.client.HttpClient;
+import org.apache.hc.client5.http.classic.HttpClient;
import org.springframework.beans.factory.FactoryBean;
import net.shibboleth.shared.httpclient.InMemoryCachingHttpClientBuilder;
diff --git a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/resource/FileBackedHTTPResource.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/resource/FileBackedHTTPResource.java
index 024f9ad5..bbb605e8 100644
--- a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/resource/FileBackedHTTPResource.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/resource/FileBackedHTTPResource.java
@@ -31,9 +31,9 @@ import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.HttpClient;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpStatus;
import org.slf4j.Logger;
import org.springframework.core.io.FileSystemResource;
@@ -141,7 +141,7 @@ public class FileBackedHTTPResource extends HTTPResource {
log.info("{}: Could not reach URL, trying file", getDescription(), e);
return backingResource.exists();
}
- final int httpStatusCode = response.getStatusLine().getStatusCode();
+ final int httpStatusCode = response.getCode();
if (httpStatusCode == HttpStatus.SC_OK) {
return true;
diff --git a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/resource/HTTPResource.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/resource/HTTPResource.java
index 98890fe9..7f99c1a5 100644
--- a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/resource/HTTPResource.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/httpclient/resource/HTTPResource.java
@@ -28,19 +28,19 @@ import java.net.URL;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.apache.http.Header;
-import org.apache.http.HttpHeaders;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.cache.CacheResponseStatus;
-import org.apache.http.client.cache.HttpCacheContext;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.client.utils.DateUtils;
-import org.apache.http.util.EntityUtils;
+import org.apache.hc.client5.http.cache.CacheResponseStatus;
+import org.apache.hc.client5.http.cache.HttpCacheContext;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.client5.http.utils.DateUtils;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.BeanNameAware;
@@ -171,7 +171,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
}
log.debug("Attempting to get data from remote resource '{}'", resourceURL);
- final HttpResponse response = httpClient.execute(httpGet, context);
+ final ClassicHttpResponse response = httpClient.executeOpen(null, httpGet, context);
if (contextHandler != null) {
log.debug("Invoking HttpClientContextHandler after execution");
@@ -179,7 +179,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
}
reportCachingStatus(context);
- final int httpStatusCode = response.getStatusLine().getStatusCode();
+ final int httpStatusCode = response.getCode();
if (httpStatusCode != HttpStatus.SC_OK) {
final String errMsg =
@@ -212,7 +212,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
} catch (final IOException e) {
return false;
}
- final int httpStatusCode = response.getStatusLine().getStatusCode();
+ final int httpStatusCode = response.getCode();
return httpStatusCode == HttpStatus.SC_OK;
}
@@ -258,7 +258,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
protected HttpResponse getResourceHeaders() throws IOException {
final HttpUriRequest httpRequest = new HttpGet(resourceURL.toExternalForm());
- HttpResponse httpResponse = null;
+ ClassicHttpResponse httpResponse = null;
try {
final HttpCacheContext context = buildHttpClientContext();
@@ -269,7 +269,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
contextHandler.invokeBefore(context, httpRequest);
}
- httpResponse = httpClient.execute(httpRequest, context);
+ httpResponse = httpClient.executeOpen(null, httpRequest, context);
if (contextHandler != null) {
log.debug("Invoking HttpClientContextHandler after execution");
@@ -298,7 +298,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
log.debug("Attempting to fetch remote resource as '{}'", resourceURL);
response = getResourceHeaders();
- final int httpStatusCode = response.getStatusLine().getStatusCode();
+ final int httpStatusCode = response.getCode();
if (httpStatusCode != HttpStatus.SC_OK) {
final String errMsg =
@@ -331,7 +331,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
@Override public long lastModified() throws IOException {
final String response = getResponseHeader(HttpHeaders.LAST_MODIFIED);
if (null != response) {
- return DateUtils.parseDate(response).getTime();
+ return DateUtils.parseStandardDate(response).toEpochMilli();
}
final String errMsg = "Response from remote resource " + resourceURL.toString() +
" did not contain a Last-Modified header";
@@ -403,7 +403,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
private static class ConnectionClosingInputStream extends InputStream {
/** HTTP response that is being wrapped. */
- private final HttpResponse response;
+ private final ClassicHttpResponse response;
/** Stream owned by the given HTTP response. */
private final InputStream stream;
@@ -414,7 +414,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
* @param httpResponse HTTP method that was invoked
* @throws IOException if there is a problem getting the entity content input stream from the response
*/
- public ConnectionClosingInputStream(@Nonnull final HttpResponse httpResponse) throws IOException {
+ public ConnectionClosingInputStream(@Nonnull final ClassicHttpResponse httpResponse) throws IOException {
response = httpResponse;
stream = response.getEntity().getContent();
}
diff --git a/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/ConditionalResourceTest.java b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/ConditionalResourceTest.java
index 1e672668..ac696387 100644
--- a/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/ConditionalResourceTest.java
+++ b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/ConditionalResourceTest.java
@@ -26,9 +26,9 @@ import net.shibboleth.shared.spring.custom.SchemaTypeAwareXMLBeanDefinitionReade
import net.shibboleth.shared.spring.resource.ConditionalResource;
import net.shibboleth.shared.spring.resource.ConditionalResourceResolver;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ClassicHttpRequest;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
@@ -78,10 +78,10 @@ public class ConditionalResourceTest {
@Test public void contextHandlerFailBeforeTest() throws IOException, ComponentInitializationException {
final HTTPResource existsHTTPResource = new HTTPResource(client, existsURL);
existsHTTPResource.setHttpClientContextHandler(new HttpClientContextHandler() {
- public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeBefore(HttpClientContext context, ClassicHttpRequest request) throws IOException {
throw new IOException("Fail");
}
- public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeAfter(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
});
@@ -95,9 +95,9 @@ public class ConditionalResourceTest {
@Test public void contextHandlerFailAfterTest() throws IOException, ComponentInitializationException {
final HTTPResource existsHTTPResource = new HTTPResource(client, existsURL);
existsHTTPResource.setHttpClientContextHandler(new HttpClientContextHandler() {
- public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeBefore(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
- public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeAfter(HttpClientContext context, ClassicHttpRequest request) throws IOException {
throw new IOException("Fail");
}
});
diff --git a/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/FileBackedHTTPResourceTest.java b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/FileBackedHTTPResourceTest.java
index 27c8a956..a9ad1160 100644
--- a/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/FileBackedHTTPResourceTest.java
+++ b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/FileBackedHTTPResourceTest.java
@@ -24,7 +24,7 @@ import net.shibboleth.shared.httpclient.HttpClientBuilder;
import net.shibboleth.shared.spring.context.FilesystemGenericApplicationContext;
import net.shibboleth.shared.spring.custom.SchemaTypeAwareXMLBeanDefinitionReader;
-import org.apache.http.client.HttpClient;
+import org.apache.hc.client5.http.classic.HttpClient;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.MutablePropertySources;
diff --git a/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/HTTPResourceTest.java b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/HTTPResourceTest.java
index 77c01f5e..4c4731c9 100644
--- a/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/HTTPResourceTest.java
+++ b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/HTTPResourceTest.java
@@ -24,11 +24,11 @@ import java.nio.file.Path;
import java.time.Instant;
import java.util.Collection;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.cache.CacheResponseStatus;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.cache.CacheResponseStatus;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ClassicHttpRequest;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
@@ -74,9 +74,9 @@ public class HTTPResourceTest {
@Test public void contextHandlerNoopTest() throws IOException {
final HTTPResource existsResource = new HTTPResource(client, existsURL);
existsResource.setHttpClientContextHandler(new HttpClientContextHandler() {
- public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeBefore(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
- public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeAfter(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
});
@@ -86,10 +86,10 @@ public class HTTPResourceTest {
@Test public void contextHandlerFailBeforeTest() throws IOException {
final HTTPResource existsResource = new HTTPResource(client, existsURL);
existsResource.setHttpClientContextHandler(new HttpClientContextHandler() {
- public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeBefore(HttpClientContext context, ClassicHttpRequest request) throws IOException {
throw new IOException("Fail");
}
- public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeAfter(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
});
@@ -99,9 +99,9 @@ public class HTTPResourceTest {
@Test public void contextHandlerFailAfterTest() throws IOException {
final HTTPResource existsResource = new HTTPResource(client, existsURL);
existsResource.setHttpClientContextHandler(new HttpClientContextHandler() {
- public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeBefore(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
- public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeAfter(HttpClientContext context, ClassicHttpRequest request) throws IOException {
throw new IOException("Fail");
}
});
diff --git a/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/TestHTTPResource.java b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/TestHTTPResource.java
index 75a3ca13..04a17a58 100644
--- a/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/TestHTTPResource.java
+++ b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/httpclient/resource/TestHTTPResource.java
@@ -19,9 +19,9 @@ package net.shibboleth.shared.spring.httpclient.resource;
import java.io.IOException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.cache.CacheResponseStatus;
-import org.apache.http.client.cache.HttpCacheContext;
+import org.apache.hc.client5.http.cache.CacheResponseStatus;
+import org.apache.hc.client5.http.cache.HttpCacheContext;
+import org.apache.hc.client5.http.classic.HttpClient;
class TestHTTPResource extends HTTPResource {
diff --git a/shib-networking/pom.xml b/shib-networking/pom.xml
index 7285fb35..f204d1cf 100644
--- a/shib-networking/pom.xml
+++ b/shib-networking/pom.xml
@@ -33,16 +33,16 @@
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
+ <groupId>${httpclient.groupId}</groupId>
+ <artifactId>${httpclient.artifactId}</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient-cache</artifactId>
+ <groupId>${httpclient.groupId}</groupId>
+ <artifactId>${httpclient.cache.artifactId}</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpcore</artifactId>
+ <groupId>${httpclient.httpcore.groupId}</groupId>
+ <artifactId>${httpclient.httpcore.artifactId}</artifactId>
</dependency>
<!-- Provided Dependencies -->
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/AbstractHttpClient.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/AbstractHttpClient.java
new file mode 100644
index 00000000..31a54cc6
--- /dev/null
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/AbstractHttpClient.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.shared.httpclient;
+
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.routing.RoutingSupport;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.io.ModalCloseable;
+import org.slf4j.Logger;
+
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * Basic abstract implementation of {@link HttpClient}.
+ *
+ * Based on {@link org.apache.hc.client5.http.impl.classic.CloseableHttpClient}.
+ */
+public abstract class AbstractHttpClient implements HttpClient, ModalCloseable {
+
+ /** Logger. */
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractHttpClient.class);
+
+ /**
+ * Execute the HTTP request.
+ *
+ * @param target the target host for the request, may be {@code null}
+ * @param request the request to execute
+ * @param context the context to use for the execution, or {@code null} to use the default context
+ * @return the response to the request
+ * @throws IOException in case of a problem or the connection was aborted
+ */
+ protected abstract ClassicHttpResponse doExecute(
+ @Nullable final HttpHost target,
+ @Nonnull final ClassicHttpRequest request,
+ @Nullable final HttpContext context) throws IOException;
+
+ /**
+ * Determine the {@link HttpHost} instance based on the specified request.
+ *
+ * @param request the request being executed
+ * @return the {@link HttpHost} instance reflecting the specified request
+ * @throws ClientProtocolException if target host can not be determined
+ */
+ private static HttpHost determineTarget(@Nullable final ClassicHttpRequest request) throws ClientProtocolException {
+ try {
+ return RoutingSupport.determineHost(request);
+ } catch (final HttpException ex) {
+ throw new ClientProtocolException(ex);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ClassicHttpResponse execute(
+ @Nullable final HttpHost target,
+ @Nonnull final ClassicHttpRequest request,
+ @Nullable final HttpContext context) throws IOException {
+ Constraint.isNotNull(request, "HTTP request");
+ return doExecute(target, request, context);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ClassicHttpResponse execute(
+ @Nonnull ClassicHttpRequest request,
+ @Nullable final HttpContext context) throws IOException {
+ Constraint.isNotNull(request, "HTTP request");
+ return doExecute(determineTarget(request), request, context);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ClassicHttpResponse execute(
+ @Nonnull final ClassicHttpRequest request) throws IOException {
+ Constraint.isNotNull(request, "HTTP request");
+ return doExecute(determineTarget(request), request, null);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ClassicHttpResponse execute(
+ @Nullable final HttpHost target,
+ @Nonnull final ClassicHttpRequest request) throws IOException {
+ Constraint.isNotNull(request, "HTTP request");
+ return doExecute(target, request, null);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public <T> T execute(
+ @Nonnull final ClassicHttpRequest request,
+ @Nonnull final HttpClientResponseHandler<? extends T> responseHandler) throws IOException {
+ Constraint.isNotNull(request, "HTTP request");
+ Constraint.isNotNull(responseHandler, "HTTP response handler");
+ return execute(request, null, responseHandler);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public <T> T execute(
+ @Nonnull final ClassicHttpRequest request,
+ @Nullable final HttpContext context,
+ @Nonnull final HttpClientResponseHandler<? extends T> responseHandler) throws IOException {
+ Constraint.isNotNull(request, "HTTP request");
+ Constraint.isNotNull(responseHandler, "HTTP response handler");
+ final HttpHost target = determineTarget(request);
+ return execute(target, request, context, responseHandler);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public <T> T execute(
+ @Nullable final HttpHost target,
+ @Nonnull ClassicHttpRequest request,
+ @Nonnull final HttpClientResponseHandler<? extends T> responseHandler) throws IOException {
+ Constraint.isNotNull(request, "HTTP request");
+ Constraint.isNotNull(responseHandler, "HTTP response handler");
+ return execute(target, request, null, responseHandler);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public <T> T execute(
+ @Nullable final HttpHost target,
+ @Nonnull final ClassicHttpRequest request,
+ @Nullable final HttpContext context,
+ @Nonnull final HttpClientResponseHandler<? extends T> responseHandler) throws IOException {
+ Constraint.isNotNull(request, "HTTP request");
+ Constraint.isNotNull(responseHandler, "HTTP response handler");
+
+ try (final ClassicHttpResponse response = doExecute(target, request, context)) {
+ try {
+ final T result = responseHandler.handleResponse(response);
+ final HttpEntity entity = response.getEntity();
+ EntityUtils.consume(entity);
+ return result;
+ } catch (final HttpException t) {
+ // Try to salvage the underlying connection in case of a protocol exception
+ final HttpEntity entity = response.getEntity();
+ try {
+ EntityUtils.consume(entity);
+ } catch (final Exception t2) {
+ // Log this exception. The original exception is more
+ // important and will be thrown to the caller.
+ LOG.warn("Error consuming content after an exception.", t2);
+ }
+ throw new ClientProtocolException(t);
+ }
+ }
+ }
+
+}
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/ContextHandlingHttpClient.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/ContextHandlingHttpClient.java
index f4088842..f0eea8f5 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/ContextHandlingHttpClient.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/ContextHandlingHttpClient.java
@@ -17,22 +17,23 @@
package net.shibboleth.shared.httpclient;
+import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpRequestWrapper;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.HttpContext;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.protocol.BasicHttpContext;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.io.ModalCloseable;
import org.slf4j.Logger;
import com.google.common.collect.Lists;
@@ -65,13 +66,13 @@ import net.shibboleth.shared.primitive.LoggerFactory;
* <li>Static handlers supplied via the constructor, in reverse list order</li>
* </ol>
*/
-class ContextHandlingHttpClient extends CloseableHttpClient {
+class ContextHandlingHttpClient extends AbstractHttpClient {
/** Logger. */
private Logger log = LoggerFactory.getLogger(ContextHandlingHttpClient.class);
/** The wrapped client instance. */
- @Nonnull private CloseableHttpClient httpClient;
+ @Nonnull private HttpClient httpClient;
/** Optional list of static handlers supplied to this class instance. */
@Nonnull private List<HttpClientContextHandler> handlers;
@@ -81,7 +82,7 @@ class ContextHandlingHttpClient extends CloseableHttpClient {
*
* @param client the wrapped client instance
*/
- public ContextHandlingHttpClient(@Nonnull final CloseableHttpClient client) {
+ public ContextHandlingHttpClient(@Nonnull final HttpClient client) {
this(client, CollectionSupport.emptyList());
}
@@ -91,52 +92,50 @@ class ContextHandlingHttpClient extends CloseableHttpClient {
* @param client the wrapped client instance
* @param staticHandlers the list of static handlers
*/
- public ContextHandlingHttpClient(@Nonnull final CloseableHttpClient client,
+ public ContextHandlingHttpClient(@Nonnull final HttpClient client,
@Nonnull final List<HttpClientContextHandler> staticHandlers) {
httpClient = Constraint.isNotNull(client, "HttpClient was null");
handlers = Constraint.isNotNull(staticHandlers, "staticHandlers was null");
}
-
- /** {@inheritDoc} */
- @Deprecated
- @Override
- public org.apache.http.params.HttpParams getParams() {
- return httpClient.getParams();
- }
-
+
/** {@inheritDoc} */
- @Deprecated
@Override
- public org.apache.http.conn.ClientConnectionManager getConnectionManager() {
- return httpClient.getConnectionManager();
+ public void close() throws IOException {
+ if (Closeable.class.isInstance(httpClient)) {
+ Closeable.class.cast(httpClient).close();
+ }
}
/** {@inheritDoc} */
@Override
- public void close() throws IOException {
- httpClient.close();
+ public void close(final CloseMode closeMode) {
+ if (ModalCloseable.class.isInstance(httpClient)) {
+ ModalCloseable.class.cast(httpClient).close(closeMode);
+ }
}
/** {@inheritDoc} */
@Override
- protected CloseableHttpResponse doExecute(final HttpHost target, final HttpRequest request,
- final HttpContext context) throws IOException, ClientProtocolException {
+ protected ClassicHttpResponse doExecute(@Nullable final HttpHost target, @Nonnull ClassicHttpRequest request,
+ @Nullable final HttpContext context) throws IOException {
Throwable error = null;
final HttpClientContext clientContext =
HttpClientContext.adapt(context != null ? context : new BasicHttpContext());
- final HttpUriRequest uriRequest = HttpUriRequest.class.isInstance(request)
- ? (HttpUriRequest)request : HttpRequestWrapper.wrap(request, target);
- assert clientContext != null && uriRequest != null;
+
+ assert clientContext != null;
+
try {
- invokeBefore(uriRequest, clientContext);
- return httpClient.execute(target, request, clientContext);
+ invokeBefore(request, clientContext);
+ // As of 5.2, using executeOpen(...) b/c all other execute(...) variants are deprecated.
+ final ClassicHttpResponse classicResponse = httpClient.executeOpen(target, request, clientContext);
+ return classicResponse;
} catch (final Throwable t) {
error = t;
throw t;
} finally {
- invokeAfter(uriRequest, clientContext, error);
+ invokeAfter(request, clientContext, error);
}
}
@@ -148,7 +147,7 @@ class ContextHandlingHttpClient extends CloseableHttpClient {
* @param context the HTTP context
* @throws IOException if any handler throws an error
*/
- private void invokeBefore(@Nonnull final HttpUriRequest request, @Nonnull final HttpClientContext context)
+ private void invokeBefore(@Nonnull final ClassicHttpRequest request, @Nonnull final HttpClientContext context)
throws IOException {
log.trace("In invokeBefore");
@@ -199,7 +198,7 @@ class ContextHandlingHttpClient extends CloseableHttpClient {
* is a type of unchecked error (RuntimeException or Error) that will be propagated out
* here as well.
*/
- private void invokeAfter(@Nonnull final HttpUriRequest request, @Nonnull final HttpClientContext context,
+ private void invokeAfter(@Nonnull final ClassicHttpRequest request, @Nonnull final HttpClientContext context,
final Throwable priorError) throws IOException {
log.trace("In invokeAfter");
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/FileCachingHttpClientBuilder.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/FileCachingHttpClientBuilder.java
index 438b3c1a..fcb25783 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/FileCachingHttpClientBuilder.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/FileCachingHttpClientBuilder.java
@@ -17,6 +17,7 @@
package net.shibboleth.shared.httpclient;
+import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
@@ -25,17 +26,17 @@ import java.util.TimerTask;
import javax.annotation.Nonnull;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.cache.CacheConfig;
-import org.apache.http.impl.client.cache.CachingHttpClientBuilder;
-import org.apache.http.impl.client.cache.FileResourceFactory;
-import org.apache.http.impl.client.cache.ManagedHttpCacheStorage;
-import org.apache.http.protocol.HttpContext;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.impl.cache.CacheConfig;
+import org.apache.hc.client5.http.impl.cache.CachingHttpClientBuilder;
+import org.apache.hc.client5.http.impl.cache.FileResourceFactory;
+import org.apache.hc.client5.http.impl.cache.ManagedHttpCacheStorage;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.io.ModalCloseable;
import org.slf4j.Logger;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
@@ -51,7 +52,7 @@ import net.shibboleth.shared.primitive.StringSupport;
import net.shibboleth.shared.primitive.TimerSupport;
/**
- * An {@link org.apache.http.client.HttpClient} builder that supports RFC 2616 caching.
+ * An {@link org.apache.hc.client5.http.classic.HttpClient} builder that supports RFC 2616 caching.
* <p>
* Cached content is written to disk. Special care should be taken so that multiple clients do not share a single cache
* directory unintentionally. This could result in sensitive data being available in ways it should not be.
@@ -251,7 +252,7 @@ public class FileCachingHttpClientBuilder extends HttpClientBuilder {
/** {@inheritDoc} */
public synchronized HttpClient buildClient() throws Exception {
- final CloseableHttpClient client = (CloseableHttpClient) super.buildClient();
+ final HttpClient client = super.buildClient();
final ManagedHttpCacheStorage tempStorage = managedStorage;
// Null this out so we don't keep a reference, inhibiting garbage collection.
assert client != null && tempStorage != null;
@@ -260,17 +261,17 @@ public class FileCachingHttpClientBuilder extends HttpClientBuilder {
}
/**
- * Class which wraps a caching instance of {@link CloseableHttpClient} and its associated
+ * Class which wraps a caching instance of {@link HttpClient} and its associated
* {@link ManagedHttpCacheStorage}, and manages the scheduled maintenance and lifecycle of the latter.
*/
- private static class StorageManagingHttpClient extends CloseableHttpClient
+ private static class StorageManagingHttpClient extends AbstractHttpClient
implements InitializableComponent, DestructableComponent {
/** Logger. */
private Logger log = LoggerFactory.getLogger(StorageManagingHttpClient.class);
/** The wrapped HttpClient instance. */
- private CloseableHttpClient httpClient;
+ private HttpClient httpClient;
/** The cache storage instance to manage. */
private ManagedHttpCacheStorage storage;
@@ -297,7 +298,7 @@ public class FileCachingHttpClientBuilder extends HttpClientBuilder {
* @param managedStorage the managed cache storage instance
* @param taskInterval the interval at which storage maintenance should run
*/
- public StorageManagingHttpClient(@Nonnull final CloseableHttpClient wrappedClient,
+ public StorageManagingHttpClient(@Nonnull final HttpClient wrappedClient,
@Nonnull final ManagedHttpCacheStorage managedStorage, final long taskInterval) {
httpClient = Constraint.isNotNull(wrappedClient, "HttpClient was null");
storage = Constraint.isNotNull(managedStorage, "ManagedHttpCacheStorage was null");
@@ -321,34 +322,29 @@ public class FileCachingHttpClientBuilder extends HttpClientBuilder {
/** {@inheritDoc} */
- protected CloseableHttpResponse doExecute(final HttpHost target, final HttpRequest request,
+ protected ClassicHttpResponse doExecute(final HttpHost target, final ClassicHttpRequest request,
final HttpContext context)
- throws IOException, ClientProtocolException {
+ throws IOException {
throwComponentStateExceptions();
- return httpClient.execute(target, request, context);
+ return httpClient.executeOpen(target, request, context);
}
/** {@inheritDoc} */
@Override
- @Deprecated
- public org.apache.http.params.HttpParams getParams() {
- throwComponentStateExceptions();
- return httpClient.getParams();
- }
-
- /** {@inheritDoc} */
- @Override
- @Deprecated
- public org.apache.http.conn.ClientConnectionManager getConnectionManager() {
+ public void close() throws IOException {
throwComponentStateExceptions();
- return httpClient.getConnectionManager();
+ if (Closeable.class.isInstance(httpClient)) {
+ Closeable.class.cast(httpClient).close();
+ }
}
/** {@inheritDoc} */
@Override
- public void close() throws IOException {
+ public void close(CloseMode closeMode) {
throwComponentStateExceptions();
- httpClient.close();
+ if (ModalCloseable.class.isInstance(httpClient)) {
+ ModalCloseable.class.cast(httpClient).close(closeMode);
+ }
}
/** {@inheritDoc} */
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientBuilder.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientBuilder.java
index 942c7bda..255a6c61 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientBuilder.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientBuilder.java
@@ -18,27 +18,39 @@
package net.shibboleth.shared.httpclient;
import java.net.InetAddress;
+import java.net.ProxySelector;
import java.net.UnknownHostException;
+import java.nio.charset.Charset;
import java.time.Duration;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpResponseInterceptor;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.HttpRequestRetryHandler;
-import org.apache.http.client.ServiceUnavailableRetryStrategy;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.config.ConnectionConfig;
-import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
-import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.util.CharsetUtils;
+import org.apache.hc.client5.http.HttpRequestRetryStrategy;
+import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
+import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
+import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
+import org.apache.hc.client5.http.io.HttpClientConnectionManager;
+import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
+import org.apache.hc.client5.http.routing.HttpRoutePlanner;
+import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpRequestInterceptor;
+import org.apache.hc.core5.http.HttpResponseInterceptor;
+import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.config.Http1Config;
+import org.apache.hc.core5.http.io.HttpConnectionFactory;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
import net.shibboleth.shared.annotation.constraint.NotLive;
@@ -54,88 +66,30 @@ import net.shibboleth.shared.primitive.StringSupport;
*
* <p>
* When using the single-arg constructor variant to wrap an existing instance of
- * {@link org.apache.http.impl.client.HttpClientBuilder}, there are several caveats of which to be aware:
- *
- * <ul>
- *
- * <li>
- * Instances of the following which are set as the default instance on the Apache builder will be unconditionally
- * overwritten by this builder when {@link #buildClient()} is called:
- *
- * <ul>
- * <li>{@link RequestConfig}</li>
- * <li>{@link ConnectionConfig}</li>
- * </ul>
- *
- * <p>
- * This is due to the unfortunate fact that the Apache builder does not currently provide accessor methods to obtain the
- * default instances currently set on the builder. Therefore, if you need to set any default request or connection
- * config parameters which are not exposed by this builder, then you must use the Apache builder directly and may not
- * use this builder.
- * </p>
- * </li>
- *
- * <li>
- * If this builder's <code>connectionDisregardTLSCertificate</code> is set to <code>true</code>, then any value
- * previously set via the Apache builder's
- * {@link org.apache.http.impl.client.HttpClientBuilder#setSSLSocketFactory} will be
- * unconditionally overwritten.</li>
- *
- * <li>
- * If this builder is supplied with a <code>connectionProxyHost</code>, <code>connectionProxyUsername</code> and
- * <code>connectionProxyPassword</code>, then any value previously set via the Apache builder's
- * {@link org.apache.http.impl.client.HttpClientBuilder#setDefaultCredentialsProvider(CredentialsProvider)} will be
- * unconditionally overwritten.</li>
- *
- * <li>
- * Per the Apache builder's Javadoc, if a non-null instance of {@link org.apache.http.conn.HttpClientConnectionManager}
- * is set on the Apache builder via
- * {@link org.apache.http.impl.client.HttpClientBuilder#setConnectionManager},
- * this supersedes various other properties set on the Apache builder. This includes the following
- * instances/properties on the Apache builder:
- *
- * <ul>
- * <li><code>SSLSocketFactory</code> ({@link org.apache.http.conn.socket.LayeredConnectionSocketFactory})</li>
- * <li>{@link javax.net.ssl.SSLContext}</li>
- * <li>{@link javax.net.ssl.HostnameVerifier}</li>
- * <li>{@link org.apache.http.config.SocketConfig}</li>
- * <li>{@link ConnectionConfig}</li>
- * <li><code>maxConnTotal</code></li>
- * <li><code>maxConnPerRoute</code></li>
- * </ul>
+ * {@link org.apache.hc.client5.http.impl.classic.HttpClientBuilder}, there are several caveats of which to be aware:
*
* <p>
- * Similarly, the following setters on this builder will become ineffective when a non-null connection manger is set on
- * the Apache builder:
+ * Instances of the following will be unconditionally overwritten by this builder when
+ * {@link #buildClient()} is called:
* </p>
*
* <ul>
- * <li>{@link #setTLSSocketFactory(LayeredConnectionSocketFactory)}</li>
- * <li>{@link #setConnectionDisregardTLSCertificate(boolean)}</li>
- * <li>{@link #setSocketBufferSize(int)}</li>
- * <li>{@link #setHttpContentCharSet(String)}</li>
- * <li>{@link #setMaxConnectionsTotal(int)}</li>
- * <li>{@link #setMaxConnectionsPerRoute(int)}</li>
+ * <li>{@link HttpClientConnectionManager} which includes the following sub-components:</li>
+ * <ul>
+ * <li>Default {@link ConnectionConfig}</li>
+ * <li>{@link HttpConnectionFactory}</li>
+ * <li>{@link LayeredConnectionSocketFactory} used as the <code>SSLSocketFactory</code></li>
+ * </ul>
+ * <li>{@link HttpRoutePlanner}</li>
+ * <li>Default {@link RequestConfig}</li>
+ * <li>Default {@link CredentialsProvider}</li>
* </ul>
*
* <p>
- * Therefore, if you need to explicitly supply a connection manager instance to the Apache builder (for example in order
- * to be able to use {@link IdleConnectionSweeper}), then you must supply these properties or instances directly to the
- * connection manager rather than to this builder or the Apache builder.
+ * This is due to the unfortunate fact that the Apache builder does not currently provide accessor methods to obtain the
+ * default instances currently set on the builder. Therefore, if you need to set any config parameters which are not
+ * exposed by this builder, then you must use the Apache builder directly and may not use this builder.
* </p>
- * </li>
- *
- * <li>
- * Similar to the above issue, setting an explicit <code>SSLSocketFactory</code> on the Apache builder will supersede
- * the following Apache builder properties:
- *
- * <ul>
- * <li>{@link javax.net.ssl.SSLContext}</li>
- * <li>{@link javax.net.ssl.HostnameVerifier}</li>
- * </ul>
- * </li>
- *
- * </ul>
*/
public class HttpClientBuilder {
@@ -157,6 +111,9 @@ public class HttpClientBuilder {
*/
@Nonnull private Duration connectionRequestTimeout;
+ /** Determines the timeout until arrival of a response from the opposite endpoint. */
+ @Nonnull private Duration responseTimeout;
+
/**
* Max total simultaneous connections allowed by the pooling connection manager.
*/
@@ -177,10 +134,9 @@ public class HttpClientBuilder {
private boolean connectionCloseAfterResponse;
/**
- * Whether to check a connection for staleness before using. This can be an expensive operation. Default value:
- * false
+ * Sets period after inactivity after which persistent connections must be checked to ensure they are still valid.
*/
- private boolean connectionStaleCheck;
+ @Nullable private Duration validateAfterInactivity;
/** Host name of the HTTP proxy server through which connections will be made. Default value: null. */
@Nullable private String connectionProxyHost;
@@ -203,11 +159,11 @@ public class HttpClientBuilder {
/** Character set used for HTTP entity content. Default value: UTF-8 */
@Nullable private String httpContentCharSet;
- /** Handler which determines if a request should be retried after a recoverable exception during execution. */
- @Nullable private HttpRequestRetryHandler retryHandler;
-
- /** Strategy which determines if a request should be retried given the response from the target server. */
- @Nullable private ServiceUnavailableRetryStrategy serviceUnavailStrategy;
+ /** Strategy which determines whether and how a retry should be attempted. */
+ @Nullable private HttpRequestRetryStrategy retryStrategy;
+
+ /** Resolver for port based on a scheme. */
+ @Nullable private SchemePortResolver schemePortResolver;
/** Flag for disabling auth caching.*/
private boolean disableAuthCaching;
@@ -226,10 +182,19 @@ public class HttpClientBuilder {
/** Flag for disabling redirect handling.*/
private boolean disableRedirectHandling;
-
+
/** Flag for enabling use of system properties.*/
private boolean useSystemProperties;
+ /** Flag for evicting expired connections from the connection pool using a background thread. */
+ private boolean evictExpiredConnections;
+
+ /** Flag for evicting expired connections from the connection pool using a background thread. */
+ private boolean evictIdleConnections;
+
+ /** Max idle time allowed for an idle connection before it is evicted. */
+ private Duration connectionMaxIdleTime;
+
/** List of request interceptors to add first. */
@Nonnull @NonnullElements @Unmodifiable @NotLive private List<HttpRequestInterceptor> requestInterceptorsFirst;
@@ -246,11 +211,11 @@ public class HttpClientBuilder {
@Nonnull @NonnullElements @Unmodifiable @NotLive private List<HttpClientContextHandler> staticContextHandlers;
/** The Apache HttpClientBuilder 4.3+ instance over which to layer this builder. */
- private org.apache.http.impl.client.HttpClientBuilder apacheBuilder;
+ private org.apache.hc.client5.http.impl.classic.HttpClientBuilder apacheBuilder;
/** Constructor. */
public HttpClientBuilder() {
- this(org.apache.http.impl.client.HttpClientBuilder.create());
+ this(org.apache.hc.client5.http.impl.classic.HttpClientBuilder.create());
}
/**
@@ -258,7 +223,7 @@ public class HttpClientBuilder {
*
* @param builder the Apache HttpClientBuilder 4.3+ instance over which to layer this builder
*/
- public HttpClientBuilder(@Nonnull final org.apache.http.impl.client.HttpClientBuilder builder) {
+ public HttpClientBuilder(@Nonnull final org.apache.hc.client5.http.impl.classic.HttpClientBuilder builder) {
apacheBuilder = Constraint.isNotNull(builder, "Apache HttpClientBuilder may not be null");
// Defaults are duplicated to avoid static null analyzer issues.
@@ -267,11 +232,11 @@ public class HttpClientBuilder {
socketLocalAddress = null;
socketBufferSize = 8192;
socketTimeout = Duration.ofSeconds(60);
+ responseTimeout = Duration.ofNanos(60);
connectionTimeout = Duration.ofSeconds(60);
connectionRequestTimeout = Duration.ofSeconds(60);
connectionDisregardTLSCertificate = false;
connectionCloseAfterResponse = true;
- connectionStaleCheck = false;
connectionProxyHost = null;
connectionProxyPort = 8080;
connectionProxyUsername = null;
@@ -279,6 +244,21 @@ public class HttpClientBuilder {
httpFollowRedirects = true;
httpContentCharSet = "UTF-8";
userAgent = null;
+ validateAfterInactivity = null;
+ retryStrategy = null;
+ schemePortResolver = null;
+
+ disableAuthCaching = false;
+ disableAutomaticRetries = false;
+ disableConnectionState = false;
+ disableContentCompression = false;
+ disableCookieManagement = false;
+ disableRedirectHandling = false;
+ useSystemProperties = false;
+
+ evictExpiredConnections = false;
+ evictIdleConnections = false;
+ connectionMaxIdleTime = Duration.ofMinutes(30);
requestInterceptorsFirst = CollectionSupport.emptyList();
requestInterceptorsLast = CollectionSupport.emptyList();
@@ -297,11 +277,11 @@ public class HttpClientBuilder {
socketLocalAddress = null;
socketBufferSize = 8192;
socketTimeout = Duration.ofSeconds(60);
+ responseTimeout = Duration.ofNanos(60);
connectionTimeout = Duration.ofSeconds(60);
connectionRequestTimeout = Duration.ofSeconds(60);
connectionDisregardTLSCertificate = false;
connectionCloseAfterResponse = true;
- connectionStaleCheck = false;
connectionProxyHost = null;
connectionProxyPort = 8080;
connectionProxyUsername = null;
@@ -309,7 +289,22 @@ public class HttpClientBuilder {
httpFollowRedirects = true;
httpContentCharSet = "UTF-8";
userAgent = null;
+ validateAfterInactivity = null;
+ retryStrategy = null;
+ schemePortResolver = null;
+
+ disableAuthCaching = false;
+ disableAutomaticRetries = false;
+ disableConnectionState = false;
+ disableContentCompression = false;
+ disableCookieManagement = false;
+ disableRedirectHandling = false;
+ useSystemProperties = false;
+ evictExpiredConnections = false;
+ evictIdleConnections = false;
+ connectionMaxIdleTime = Duration.ofMinutes(30);
+
requestInterceptorsFirst = CollectionSupport.emptyList();
requestInterceptorsLast = CollectionSupport.emptyList();
responseInterceptorsFirst = CollectionSupport.emptyList();
@@ -382,6 +377,27 @@ public class HttpClientBuilder {
socketLocalAddress = InetAddress.getByName(Constraint.isNotNull(ipOrHost, "IP or hostname may not be null"));
}
+ /**
+ * Gets the timeout until arrival of a response from the opposite endpoint.
+ *
+ * @return timeout
+ */
+ @Nonnull public Duration getResponseTimeout() {
+ return responseTimeout;
+ }
+
+ /**
+ * Gets the timeout until arrival of a response from the opposite endpoint.
+ *
+ * @param timeout
+ */
+ public void setResponseTimeout(@Nonnull final Duration timeout) {
+ Constraint.isNotNull(timeout, "Timeout cannot be null");
+ Constraint.isLessThanOrEqual(Integer.MAX_VALUE, timeout.toMillis(), "Timeout too large");
+
+ responseTimeout = timeout;
+ }
+
/**
* Gets the maximum period inactivity between two consecutive data packets. A value of less than 1 ms
* indicates no timeout.
@@ -532,62 +548,25 @@ public class HttpClientBuilder {
public void setConnectionCloseAfterResponse(final boolean close) {
connectionCloseAfterResponse = close;
}
-
- /**
- * Gets whether reused connections are checked if they are closed before being used by the client.
- *
- * @return whether reused connections are checked if they are closed before being used by the client
- *
- * @deprecated use {@link #isConnectionStaleCheck()}
- */
- @Deprecated(forRemoval=true)
- public boolean isConnectionStalecheck() {
- return isConnectionStaleCheck();
- }
-
- /**
- * Sets whether reused connections are checked if they are closed before being used by the client. Checking can take
- * up to 30ms (per request). If checking is turned off an I/O error occurs if the connection is used request. This
- * should be enabled uncles the code using the client explicitly handles the error case and retries connection as
- * appropriate.
- *
- * @param check whether reused connections are checked if they are closed before being used by the client
- *
- * @deprecated use {@link #setConnectionStaleCheck(boolean)}
- */
- @Deprecated(forRemoval=true)
- public void setConnectionStalecheck(final boolean check) {
- setConnectionStaleCheck(check);
- }
/**
- * Gets whether reused connections are checked if they are closed before being used by the client.
- *
- * @return whether reused connections are checked if they are closed before being used by the client
- *
- * @deprecated use a custom-configured connection pool manger.
- * See {@link org.apache.http.impl.conn.PoolingHttpClientConnectionManager#setValidateAfterInactivity(int)}
+ * Gets period after inactivity after which persistent
+ * connections must be checked to ensure they are still valid.
*
+ * @return the duration value
*/
- @Deprecated(forRemoval=true)
- public boolean isConnectionStaleCheck() {
- return connectionStaleCheck;
+ @Nullable Duration getValidateAfterInactivity() {
+ return validateAfterInactivity;
}
/**
- * Sets whether reused connections are checked if they are closed before being used by the client. Checking can take
- * up to 30ms (per request). If checking is turned off an I/O error occurs if the connection is used request. This
- * should be enabled uncles the code using the client explicitly handles the error case and retries connection as
- * appropriate.
- *
- * @param check whether reused connections are checked if they are closed before being used by the client
+ * Sets period after inactivity after which persistent
+ * connections must be checked to ensure they are still valid.
*
- * @deprecated use a custom-configured connection pool manger.
- * See {@link org.apache.http.impl.conn.PoolingHttpClientConnectionManager#setValidateAfterInactivity(int)}
+ * @param duration the duration value
*/
- @Deprecated(forRemoval=true)
- public void setConnectionStaleCheck(final boolean check) {
- connectionStaleCheck = check;
+ public void setValidateAfterInactivity(@Nullable final Duration duration) {
+ validateAfterInactivity = duration;
}
/**
@@ -719,39 +698,39 @@ public class HttpClientBuilder {
}
/**
- * Get the handler which determines if a request should be retried after a recoverable exception during execution.
+ * Get the strategy which determines whether and how a retry should be attempted.
*
- * @return handler which determines if a request should be retried
+ * @return strategy which determines if a request should be retried
*/
- @Nullable public HttpRequestRetryHandler getHttpRequestRetryHandler() {
- return retryHandler;
+ @Nullable public HttpRequestRetryStrategy getHttpRequestRetryStrategy() {
+ return retryStrategy;
}
/**
- * Set the handler which determines if a request should be retried after a recoverable exception during execution.
+ * Set the strategy which determines whether and how a retry should be attempted.
*
- * @param handler handler which determines if a request should be retried
+ * @param strategy handler which determines if a request should be retried
*/
- public void setHttpRequestRetryHandler(@Nullable final HttpRequestRetryHandler handler) {
- retryHandler = handler;
+ public void setHttpRequestRetryStrategy(@Nullable final HttpRequestRetryStrategy strategy) {
+ retryStrategy = strategy;
}
-
+
/**
- * Get the handler which determines if a request should be retried given the response from the target server.
+ * Get the resolver for port based on a scheme.
*
- * @return handler which determines if a request should be retried
+ * @return the resolver, or null
*/
- @Nullable public ServiceUnavailableRetryStrategy getServiceUnavailableRetryHandler() {
- return serviceUnavailStrategy;
+ @Nullable public SchemePortResolver getSchemePortResolver() {
+ return schemePortResolver;
}
-
+
/**
- * Set the strategy which determines if a request should be retried given the response from the target server.
+ * Set the resolver for port based on a scheme.
*
- * @param strategy handler which determines if a request should be retried
+ * @param resolver the resolver, or null
*/
- public void setServiceUnavailableRetryHandler(@Nullable final ServiceUnavailableRetryStrategy strategy) {
- serviceUnavailStrategy = strategy;
+ public void setSchemePortResolver(@Nullable final SchemePortResolver resolver) {
+ schemePortResolver = resolver;
}
/**
@@ -881,6 +860,63 @@ public class HttpClientBuilder {
useSystemProperties = flag;
}
+ /**
+ * Get the flag for evicting expired connections from the connection pool using a background thread.
+ *
+ * @return true if enabled, false if not
+ */
+ public boolean isEvictExpiredConnections() {
+ return evictExpiredConnections;
+ }
+
+ /**
+ * Set the flag for evicting expired connections from the connection pool using a background thread.
+ *
+ * @param flag true if enabled, false if not
+ */
+ public void setEvictExpiredConnections(final boolean flag) {
+ evictExpiredConnections = flag;
+ }
+
+ /**
+ * Get the flag for evicting idle connections from the connection pool using a background thread.
+ *
+ * @return true if enabled, false if not
+ */
+ public boolean isEvictIdleConnections() {
+ return evictIdleConnections;
+ }
+
+ /**
+ * Set the flag for evicting idle connections from the connection pool using a background thread.
+ *
+ * @param flag true if enabled, false if not
+ */
+ public void setEvictIdleConnections(final boolean flag) {
+ evictIdleConnections = flag;
+ }
+
+ /**
+ * Get the max idle time allowed for an idle connection before it is evicted.
+ *
+ * @return max idle time
+ */
+ @Nonnull Duration getConnectionMaxIdleTime() {
+ return connectionMaxIdleTime;
+ }
+
+ /**
+ * Set the max idle time allowed for an idle connection before it is evicted.
+ *
+ * @param duration the max idle time
+ */
+ public void setConnectionMaxIdleTime(@Nonnull final Duration duration) {
+ Constraint.isNotNull(duration, "Connection max idle time cannot be null");
+ Constraint.isLessThanOrEqual(Integer.MAX_VALUE, duration.toMillis(), "Connection max idle time too large");
+
+ connectionMaxIdleTime = duration;
+ }
+
/**
* Get the list of request interceptors to add first.
*
@@ -1017,43 +1053,82 @@ public class HttpClientBuilder {
*
* @throws Exception if there is a problem decorating the Apache builder
*/
- // Checkstyle: CyclomaticComplexity|MethodLength OFF
- @SuppressWarnings("deprecation")
protected void decorateApacheBuilder() throws Exception {
- final org.apache.http.impl.client.HttpClientBuilder builder = getApacheBuilder();
+ final org.apache.hc.client5.http.impl.classic.HttpClientBuilder builder = getApacheBuilder();
- if (getTLSSocketFactory() != null) {
- builder.setSSLSocketFactory(getTLSSocketFactory());
- } else if (connectionDisregardTLSCertificate) {
- builder.setSSLSocketFactory(HttpClientSupport.buildNoTrustTLSSocketFactory());
- } else {
- builder.setSSLSocketFactory(HttpClientSupport.buildStrictTLSSocketFactory());
+ builder.setConnectionManager(buildConnectionManager());
+
+ builder.setDefaultRequestConfig(buildDefaultRequestConfig());
+
+ HttpHost proxyHost = null;
+ if (connectionProxyHost != null) {
+ proxyHost = new HttpHost(connectionProxyHost, connectionProxyPort);
+ builder.setProxy(proxyHost);
}
+ builder.setRoutePlanner(buildRoutePlanner(proxyHost));
+
+ builder.setDefaultCredentialsProvider(buildDefaultCredentialsProvider());
+
+ handleFluentProperties(builder);
+
if (connectionCloseAfterResponse) {
if (!getFirstRequestInterceptors().stream().anyMatch(RequestConnectionClose.class::isInstance)
&& !getLastRequestInterceptors().stream().anyMatch(RequestConnectionClose.class::isInstance)) {
- builder.addInterceptorLast(new RequestConnectionClose());
+ builder.addRequestInterceptorLast(new RequestConnectionClose());
}
}
- if (maxConnectionsTotal > 0) {
- builder.setMaxConnTotal(maxConnectionsTotal);
+ getFirstRequestInterceptors().forEach(builder::addRequestInterceptorFirst);
+ getLastRequestInterceptors().forEach(builder::addRequestInterceptorLast);
+ getFirstResponseInterceptors().forEach(builder::addResponseInterceptorFirst);
+ getLastResponseInterceptors().forEach(builder::addResponseInterceptorLast);
+
+ if (retryStrategy != null) {
+ builder.setRetryStrategy(retryStrategy);
}
-
- if (maxConnectionsPerRoute > 0) {
- builder.setMaxConnPerRoute(maxConnectionsPerRoute);
+
+ if (null != userAgent) {
+ builder.setUserAgent(userAgent);
}
-
- if (retryHandler != null) {
- builder.setRetryHandler(retryHandler);
+ }
+
+ /**
+ * Build the instance of {@link HttpRoutePlanner}.
+ *
+ * This is only necessary if we have a configured local address via
+ * (@link {@link #getSocketLocalAddress()}).
+ *
+ * @param proxyHost the proxy host, or null
+ * @return the route planner instance, or null
+ */
+ @Nullable protected HttpRoutePlanner buildRoutePlanner(@Nullable final HttpHost proxyHost) {
+ // By default we only need to build this if we have an explicitly-configured local address
+ if (socketLocalAddress == null) {
+ return null;
}
- if (serviceUnavailStrategy != null) {
- builder.setServiceUnavailableRetryStrategy(serviceUnavailStrategy);
- }
+ // This logic for the selection of the route planner impl to use is mirrored from
+ // the Apache HttpClientBuilder#build().
+ final SchemePortResolver resolver = schemePortResolver != null ?
+ schemePortResolver : DefaultSchemePortResolver.INSTANCE;
- // These boolean and interceptor properties can otherwise only be supplied
+ if (proxyHost != null) {
+ return new LocalAddressProxyRoutePlanner(socketLocalAddress, proxyHost, resolver);
+ } else if (isUseSystemProperties()) {
+ return new LocalAddressSystemRoutePlanner(socketLocalAddress, resolver, ProxySelector.getDefault());
+ } else {
+ return new LocalAddressRoutePlanner(socketLocalAddress, resolver);
+ }
+ }
+
+ /**
+ * Handle the fluent (non-DI-friendly) builder properties.
+ *
+ * @param builder the Apache HttpClientBuilder
+ */
+ protected void handleFluentProperties(org.apache.hc.client5.http.impl.classic.HttpClientBuilder builder ) {
+ // These boolean, interceptor, and eviction properties can otherwise only be supplied
// to the Apache builder via a fluent-style API.
if (isDisableAuthCaching()) {
@@ -1083,75 +1158,138 @@ public class HttpClientBuilder {
if (isUseSystemProperties()) {
builder.useSystemProperties();
}
+
+ if (isEvictExpiredConnections()) {
+ builder.evictExpiredConnections();
+ }
- getFirstRequestInterceptors().forEach(builder::addInterceptorFirst);
- getLastRequestInterceptors().forEach(builder::addInterceptorLast);
- getFirstResponseInterceptors().forEach(builder::addInterceptorFirst);
- getLastResponseInterceptors().forEach(builder::addInterceptorLast);
-
- // RequestConfig params
+ if (isEvictIdleConnections()) {
+ builder.evictIdleConnections(TimeValue.ofMilliseconds(connectionMaxIdleTime.toMillis()));
+ }
+ }
+
+ /**
+ * Build default {@link CredentialsProvider}.
+ *
+ * @return the default credentials provider, or null
+ */
+ @Nullable protected CredentialsProvider buildDefaultCredentialsProvider() {
+ if (connectionProxyHost != null && connectionProxyUsername != null && connectionProxyPassword != null) {
+ // Note proxy HttpHost is set separately
+ return CredentialsProviderBuilder.create()
+ .add(new AuthScope(connectionProxyHost, connectionProxyPort),
+ new UsernamePasswordCredentials(connectionProxyUsername,
+ connectionProxyPassword.toCharArray()))
+ .build();
+ }
+
+ return null;
+ }
+
+ /**
+ * Build the default instance of {@link RequestConfig}
+ *
+ * @return the request config instance
+ */
+ @Nonnull protected RequestConfig buildDefaultRequestConfig() {
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
- if (socketLocalAddress != null) {
- requestConfigBuilder.setLocalAddress(socketLocalAddress);
+ if (!connectionRequestTimeout.isNegative()) {
+ requestConfigBuilder.setConnectionRequestTimeout(Timeout.ofMilliseconds(connectionRequestTimeout.toMillis()));
}
- if (!socketTimeout.isNegative()) {
- requestConfigBuilder.setSocketTimeout((int) socketTimeout.toMillis());
+ if (!responseTimeout.isNegative()) {
+ requestConfigBuilder.setResponseTimeout(Timeout.ofMilliseconds(responseTimeout.toMillis()));
}
- if (!connectionTimeout.isNegative()) {
- requestConfigBuilder.setConnectTimeout((int) connectionTimeout.toMillis());
- }
+ requestConfigBuilder.setRedirectsEnabled(httpFollowRedirects);
- if (!connectionRequestTimeout.isNegative()) {
- requestConfigBuilder.setConnectionRequestTimeout((int) connectionRequestTimeout.toMillis());
+ return requestConfigBuilder.build();
+ }
+
+ /**
+ * Build an instance of {@link HttpClientConnectionManager}
+ *
+ * @return the connection manager instance
+ */
+ @Nonnull protected HttpClientConnectionManager buildConnectionManager() {
+ final PoolingHttpClientConnectionManagerBuilder connMgrBuilder =
+ PoolingHttpClientConnectionManagerBuilder.create();
+
+ connMgrBuilder.setConnectionFactory(buildConnectionFactory());
+
+ connMgrBuilder.setDefaultConnectionConfig(buildDefaultConnectionConfig());
+
+ if (getTLSSocketFactory() != null) {
+ connMgrBuilder.setSSLSocketFactory(getTLSSocketFactory());
+ } else if (connectionDisregardTLSCertificate) {
+ connMgrBuilder.setSSLSocketFactory(HttpClientSupport.buildNoTrustTLSSocketFactory());
+ } else {
+ connMgrBuilder.setSSLSocketFactory(HttpClientSupport.buildStrictTLSSocketFactory());
+ }
+
+ if (maxConnectionsTotal > 0) {
+ connMgrBuilder.setMaxConnTotal(maxConnectionsTotal);
+ }
+
+ if (maxConnectionsPerRoute > 0) {
+ connMgrBuilder.setMaxConnPerRoute(maxConnectionsPerRoute);
}
- // TODO: When we remove the deprecated 'connectionStaleCheck' when we move to HC 5,
- // be sure to also remove the @SuppressWarnings("deprecation") on this method.
- requestConfigBuilder.setStaleConnectionCheckEnabled(connectionStaleCheck);
+ return connMgrBuilder.build();
+ }
- requestConfigBuilder.setRedirectsEnabled(httpFollowRedirects);
+ /**
+ * Build the default instance of {@link ConnectionConfig}.
+ *
+ * @return the default connection config instance
+ */
+ protected ConnectionConfig buildDefaultConnectionConfig() {
+ ConnectionConfig.Builder builder = ConnectionConfig.custom();
+ if (!connectionTimeout.isNegative()) {
+ builder.setConnectTimeout(Timeout.ofMilliseconds(connectionTimeout.toMillis()));
+ }
- if (connectionProxyHost != null) {
- final HttpHost proxyHost = new HttpHost(connectionProxyHost, connectionProxyPort);
- requestConfigBuilder.setProxy(proxyHost);
-
- if (connectionProxyUsername != null && connectionProxyPassword != null) {
- final CredentialsProvider credProvider = new BasicCredentialsProvider();
- credProvider.setCredentials(new AuthScope(connectionProxyHost, connectionProxyPort),
- new UsernamePasswordCredentials(connectionProxyUsername, connectionProxyPassword));
- builder.setDefaultCredentialsProvider(credProvider);
- }
+ if (!socketTimeout.isNegative()) {
+ builder.setSocketTimeout(Timeout.ofMilliseconds(socketTimeout.toMillis()));
+ }
+
+ if (validateAfterInactivity != null) {
+ builder.setValidateAfterInactivity(TimeValue.ofMilliseconds(validateAfterInactivity.toMillis()));
}
- // ConnectionConfig params
- final ConnectionConfig.Builder connectionConfigBuilder = ConnectionConfig.custom();
+ return builder.build();
+ }
+
+ /**
+ * Build an instance of {@link HttpConnectionFactory}.
+ *
+ * @return the connection factory instance
+ */
+ @Nonnull protected HttpConnectionFactory<ManagedHttpClientConnection> buildConnectionFactory() {
+ ManagedHttpClientConnectionFactory.Builder builder = ManagedHttpClientConnectionFactory.builder();
- connectionConfigBuilder.setBufferSize(socketBufferSize);
+ builder.http1Config(Http1Config.custom()
+ .setBufferSize(socketBufferSize)
+ .build());
if (httpContentCharSet != null) {
- connectionConfigBuilder.setCharset(CharsetUtils.get(httpContentCharSet));
+ builder.charCodingConfig(CharCodingConfig.custom()
+ .setCharset(Charset.forName(httpContentCharSet))
+ .build());
}
- builder.setDefaultRequestConfig(requestConfigBuilder.build());
- builder.setDefaultConnectionConfig(connectionConfigBuilder.build());
-
- if (null != userAgent) {
- builder.setUserAgent(userAgent);
- }
+ return builder.build();
}
- // Checkstyle: CyclomaticComplexity|MethodLength ON
/**
- * Get the Apache {@link org.apache.http.impl.client.HttpClientBuilder} instance over which this builder will be
- * layered. Subclasses may override to return a specialized subclass.
+ * Get the Apache {@link org.apache.hc.client5.http.impl.classic.HttpClientBuilder} instance over which this builder
+ * will be layered. Subclasses may override to return a specialized subclass.
*
* @return the Apache HttpClientBuilder instance to use
*/
- protected org.apache.http.impl.client.HttpClientBuilder getApacheBuilder() {
+ @Nonnull org.apache.hc.client5.http.impl.classic.HttpClientBuilder getApacheBuilder() {
return apacheBuilder;
}
-}
\ No newline at end of file
+}
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientContextHandler.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientContextHandler.java
index 275917c0..eb069719 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientContextHandler.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientContextHandler.java
@@ -22,8 +22,8 @@ import java.io.IOException;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ClassicHttpRequest;
/**
* Extension that allows the {@link HttpClientContext} to be externally manipulated before use.
@@ -41,7 +41,7 @@ public interface HttpClientContextHandler {
*
* @throws IOException if the call should be aborted
*/
- void invokeBefore(@Nonnull final HttpClientContext context, @Nonnull final HttpUriRequest request)
+ void invokeBefore(@Nonnull final HttpClientContext context, @Nonnull final ClassicHttpRequest request)
throws IOException;
/**
@@ -52,7 +52,7 @@ public interface HttpClientContextHandler {
*
* @throws IOException if the call should be aborted
*/
- void invokeAfter(@Nonnull final HttpClientContext context, @Nonnull final HttpUriRequest request)
+ void invokeAfter(@Nonnull final HttpClientContext context, @Nonnull final ClassicHttpRequest request)
throws IOException;
}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientSupport.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientSupport.java
index 5fc6a466..b4c5b75f 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientSupport.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/HttpClientSupport.java
@@ -36,15 +36,14 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
-import org.apache.http.HttpEntity;
-import org.apache.http.ParseException;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
-import org.apache.http.conn.ssl.DefaultHostnameVerifier;
-import org.apache.http.conn.ssl.NoopHostnameVerifier;
-import org.apache.http.entity.ContentType;
-import org.apache.http.protocol.HTTP;
-import org.apache.http.util.CharArrayBuffer;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier;
+import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.util.CharArrayBuffer;
import org.slf4j.Logger;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
@@ -52,7 +51,7 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
/**
- * Support class for using {@link org.apache.http.client.HttpClient} and related components.
+ * Support class for using {@link org.apache.hc.client5.http.classic.HttpClient} and related components.
*/
public final class HttpClientSupport {
@@ -141,6 +140,7 @@ public final class HttpClientSupport {
@Nonnull public static List<HttpClientContextHandler> getDynamicContextHandlerList(
@Nonnull final HttpClientContext context) {
Constraint.isNotNull(context, "HttpClientContext was null");
+ @SuppressWarnings("unchecked")
List<HttpClientContextHandler> handlers =
context.getAttribute(CONTEXT_KEY_DYNAMIC_CONTEXT_HANDLERS, List.class);
if (handlers == null) {
@@ -244,7 +244,7 @@ public final class HttpClientSupport {
}
Charset charset = null;
try {
- final ContentType contentType = ContentType.get(entity);
+ final ContentType contentType = ContentType.parse(entity.getContentType());
if (contentType != null) {
charset = contentType.getCharset();
}
@@ -255,7 +255,7 @@ public final class HttpClientSupport {
charset = defaultCharset;
}
if (charset == null) {
- charset = HTTP.DEF_CONTENT_CHARSET;
+ charset = Charset.forName("ISO-8859-1");
}
try (final Reader reader = new InputStreamReader(instream, charset)) {
final CharArrayBuffer buffer = new CharArrayBuffer(i);
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/IdleConnectionSweeper.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/IdleConnectionSweeper.java
deleted file mode 100644
index 9a8cdd0e..00000000
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/IdleConnectionSweeper.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the University Corporation for Advanced Internet Development,
- * Inc. (UCAID) under one or more contributor license agreements. See the
- * NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.shared.httpclient;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.shared.component.DestroyedComponentException;
-import net.shibboleth.shared.component.DestructableComponent;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.TimerSupport;
-
-import org.apache.http.conn.HttpClientConnectionManager;
-
-/** A utility that periodically closes idle connections held by an {@link HttpClientConnectionManager}. */
-public class IdleConnectionSweeper implements DestructableComponent {
-
- /** Whether this sweeper has been destroyed. */
- private boolean destroyed;
-
- /**
- * Whether this sweeper created a {@link TimerTask} to use and thus should destroy when {@link #destroy()} is
- * invoked.
- */
- private boolean createdTimer;
-
- /** Time at which the sweeper last executed. */
- @Nullable private Instant executionTime;
-
- /** HttpClientConnectionManager whose connections will be swept. */
- @Nonnull private final HttpClientConnectionManager connectionManager;
-
- /** Timer used to schedule and execute the sweeping task. */
- @Nonnull private final Timer taskTimer;
-
- /** Sweeping task executed by the timer. */
- @Nonnull private final TimerTask sweeper;
-
- /**
- * Constructor. This method will create a daemon {@link Timer} and use it to periodically sweep connections.
- *
- * @param manager HTTP client connection manager whose connections will be swept
- * @param idleTimeout length of time connection may be idle before being closed down
- * @param sweepInterval length of time between sweeps
- */
- public IdleConnectionSweeper(@Nonnull final HttpClientConnectionManager manager,
- @Nonnull final Duration idleTimeout, @Nonnull final Duration sweepInterval) {
- this(manager, idleTimeout, sweepInterval,
- new Timer(TimerSupport.getTimerName(IdleConnectionSweeper.class.getName(), null), true));
- createdTimer = true;
- }
-
- /**
- * Constructor.
- *
- * @param manager HTTP client connection manager whose connections will be swept
- * @param idleTimeout length of time connection may be idle before being closed down
- * @param sweepInterval length of time between sweeps
- * @param backgroundTimer timer used to schedule the background sweeping task
- */
- public IdleConnectionSweeper(@Nonnull final HttpClientConnectionManager manager,
- @Nonnull final Duration idleTimeout, @Nonnull final Duration sweepInterval,
- @Nonnull final Timer backgroundTimer) {
- connectionManager = Constraint.isNotNull(manager, "HttpClientConnectionManager can not be null");
- taskTimer = Constraint.isNotNull(backgroundTimer, "Sweeper task timer can not be null");
-
- sweeper = new TimerTask() {
- public void run() {
- executionTime = Instant.now();
- connectionManager.closeIdleConnections(idleTimeout.toMillis(), TimeUnit.MILLISECONDS);
- }
- };
-
- taskTimer.schedule(sweeper, sweepInterval.toMillis(), sweepInterval.toMillis());
- }
-
- /**
- * Gets the time when the sweeper last executed or, if it has not yet executed,
- * when it was first scheduled to run.
- *
- * @return the time when the sweeper last executed or when it was first scheduled to run
- */
- @Nonnull public Instant scheduledExecutionTime() {
- if (isDestroyed()) {
- throw new DestroyedComponentException();
- }
-
- if (executionTime != null) {
- return executionTime;
- }
-
- return Instant.ofEpochMilli(sweeper.scheduledExecutionTime());
- }
-
- /** {@inheritDoc} */
- public boolean isDestroyed() {
- return destroyed;
- }
-
- /** {@inheritDoc} */
- public synchronized void destroy() {
- sweeper.cancel();
-
- if (createdTimer) {
- taskTimer.cancel();
- }
-
- destroyed = true;
- }
-}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/InMemoryCachingHttpClientBuilder.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/InMemoryCachingHttpClientBuilder.java
index 4b8c9ca9..3535fe66 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/InMemoryCachingHttpClientBuilder.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/InMemoryCachingHttpClientBuilder.java
@@ -19,15 +19,15 @@ package net.shibboleth.shared.httpclient;
import javax.annotation.Nonnull;
-import org.apache.http.impl.client.cache.BasicHttpCacheStorage;
-import org.apache.http.impl.client.cache.CacheConfig;
-import org.apache.http.impl.client.cache.CachingHttpClientBuilder;
-import org.apache.http.impl.client.cache.HeapResourceFactory;
+import org.apache.hc.client5.http.impl.cache.BasicHttpCacheStorage;
+import org.apache.hc.client5.http.impl.cache.CacheConfig;
+import org.apache.hc.client5.http.impl.cache.CachingHttpClientBuilder;
+import org.apache.hc.client5.http.impl.cache.HeapResourceFactory;
import net.shibboleth.shared.logic.Constraint;
/**
- * An {@link org.apache.http.client.HttpClient} builder that supports RFC 2616 caching.
+ * An {@link org.apache.hc.client5.http.classic.HttpClient} builder that supports RFC 2616 caching.
* <p>
* This client will cache information retrieved from the remote server in memory. The backing store does
* <strong>not</strong> perform any resource management (e.g., removing content that has nominally expired) so, special
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressProxyRoutePlanner.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressProxyRoutePlanner.java
new file mode 100644
index 00000000..1082aeec
--- /dev/null
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressProxyRoutePlanner.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.shared.httpclient;
+
+import java.net.InetAddress;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * Extension of {@link DefaultProxyRoutePlanner} which allows supplying a static local address.
+ */
+public class LocalAddressProxyRoutePlanner extends DefaultProxyRoutePlanner {
+
+ /** The local address. */
+ @Nullable InetAddress address;
+
+ /**
+ * Constructor.
+ *
+ * @param localAddress the local address
+ * @param proxy the proxy host
+ * @param schemePortResolver the scheme port resolver
+ */
+ public LocalAddressProxyRoutePlanner(@Nullable final InetAddress localAddress, @Nonnull final HttpHost proxy,
+ @Nullable final SchemePortResolver schemePortResolver) {
+ super(proxy, schemePortResolver);
+ address = localAddress;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) throws HttpException {
+ return address;
+ }
+
+}
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressRoutePlanner.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressRoutePlanner.java
new file mode 100644
index 00000000..63e36fa9
--- /dev/null
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressRoutePlanner.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.shared.httpclient;
+
+import java.net.InetAddress;
+
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * Extension of {@link DefaultRoutePlanner} which allows supplying a static local address.
+ */
+public class LocalAddressRoutePlanner extends DefaultRoutePlanner {
+
+ /** The local address. */
+ @Nullable InetAddress address;
+
+ /**
+ * Constructor.
+ *
+ * @param localAddress the local address
+ * @param schemePortResolver the scheme port resolver
+ */
+ public LocalAddressRoutePlanner(@Nullable final InetAddress localAddress,
+ @Nullable final SchemePortResolver schemePortResolver) {
+ super(schemePortResolver);
+ address = localAddress;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) throws HttpException {
+ return address;
+ }
+
+}
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressSystemRoutePlanner.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressSystemRoutePlanner.java
new file mode 100644
index 00000000..5b985ee9
--- /dev/null
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/LocalAddressSystemRoutePlanner.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.shared.httpclient;
+
+import java.net.InetAddress;
+import java.net.ProxySelector;
+
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * Extension of {@link SystemDefaultRoutePlanner} which allows supplying a static local address.
+ */
+public class LocalAddressSystemRoutePlanner extends SystemDefaultRoutePlanner {
+
+ /** The local address. */
+ @Nullable InetAddress address;
+
+ /**
+ * Constructor.
+ *
+ * @param localAddress the local address
+ * @param schemePortResolver the schema port resolver
+ * @param proxySelector the proxy selector
+ */
+ public LocalAddressSystemRoutePlanner(@Nullable final InetAddress localAddress,
+ @Nullable final SchemePortResolver schemePortResolver, @Nullable final ProxySelector proxySelector) {
+ super(schemePortResolver, proxySelector);
+ address = localAddress;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) throws HttpException {
+ return address;
+ }
+
+}
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/RequestConnectionClose.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/RequestConnectionClose.java
index 28885a93..190b6f4c 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/RequestConnectionClose.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/RequestConnectionClose.java
@@ -19,30 +19,48 @@ package net.shibboleth.shared.httpclient;
import java.io.IOException;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHeaders;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpVersion;
-import org.apache.http.protocol.HttpContext;
+import javax.annotation.Nonnull;
+
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.HeaderElements;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpRequestInterceptor;
+import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.slf4j.Logger;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
/**
* Adds a <code>Connection: close</code> to all HTTP/1.1 requests.
*
* <p>
* This interceptor essentially disables connection keep-alive support and, by virtue of the server closing the
- * connection, prevents a {@link org.apache.http.conn.ClientConnectionManager} from holding open and reusing
- * connections. If you'd like to allow the {@link org.apache.http.conn.ClientConnectionManager} to hold open connections
- * for a while and potentially reuse them consider using the {@link IdleConnectionSweeper} to limit the amount of time
+ * connection, prevents a {@link org.apache.hc.client5.http.io.HttpClientConnectionManager} from holding open and
+ * reusing connections. If you'd like to allow the {@link org.apache.hc.client5.http.io.HttpClientConnectionManager}
+ * to hold open connections for a while and potentially reuse them, consider using
+ * {@link HttpClientBuilder#setEvictIdleConnections(boolean)} and
+ * {@link HttpClientBuilder#setConnectionMaxIdleTime(java.time.Duration)} to limit the amount of time
* the connections are held open.
* </p>
*/
public class RequestConnectionClose implements HttpRequestInterceptor {
+
+ /** Logger. */
+ @Nonnull static final Logger log = LoggerFactory.getLogger(RequestConnectionClose.class);
/** {@inheritDoc} */
- public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
- if (HttpVersion.HTTP_1_1.equals(request.getProtocolVersion())) {
- request.addHeader(HttpHeaders.CONNECTION, "close");
+ public void process(final HttpRequest request, EntityDetails entity, final HttpContext context)
+ throws HttpException, IOException {
+ log.trace("Saw negotiated protocol version: {}", context.getProtocolVersion());
+ if (HttpVersion.HTTP_1_1.lessEquals(context.getProtocolVersion())) {
+ log.trace("Adding request header '{}: {}'", HttpHeaders.CONNECTION, HeaderElements.CLOSE);
+ request.addHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE);
+ } else {
+ log.warn("Negotiated protocol did not match condition, skipping add of request header '{}: {}', "
+ + "may cause issues related to pooling", HttpHeaders.CONNECTION, HeaderElements.CLOSE);
}
}
}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/TLSSocketFactory.java b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/TLSSocketFactory.java
index 87841e53..396d9deb 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/httpclient/TLSSocketFactory.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/httpclient/TLSSocketFactory.java
@@ -39,13 +39,13 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.primitive.StringSupport;
-import org.apache.http.HttpHost;
-import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
-import org.apache.http.conn.ssl.DefaultHostnameVerifier;
-import org.apache.http.conn.ssl.NoopHostnameVerifier;
-import org.apache.http.conn.util.PublicSuffixMatcher;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.util.Args;
+import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier;
+import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.util.Args;
+import org.apache.hc.core5.util.TimeValue;
import org.slf4j.Logger;
@@ -54,7 +54,7 @@ import org.slf4j.Logger;
* for TLS sockets.
*
* <p>
- * This class is functionally modeled on {@link org.apache.http.conn.ssl.SSLConnectionSocketFactory},
+ * This class is functionally modeled on {@link org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory},
* but provides better support for subclassing, as well as specific additional features:
* </p>
*
@@ -241,7 +241,7 @@ public class TLSSocketFactory implements LayeredConnectionSocketFactory {
// Checkstyle: ParameterNumber OFF
/** {@inheritDoc} */
public Socket connectSocket(
- final int connectTimeout,
+ TimeValue connectTimeout,
final Socket socket,
final HttpHost host,
final InetSocketAddress remoteAddress,
@@ -258,10 +258,11 @@ public class TLSSocketFactory implements LayeredConnectionSocketFactory {
sock.bind(localAddress);
}
try {
- if (connectTimeout > 0 && sock.getSoTimeout() == 0) {
- sock.setSoTimeout(connectTimeout);
+ int connectTimeoutMillis = connectTimeout.toMillisecondsIntBound();
+ if (connectTimeoutMillis > 0 && sock.getSoTimeout() == 0) {
+ sock.setSoTimeout(connectTimeoutMillis);
}
- sock.connect(remoteAddress, connectTimeout);
+ sock.connect(remoteAddress, connectTimeoutMillis);
} catch (final IOException ex) {
try {
sock.close();
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/httpclient/HttpClientSupport.java b/shib-networking/src/main/java/net/shibboleth/utilities/java/support/httpclient/HttpClientSupport.java
index 62c2fca4..d656123d 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/httpclient/HttpClientSupport.java
+++ b/shib-networking/src/main/java/net/shibboleth/utilities/java/support/httpclient/HttpClientSupport.java
@@ -27,11 +27,10 @@ import javax.annotation.Nullable;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
-import org.apache.http.HttpEntity;
-import org.apache.http.ParseException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.ParseException;
import net.shibboleth.shared.httpclient.HttpClientContextHandler;
import net.shibboleth.shared.primitive.DeprecationSupport;
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/ContextHandlingHttpClientTest.java b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/ContextHandlingHttpClientTest.java
index 2348cd3a..33fbc43f 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/ContextHandlingHttpClientTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/ContextHandlingHttpClientTest.java
@@ -22,20 +22,17 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.ProtocolVersion;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.message.BasicHttpResponse;
-import org.apache.http.protocol.HttpContext;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.io.CloseMode;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
@@ -44,7 +41,8 @@ import org.testng.annotations.Test;
@SuppressWarnings("javadoc")
public class ContextHandlingHttpClientTest {
- public static final CloseableHttpResponse STATIC_RESPONSE_HTTP = new MockCloseableHttpResponse(new ProtocolVersion("HTTP", 1, 1), HttpStatus.SC_OK, "OK");
+ public static final ClassicHttpResponse STATIC_RESPONSE_HTTP =
+ new MockClassicHttpResponse(new ProtocolVersion("HTTP", 1, 1), HttpStatus.SC_OK, "OK");
public static final Object STATIC_RESPONSE_HANDLER = new Object();
@@ -55,9 +53,9 @@ public class ContextHandlingHttpClientTest {
private HttpClientContext context;
- private HttpUriRequest request;
+ private ClassicHttpRequest request;
private HttpHost target;
- private ResponseHandler<Object> responseHandler = new MockResponseHandler();
+ private HttpClientResponseHandler<Object> responseHandler = new MockResponseHandler();
@BeforeClass
public void setupClass() {
@@ -77,7 +75,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testNoHandlers() throws ClientProtocolException, IOException {
+ public void testNoHandlers() throws IOException {
client = new ContextHandlingHttpClient(new MockHttpClient());
context = HttpClientContext.create();
@@ -89,13 +87,13 @@ public class ContextHandlingHttpClientTest {
//Context execute methods
Assert.assertSame(client.execute(request, context), STATIC_RESPONSE_HTTP);
- Assert.assertSame(client.execute(request, responseHandler, context), STATIC_RESPONSE_HANDLER);
+ Assert.assertSame(client.execute(request, context, responseHandler), STATIC_RESPONSE_HANDLER);
Assert.assertSame(client.execute(target, request, context), STATIC_RESPONSE_HTTP);
- Assert.assertSame(client.execute(target, request, responseHandler, context), STATIC_RESPONSE_HANDLER);
+ Assert.assertSame(client.execute(target, request, context, responseHandler), STATIC_RESPONSE_HANDLER);
}
@Test
- public void testStaticOnly() throws ClientProtocolException, IOException {
+ public void testStaticOnly() throws IOException {
client = new ContextHandlingHttpClient(new MockHttpClient(), List.of(staticOne, staticTwo, staticThree));
List<String> control = List.of(
@@ -112,7 +110,7 @@ public class ContextHandlingHttpClientTest {
Assert.assertEquals(context.getAttribute(TestContextHandler.TEST_KEY), control);
context = HttpClientContext.create();
- Assert.assertSame(client.execute(request, responseHandler, context), STATIC_RESPONSE_HANDLER);
+ Assert.assertSame(client.execute(request, context, responseHandler), STATIC_RESPONSE_HANDLER);
Assert.assertEquals(context.getAttribute(TestContextHandler.TEST_KEY), control);
context = HttpClientContext.create();
@@ -120,12 +118,12 @@ public class ContextHandlingHttpClientTest {
Assert.assertEquals(context.getAttribute(TestContextHandler.TEST_KEY), control);
context = HttpClientContext.create();
- Assert.assertSame(client.execute(target, request, responseHandler, context), STATIC_RESPONSE_HANDLER);
+ Assert.assertSame(client.execute(target, request, context, responseHandler), STATIC_RESPONSE_HANDLER);
Assert.assertEquals(context.getAttribute(TestContextHandler.TEST_KEY), control);
}
@Test
- public void testDynamicOnly() throws ClientProtocolException, IOException {
+ public void testDynamicOnly() throws IOException {
client = new ContextHandlingHttpClient(new MockHttpClient());
List<String> control = List.of(
@@ -146,7 +144,7 @@ public class ContextHandlingHttpClientTest {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- Assert.assertSame(client.execute(request, responseHandler, context), STATIC_RESPONSE_HANDLER);
+ Assert.assertSame(client.execute(request, context, responseHandler), STATIC_RESPONSE_HANDLER);
Assert.assertEquals(context.getAttribute(TestContextHandler.TEST_KEY), control);
context = HttpClientContext.create();
@@ -156,12 +154,12 @@ public class ContextHandlingHttpClientTest {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- Assert.assertSame(client.execute(target, request, responseHandler, context), STATIC_RESPONSE_HANDLER);
+ Assert.assertSame(client.execute(target, request, context, responseHandler), STATIC_RESPONSE_HANDLER);
Assert.assertEquals(context.getAttribute(TestContextHandler.TEST_KEY), control);
}
@Test
- public void testStaticAndDynamic() throws ClientProtocolException, IOException {
+ public void testStaticAndDynamic() throws IOException {
client = new ContextHandlingHttpClient(new MockHttpClient(), List.of(staticOne, staticTwo, staticThree));
List<String> control = List.of(
@@ -188,7 +186,7 @@ public class ContextHandlingHttpClientTest {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- Assert.assertSame(client.execute(request, responseHandler, context), STATIC_RESPONSE_HANDLER);
+ Assert.assertSame(client.execute(request, context, responseHandler), STATIC_RESPONSE_HANDLER);
Assert.assertEquals(context.getAttribute(TestContextHandler.TEST_KEY), control);
context = HttpClientContext.create();
@@ -198,12 +196,12 @@ public class ContextHandlingHttpClientTest {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- Assert.assertSame(client.execute(target, request, responseHandler, context), STATIC_RESPONSE_HANDLER);
+ Assert.assertSame(client.execute(target, request, context, responseHandler), STATIC_RESPONSE_HANDLER);
Assert.assertEquals(context.getAttribute(TestContextHandler.TEST_KEY), control);
}
@Test
- public void testWrappedClientThrowsIOException() throws ClientProtocolException, IOException {
+ public void testWrappedClientThrowsIOException() throws IOException {
IOException error = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(error), List.of(staticOne, staticTwo, staticThree));
@@ -237,7 +235,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -257,7 +255,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -266,7 +264,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testWrappedClientThrowsRuntimeException() throws ClientProtocolException, IOException {
+ public void testWrappedClientThrowsRuntimeException() throws IOException {
RuntimeException error = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(error), List.of(staticOne, staticTwo, staticThree));
@@ -300,7 +298,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (RuntimeException e) {
Assert.assertSame(e, error);
@@ -320,7 +318,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (RuntimeException e) {
Assert.assertSame(e, error);
@@ -329,7 +327,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testWrappedClientThrowsError() throws ClientProtocolException, IOException {
+ public void testWrappedClientThrowsError() throws IOException {
Error error = new Error();
client = new ContextHandlingHttpClient(new MockHttpClient(error), List.of(staticOne, staticTwo, staticThree));
@@ -363,7 +361,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (Error e) {
Assert.assertSame(e, error);
@@ -383,7 +381,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (Error e) {
Assert.assertSame(e, error);
@@ -392,7 +390,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testSingleStaticHandlerInvokeBeforeThrowsIOException() throws ClientProtocolException, IOException {
+ public void testSingleStaticHandlerInvokeBeforeThrowsIOException() throws IOException {
IOException error = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
List.of(staticOne, new TestContextHandler("static-2", error, null), staticThree));
@@ -427,7 +425,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -447,7 +445,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -456,7 +454,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testSingleStaticHandlerInvokeAfterThrowsIOException() throws ClientProtocolException, IOException {
+ public void testSingleStaticHandlerInvokeAfterThrowsIOException() throws IOException {
IOException error = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
List.of(staticOne, new TestContextHandler("static-2", null, error), staticThree));
@@ -491,7 +489,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -511,7 +509,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -520,7 +518,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testSingleStaticHandlerInvokeBeforeThrowsRuntimeException() throws ClientProtocolException, IOException {
+ public void testSingleStaticHandlerInvokeBeforeThrowsRuntimeException() throws IOException {
RuntimeException error = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
List.of(staticOne, new TestContextHandler("static-2", error, null), staticThree));
@@ -555,7 +553,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), error);
@@ -575,7 +573,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), error);
@@ -584,7 +582,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testSingleStaticHandlerInvokeAfterThrowsRuntimeException() throws ClientProtocolException, IOException {
+ public void testSingleStaticHandlerInvokeAfterThrowsRuntimeException() throws IOException {
RuntimeException error = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
List.of(staticOne, new TestContextHandler("static-2", null, error), staticThree));
@@ -619,7 +617,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), error);
@@ -639,7 +637,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), error);
@@ -648,7 +646,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testMultipleStaticHandlersInvokeBeforeThrowIOException() throws ClientProtocolException, IOException {
+ public void testMultipleStaticHandlersInvokeBeforeThrowIOException() throws IOException {
IOException error1 = new IOException();
IOException error3 = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
@@ -687,7 +685,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -713,7 +711,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -725,7 +723,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testMultipleStaticHandlersInvokeBeforeThrowRuntimeException() throws ClientProtocolException, IOException {
+ public void testMultipleStaticHandlersInvokeBeforeThrowRuntimeException() throws IOException {
RuntimeException error1 = new RuntimeException();
RuntimeException error3 = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
@@ -764,7 +762,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -790,7 +788,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -803,7 +801,7 @@ public class ContextHandlingHttpClientTest {
@Test
- public void testMultipleStaticHandlersInvokeAfterThrowIOException() throws ClientProtocolException, IOException {
+ public void testMultipleStaticHandlersInvokeAfterThrowIOException() throws IOException {
IOException error1 = new IOException();
IOException error3 = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
@@ -842,7 +840,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -868,7 +866,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -880,7 +878,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testMultipleStaticHandlersInvokeAfterThrowRuntimeException() throws ClientProtocolException, IOException {
+ public void testMultipleStaticHandlersInvokeAfterThrowRuntimeException() throws IOException {
RuntimeException error1 = new RuntimeException();
RuntimeException error3 = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
@@ -919,7 +917,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -945,7 +943,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -958,7 +956,7 @@ public class ContextHandlingHttpClientTest {
@Test
- public void testSingleDynamicHandlerInvokeBeforeThrowsIOException() throws ClientProtocolException, IOException {
+ public void testSingleDynamicHandlerInvokeBeforeThrowsIOException() throws IOException {
IOException error = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
List.of(staticOne, staticTwo, staticThree));
@@ -993,7 +991,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -1013,7 +1011,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -1022,7 +1020,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testSingleDynamicHandlerInvokeAfterThrowsIOException() throws ClientProtocolException, IOException {
+ public void testSingleDynamicHandlerInvokeAfterThrowsIOException() throws IOException {
IOException error = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
List.of(staticOne, staticTwo, staticThree));
@@ -1057,7 +1055,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -1077,7 +1075,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, error);
@@ -1087,7 +1085,7 @@ public class ContextHandlingHttpClientTest {
@Test
- public void testSingleDynamicHandlerInvokeBeforeThrowsRuntimeException() throws ClientProtocolException, IOException {
+ public void testSingleDynamicHandlerInvokeBeforeThrowsRuntimeException() throws IOException {
RuntimeException error = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
List.of(staticOne, staticTwo, staticThree));
@@ -1122,7 +1120,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), error);
@@ -1142,7 +1140,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), error);
@@ -1151,7 +1149,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testSingleDynamicHandlerInvokeAfterThrowsRuntimeException() throws ClientProtocolException, IOException {
+ public void testSingleDynamicHandlerInvokeAfterThrowsRuntimeException() throws IOException {
RuntimeException error = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
List.of(staticOne, staticTwo, staticThree));
@@ -1186,7 +1184,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), error);
@@ -1206,7 +1204,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), error);
@@ -1216,7 +1214,7 @@ public class ContextHandlingHttpClientTest {
@Test
- public void testMultipleDynamicHandlersInvokeBeforeThrowIOException() throws ClientProtocolException, IOException {
+ public void testMultipleDynamicHandlersInvokeBeforeThrowIOException() throws IOException {
IOException error1 = new IOException();
IOException error3 = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(), List.of(staticOne, staticTwo, staticThree));
@@ -1255,7 +1253,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -1281,7 +1279,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -1293,7 +1291,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testMultipleDynamicHandlersInvokeBeforeThrowRuntimeException() throws ClientProtocolException, IOException {
+ public void testMultipleDynamicHandlersInvokeBeforeThrowRuntimeException() throws IOException {
RuntimeException error1 = new RuntimeException();
RuntimeException error3 = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(), List.of(staticOne, staticTwo, staticThree));
@@ -1332,7 +1330,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -1358,7 +1356,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -1370,7 +1368,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testMultipleDynamicHandlersInvokeAfterThrowIOException() throws ClientProtocolException, IOException {
+ public void testMultipleDynamicHandlersInvokeAfterThrowIOException() throws IOException {
IOException error1 = new IOException();
IOException error3 = new IOException();
client = new ContextHandlingHttpClient(new MockHttpClient(), List.of(staticOne, staticTwo, staticThree));
@@ -1409,7 +1407,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -1435,7 +1433,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -1447,7 +1445,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testMultipleDynamicHandlersInvokeAfterThrowRuntimeException() throws ClientProtocolException, IOException {
+ public void testMultipleDynamicHandlersInvokeAfterThrowRuntimeException() throws IOException {
RuntimeException error1 = new RuntimeException();
RuntimeException error3 = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(), List.of(staticOne, staticTwo, staticThree));
@@ -1486,7 +1484,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -1512,7 +1510,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertNotSame(e, error1);
@@ -1525,7 +1523,7 @@ public class ContextHandlingHttpClientTest {
@Test
- public void testStaticAndDynamicHandlersThrowIOException() throws ClientProtocolException, IOException {
+ public void testStaticAndDynamicHandlersThrowIOException() throws IOException {
IOException staticBeforeError = null;
IOException dynamicAfterError = null;
@@ -1575,7 +1573,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(dynamicHandlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, staticBeforeError);
@@ -1613,7 +1611,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(dynamicHandlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, staticBeforeError);
@@ -1624,7 +1622,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testStaticAndDynamicHandlersThrowRuntimeException() throws ClientProtocolException, IOException {
+ public void testStaticAndDynamicHandlersThrowRuntimeException() throws IOException {
RuntimeException staticBeforeError = new RuntimeException();
RuntimeException dynamicAfterError = new RuntimeException();
client = new ContextHandlingHttpClient(new MockHttpClient(),
@@ -1662,7 +1660,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), staticBeforeError);
@@ -1686,7 +1684,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(handlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e.getCause(), staticBeforeError);
@@ -1697,7 +1695,7 @@ public class ContextHandlingHttpClientTest {
}
@Test
- public void testWrappedClientThrowsIOExceptionInvokeAfterThrowsIOException() throws ClientProtocolException, IOException {
+ public void testWrappedClientThrowsIOExceptionInvokeAfterThrowsIOException() throws IOException {
IOException clientError = null;
IOException dynamicAfterError = null;
@@ -1747,7 +1745,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(dynamicHandlers);
- client.execute(request, responseHandler, context);
+ client.execute(request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, clientError);
@@ -1785,7 +1783,7 @@ public class ContextHandlingHttpClientTest {
try {
context = HttpClientContext.create();
HttpClientSupport.getDynamicContextHandlerList(context).addAll(dynamicHandlers);
- client.execute(target, request, responseHandler, context);
+ client.execute(target, request, context, responseHandler);
Assert.fail("Wrapped client should have thrown");
} catch (IOException e) {
Assert.assertSame(e, clientError);
@@ -1821,7 +1819,7 @@ public class ContextHandlingHttpClientTest {
}
/** {@inheritDoc} */
- public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeBefore(HttpClientContext context, ClassicHttpRequest request) throws IOException {
if (name != null) {
addValue(context, "before-" + name);
}
@@ -1829,7 +1827,7 @@ public class ContextHandlingHttpClientTest {
}
/** {@inheritDoc} */
- public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeAfter(HttpClientContext context, ClassicHttpRequest request) throws IOException {
if (name != null) {
addValue(context, "after-" + name);
}
@@ -1847,7 +1845,7 @@ public class ContextHandlingHttpClientTest {
}
- private static class MockHttpClient extends CloseableHttpClient {
+ private static class MockHttpClient extends AbstractHttpClient {
private Throwable error;
@@ -1857,20 +1855,6 @@ public class ContextHandlingHttpClientTest {
public MockHttpClient(final Throwable throwable) {
error = throwable;
}
-
- /** {@inheritDoc} */
- @Deprecated
- @Override
- public org.apache.http.params.HttpParams getParams() {
- return null;
- }
-
- /** {@inheritDoc} */
- @Deprecated
- @Override
- public org.apache.http.conn.ClientConnectionManager getConnectionManager() {
- return null;
- }
/** {@inheritDoc} */
public void close() throws IOException {
@@ -1878,26 +1862,34 @@ public class ContextHandlingHttpClientTest {
}
/** {@inheritDoc} */
- protected CloseableHttpResponse doExecute(HttpHost target, HttpRequest request, HttpContext context)
- throws IOException, ClientProtocolException {
+ public void close(CloseMode closeMode) {
+ // nothing to do
+ }
+
+ /** {@inheritDoc} */
+ protected ClassicHttpResponse doExecute(HttpHost target, ClassicHttpRequest request, HttpContext context)
+ throws IOException {
ThrowableHelper.checkAndThrowError(error);
return STATIC_RESPONSE_HTTP;
}
-
+
}
- public static class MockResponseHandler implements ResponseHandler<Object> {
+ public static class MockResponseHandler implements HttpClientResponseHandler<Object> {
- public Object handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
+ public Object handleResponse(ClassicHttpResponse response) throws IOException {
return STATIC_RESPONSE_HANDLER;
}
}
- public static class MockCloseableHttpResponse extends BasicHttpResponse implements CloseableHttpResponse {
+ public static class MockClassicHttpResponse extends BasicClassicHttpResponse {
+
+ private static final long serialVersionUID = -3530926876971302045L;
- public MockCloseableHttpResponse(ProtocolVersion ver, int code, String reason) {
- super(ver, code, reason);
+ public MockClassicHttpResponse(ProtocolVersion ver, int code, String reason) {
+ super(code, reason);
+ this.setVersion(ver);
}
public void close() throws IOException {
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/FileCachingHttpClientBuilderTest.java b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/FileCachingHttpClientBuilderTest.java
index b107ecdd..a6d1c115 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/FileCachingHttpClientBuilderTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/FileCachingHttpClientBuilderTest.java
@@ -17,7 +17,7 @@
package net.shibboleth.shared.httpclient;
-import org.apache.http.client.HttpClient;
+import org.apache.hc.client5.http.classic.HttpClient;
import org.testng.annotations.Test;
@SuppressWarnings("javadoc")
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/HttpClientBuilderTest.java b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/HttpClientBuilderTest.java
index 497471d0..17b64a34 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/HttpClientBuilderTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/HttpClientBuilderTest.java
@@ -22,9 +22,9 @@ import java.io.IOException;
import java.time.Duration;
import java.util.List;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ClassicHttpRequest;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -92,12 +92,12 @@ public class HttpClientBuilderTest {
public class TestContextHandler implements HttpClientContextHandler {
/** {@inheritDoc} */
- public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeBefore(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
/** {@inheritDoc} */
- public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeAfter(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/HttpClientSupportTest.java b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/HttpClientSupportTest.java
index 524e6abe..9487fa31 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/HttpClientSupportTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/HttpClientSupportTest.java
@@ -21,8 +21,8 @@ import java.io.IOException;
import java.util.Collections;
import java.util.List;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ClassicHttpRequest;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -134,12 +134,12 @@ public class HttpClientSupportTest {
public class TestContextHandler implements HttpClientContextHandler {
/** {@inheritDoc} */
- public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeBefore(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
/** {@inheritDoc} */
- public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ public void invokeAfter(HttpClientContext context, ClassicHttpRequest request) throws IOException {
}
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/IdleConectionSweeperTest.java b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/IdleConectionSweeperTest.java
deleted file mode 100644
index 4a7fdd0b..00000000
--- a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/IdleConectionSweeperTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the University Corporation for Advanced Internet Development,
- * Inc. (UCAID) under one or more contributor license agreements. See the
- * NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.shared.httpclient;
-
-import java.time.Duration;
-import java.util.Timer;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import net.shibboleth.shared.component.DestroyedComponentException;
-
-/** {@link IdleConnectionSweeper} unit test. */
- at SuppressWarnings("javadoc")
-public class IdleConectionSweeperTest {
-
- private final Duration SWEEP_INTERVAL = Duration.ofMillis(50);
-
- @Test public void test() throws Exception {
- MyCm connectionManager = new MyCm();
-
- IdleConnectionSweeper sweeper = new IdleConnectionSweeper(connectionManager, Duration.ofMillis(30), SWEEP_INTERVAL);
- Thread.yield(); // for luck.
- if (!connectionManager.isCloseCalled()) {
- Thread.sleep(25+SWEEP_INTERVAL.toMillis());
- Thread.yield();
- if (!connectionManager.isCloseCalled()) {
- // Windows sometimes takes its time...
- Thread.sleep(25+SWEEP_INTERVAL.toMillis());
- Thread.yield();
- Assert.assertTrue(connectionManager.isCloseCalled());
- }
- }
-
- sweeper.destroy();
- Assert.assertTrue(sweeper.isDestroyed());
-
- try {
- sweeper.scheduledExecutionTime();
- Assert.fail();
- } catch (DestroyedComponentException e) {
- // expected this
- }
-
- connectionManager = new MyCm();
-
- Timer timer = new Timer(true);
- sweeper = new IdleConnectionSweeper(connectionManager, Duration.ofMillis(30), SWEEP_INTERVAL, timer);
- Thread.yield();
- if (!connectionManager.isCloseCalled()) {
- Thread.sleep(SWEEP_INTERVAL.toMillis());
- Thread.yield();
- int loopCount = 0;
- while (!connectionManager.isCloseCalled()) {
- // Windows sometimes takes its time...
- Thread.sleep(SWEEP_INTERVAL.toMillis());
- Thread.yield();
- Assert.assertTrue(++loopCount != 5); // 5 timed 50 ms is quarter of a second
- }
- }
-
- sweeper.destroy();
- Assert.assertTrue(sweeper.isDestroyed());
-
- try {
- sweeper.scheduledExecutionTime();
- Assert.fail();
- } catch (DestroyedComponentException e) {
- // expected this
- }
- timer.cancel();
- }
-
- private class MyCm extends PoolingHttpClientConnectionManager {
- private boolean closeCalled;
- public void closeIdleConnections(long idletime, TimeUnit timeUnit) {
- closeCalled = true;
- super.closeIdleConnections(idletime, timeUnit);
- }
- public boolean isCloseCalled() {
- return closeCalled;
- }
- }
-}
\ No newline at end of file
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/InMemoryCachingHttpClientBuilderTest.java b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/InMemoryCachingHttpClientBuilderTest.java
index ab4de830..0ce59664 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/httpclient/InMemoryCachingHttpClientBuilderTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/httpclient/InMemoryCachingHttpClientBuilderTest.java
@@ -17,7 +17,7 @@
package net.shibboleth.shared.httpclient;
-import org.apache.http.client.HttpClient;
+import org.apache.hc.client5.http.classic.HttpClient;
import org.testng.annotations.Test;
@SuppressWarnings("javadoc")
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list