Skip to content

Commit

Permalink
Adopt Apache HttpClient 5 for src/main (#1625)
Browse files Browse the repository at this point in the history
* Adopt Apache HttpClient 5 for src/main

* Add copy of HttpClient4Utils in wiremock-webhooks-extension

* Restore Boolean isPersistent

* Verify on a different header since Content-Length no longer returned

* Revert StubMapping changes as compared to master
  • Loading branch information
Tim te Beek committed Oct 14, 2021
1 parent e1e49d9 commit 59e8c00
Show file tree
Hide file tree
Showing 16 changed files with 268 additions and 145 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ dependencies {
"com.fasterxml.jackson.core:jackson-annotations:$versions.jackson",
"com.fasterxml.jackson.core:jackson-databind:$versions.jackson"
compile "org.apache.httpcomponents:httpclient:4.5.13"
compile "org.apache.httpcomponents.client5:httpclient5:5.1"
compile "org.xmlunit:xmlunit-core:$versions.xmlUnit"
compile "org.xmlunit:xmlunit-legacy:$versions.xmlUnit", {
exclude group: 'junit', module: 'junit'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newLinkedHashMap;

class BasicMappingBuilder implements ScenarioMappingBuilder {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,34 @@
import com.github.tomakehurst.wiremock.http.HttpStatus;
import com.github.tomakehurst.wiremock.matching.RequestPattern;
import com.github.tomakehurst.wiremock.matching.StringValuePattern;
import com.github.tomakehurst.wiremock.recording.RecordSpec;
import com.github.tomakehurst.wiremock.recording.RecordSpecBuilder;
import com.github.tomakehurst.wiremock.recording.RecordingStatusResult;
import com.github.tomakehurst.wiremock.recording.SnapshotRecordResult;
import com.github.tomakehurst.wiremock.recording.RecordSpec;
import com.github.tomakehurst.wiremock.security.ClientAuthenticator;
import com.github.tomakehurst.wiremock.security.NotAuthorisedException;
import com.github.tomakehurst.wiremock.stubbing.StubImport;
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import com.github.tomakehurst.wiremock.verification.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;

import static com.github.tomakehurst.wiremock.common.Exceptions.throwUnchecked;
import static com.github.tomakehurst.wiremock.common.HttpClientUtils.getEntityAsStringAndCloseStream;
import static com.github.tomakehurst.wiremock.security.NoClientAuthenticator.noClientAuthenticator;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.http.HttpHeaders.HOST;
import static org.apache.hc.core5.http.HttpHeaders.HOST;

public class HttpAdminClient implements Admin {

Expand Down Expand Up @@ -118,7 +123,7 @@ public HttpAdminClient(String host, int port) {
}

private static StringEntity jsonStringEntity(String json) {
return new StringEntity(json, UTF_8.name());
return new StringEntity(json, StandardCharsets.UTF_8);
}

@Override
Expand Down Expand Up @@ -443,7 +448,7 @@ private <B, R> R executeRequest(RequestSpec requestSpec, PathParams pathParams,

private <B, R> R executeRequest(RequestSpec requestSpec, PathParams pathParams, B requestBody, Class<R> responseType) {
String url = String.format(ADMIN_URL_PREFIX + requestSpec.path(pathParams), scheme, host, port, urlPathPrefix);
RequestBuilder requestBuilder = RequestBuilder
ClassicRequestBuilder requestBuilder = ClassicRequestBuilder
.create(requestSpec.method().getName())
.setUri(url);

Expand All @@ -458,7 +463,7 @@ private <B, R> R executeRequest(RequestSpec requestSpec, PathParams pathParams,
Json.read(responseBodyString, responseType);
}

private String safelyExecuteRequest(String url, HttpUriRequest request) {
private String safelyExecuteRequest(String url, ClassicHttpRequest request) {
if (hostHeader != null) {
request.addHeader(HOST, hostHeader);
}
Expand All @@ -471,7 +476,7 @@ private String safelyExecuteRequest(String url, HttpUriRequest request) {
}

try (CloseableHttpResponse response = httpClient.execute(request)) {
int statusCode = response.getStatusLine().getStatusCode();
int statusCode = response.getCode();
if (HttpStatus.isServerError(statusCode)) {
throw new VerificationException(
"Expected status 2xx for " + url + " but was " + statusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,33 @@
*/
package com.github.tomakehurst.wiremock.common;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import java.io.IOException;

import static com.google.common.base.Charsets.UTF_8;

public class HttpClientUtils {

public static String getEntityAsStringAndCloseStream(HttpResponse httpResponse) {
public static String getEntityAsStringAndCloseStream(ClassicHttpResponse httpResponse) {
HttpEntity entity = httpResponse.getEntity();
if (entity != null) {
try {
String content = EntityUtils.toString(entity, UTF_8.name());
entity.getContent().close();
return content;
} catch (IOException ioe) {
} catch (IOException | ParseException ioe) {
throw new RuntimeException(ioe);
}
}

return null;
}

public static byte[] getEntityAsByteArrayAndCloseStream(HttpResponse httpResponse) {
public static byte[] getEntityAsByteArrayAndCloseStream(ClassicHttpResponse httpResponse) {
HttpEntity entity = httpResponse.getEntity();
if (entity != null) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,9 @@
*/
package com.github.tomakehurst.wiremock.common;

import static com.github.tomakehurst.wiremock.common.LocalNotifier.notifier;
import static com.google.common.base.Splitter.on;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getFirst;
import static org.apache.commons.lang3.StringUtils.isEmpty;

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;

import java.net.MalformedURLException;
import java.net.URL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,39 @@
*/
package com.github.tomakehurst.wiremock.http;

import com.github.tomakehurst.wiremock.common.ssl.KeyStoreSettings;
import com.github.tomakehurst.wiremock.common.ProxySettings;
import com.github.tomakehurst.wiremock.http.ssl.HostVerifyingSSLSocketFactory;
import com.github.tomakehurst.wiremock.http.ssl.SSLContextBuilder;
import com.github.tomakehurst.wiremock.http.ssl.TrustEverythingStrategy;
import com.github.tomakehurst.wiremock.http.ssl.TrustSelfSignedStrategy;
import com.github.tomakehurst.wiremock.http.ssl.TrustSpecificHostsStrategy;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.NoConnectionReuseStrategy;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.TextUtils;

import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableEntryException;
import com.github.tomakehurst.wiremock.common.ssl.KeyStoreSettings;
import com.github.tomakehurst.wiremock.http.ssl.*;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.classic.methods.*;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.util.TextUtils;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;

import java.net.URI;
import java.security.*;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import javax.net.ssl.SSLContext;

import static com.github.tomakehurst.wiremock.common.Exceptions.throwUnchecked;
import static com.github.tomakehurst.wiremock.common.ssl.KeyStoreSettings.NO_STORE;
import static com.github.tomakehurst.wiremock.common.LocalNotifier.notifier;
import static com.github.tomakehurst.wiremock.common.ProxySettings.NO_PROXY;
import static com.github.tomakehurst.wiremock.common.ssl.KeyStoreSettings.NO_STORE;
import static com.github.tomakehurst.wiremock.http.RequestMethod.*;
import static org.apache.commons.lang3.StringUtils.isEmpty;

Expand All @@ -63,13 +56,6 @@ public class HttpClientFactory {
public static final int DEFAULT_MAX_CONNECTIONS = 50;
public static final int DEFAULT_TIMEOUT = 30000;

private static final ConnectionKeepAliveStrategy NO_KEEP_ALIVE = new ConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
return 0;
}
};

public static CloseableHttpClient createClient(
int maxConnections,
int timeoutMilliseconds,
Expand All @@ -85,12 +71,16 @@ public static CloseableHttpClient createClient(
.disableCookieManagement()
.disableRedirectHandling()
.disableContentCompression()
.setMaxConnTotal(maxConnections)
.setMaxConnPerRoute(maxConnections)
.setDefaultRequestConfig(RequestConfig.custom().setStaleConnectionCheckEnabled(true).build())
.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(timeoutMilliseconds).build())
.setConnectionReuseStrategy(NoConnectionReuseStrategy.INSTANCE)
.setKeepAliveStrategy(NO_KEEP_ALIVE);
.setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create()
.setMaxConnPerRoute(maxConnections)
.setMaxConnTotal(maxConnections)
.setValidateAfterInactivity(TimeValue.ofSeconds(5)) // TODO Verify duration
.build())
.setDefaultRequestConfig(RequestConfig.custom()
.setResponseTimeout(Timeout.ofMilliseconds(timeoutMilliseconds))
.build())
.setConnectionReuseStrategy((request, response, context) -> false)
.setKeepAliveStrategy((response, context) -> TimeValue.ZERO_MILLISECONDS);

if (useSystemProperties) {
builder.useSystemProperties();
Expand All @@ -100,21 +90,22 @@ public static CloseableHttpClient createClient(
HttpHost proxyHost = new HttpHost(proxySettings.host(), proxySettings.port());
builder.setProxy(proxyHost);
if(!isEmpty(proxySettings.getUsername()) && !isEmpty(proxySettings.getPassword())) {
builder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
builder.setProxyAuthenticationStrategy(new DefaultAuthenticationStrategy()); // TODO Verify
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(proxySettings.host(), proxySettings.port()),
new UsernamePasswordCredentials(proxySettings.getUsername(), proxySettings.getPassword()));
new UsernamePasswordCredentials(proxySettings.getUsername(), proxySettings.getPassword().toCharArray()));
builder.setDefaultCredentialsProvider(credentialsProvider);
}
}

final SSLContext sslContext = buildSslContext(trustStoreSettings, trustSelfSignedCertificates, trustedHosts);
LayeredConnectionSocketFactory sslSocketFactory = buildSslConnectionSocketFactory(sslContext);
builder.setSSLSocketFactory(sslSocketFactory);
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create().setSSLSocketFactory(sslSocketFactory).build();
builder.setConnectionManager(connectionManager);

return builder.build();
}
}

private static LayeredConnectionSocketFactory buildSslConnectionSocketFactory(final SSLContext sslContext) {
final String[] supportedProtocols = split(System.getProperty("https.protocols"));
Expand Down Expand Up @@ -212,9 +203,9 @@ public static CloseableHttpClient createClient(int maxConnections, int timeoutMi
return createClient(maxConnections, timeoutMilliseconds, NO_PROXY, NO_STORE, true);
}

public static CloseableHttpClient createClient(int timeoutMilliseconds) {
return createClient(DEFAULT_MAX_CONNECTIONS, timeoutMilliseconds);
}
public static CloseableHttpClient createClient(int timeoutMilliseconds) {
return createClient(DEFAULT_MAX_CONNECTIONS, timeoutMilliseconds);
}

public static CloseableHttpClient createClient(ProxySettings proxySettings) {
return createClient(DEFAULT_MAX_CONNECTIONS, DEFAULT_TIMEOUT, proxySettings, NO_STORE, true);
Expand Down Expand Up @@ -244,6 +235,6 @@ else if (method.equals(TRACE))
else if (method.equals(PATCH))
return new HttpPatch(url);
else
return new GenericHttpUriRequest(method.toString(), url);
return new HttpUriRequestBase(method.toString(), URI.create(url));
}
}

0 comments on commit 59e8c00

Please sign in to comment.