Skip to content

Commit

Permalink
Http2Client: added clients cache (#2405)
Browse files Browse the repository at this point in the history
  • Loading branch information
illia2m4ch authored May 13, 2024
1 parent 81168f1 commit 5099c0f
Showing 1 changed file with 42 additions and 10 deletions.
52 changes: 42 additions & 10 deletions java11/src/main/java/feign/http2client/Http2Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import feign.Util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
Expand All @@ -48,13 +49,16 @@
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Http2Client implements Client, AsyncClient<Object> {

private final HttpClient client;

private final Map<Integer, SoftReference<HttpClient>> clients = new ConcurrentHashMap<>();

/**
* Creates the new Http2Client using following defaults:
*
Expand Down Expand Up @@ -139,16 +143,26 @@ private HttpClient getOrCreateClient(Options options) {
if (doesClientConfigurationDiffer(options)) {
// create a new client from the existing one - but with connectTimeout and followRedirect
// settings from options
java.net.http.HttpClient.Builder builder =
newClientBuilder(options)
.sslContext(client.sslContext())
.sslParameters(client.sslParameters())
.version(client.version());
client.authenticator().ifPresent(builder::authenticator);
client.cookieHandler().ifPresent(builder::cookieHandler);
client.executor().ifPresent(builder::executor);
client.proxy().ifPresent(builder::proxy);
return builder.build();
final int clientKey = createClientKey(options);

SoftReference<HttpClient> requestScopedSoftReference = clients.get(clientKey);
HttpClient requestScoped =
requestScopedSoftReference == null ? null : requestScopedSoftReference.get();

if (requestScoped == null) {
java.net.http.HttpClient.Builder builder =
newClientBuilder(options)
.sslContext(client.sslContext())
.sslParameters(client.sslParameters())
.version(client.version());
client.authenticator().ifPresent(builder::authenticator);
client.cookieHandler().ifPresent(builder::cookieHandler);
client.executor().ifPresent(builder::executor);
client.proxy().ifPresent(builder::proxy);
requestScoped = builder.build();
clients.put(clientKey, new SoftReference<>(requestScoped));
}
return requestScoped;
}
return client;
}
Expand All @@ -163,6 +177,24 @@ private boolean doesClientConfigurationDiffer(Options options) {
.orElse(true);
}

/**
* Creates integer key that represents {@link Options} settings based on {@link
* Http2Client#doesClientConfigurationDiffer(Options)} method
*
* @param options value
* @return integer key
*/
public int createClientKey(feign.Request.Options options) {
int key = options.connectTimeoutMillis();
if (options.isFollowRedirects()) {
key |=
1
<< 31; // connectTimeoutMillis always positive, so we can use first sign bit for
// isFollowRedirects flag
}
return key;
}

private static java.net.http.HttpClient.Builder newClientBuilder(Options options) {
return HttpClient.newBuilder()
.followRedirects(options.isFollowRedirects() ? Redirect.ALWAYS : Redirect.NEVER)
Expand Down

0 comments on commit 5099c0f

Please sign in to comment.