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 69f0119 commit ed76479
Showing 1 changed file with 36 additions and 9 deletions.
45 changes: 36 additions & 9 deletions java11/src/main/java/feign/http2client/Http2Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

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 @@ -39,6 +40,7 @@
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;
import feign.AsyncClient;
Expand All @@ -54,6 +56,8 @@ 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:
* <ul>
Expand Down Expand Up @@ -140,15 +144,24 @@ 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 @@ -162,6 +175,20 @@ 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()
Expand Down

0 comments on commit ed76479

Please sign in to comment.