diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-05-11 13:32:09 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-05-11 13:32:09 +0200 |
commit | 7ac7e6e3c39fd80b24c38561949466e4fc00921a (patch) | |
tree | 47245435575610ae2365f7e302d28e08eda40daa /vespa-feed-client | |
parent | d620a96865da85cef199a1b73e10dbeeacca99cf (diff) |
Construct underlying apache httpclient5 builder
Diffstat (limited to 'vespa-feed-client')
-rw-r--r-- | vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java | 30 | ||||
-rw-r--r-- | vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java | 73 |
2 files changed, 103 insertions, 0 deletions
diff --git a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java index e49d253a321..9e5f2a53a8d 100644 --- a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java +++ b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java @@ -1,14 +1,44 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.feed.client; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + /** + * Builder for creating a {@link FeedClient} instance. + * * @author bjorncs */ public class FeedClientBuilder { + SSLContext sslContext; + HostnameVerifier hostnameVerifier; + final Map<String, Supplier<String>> requestHeaders = new HashMap<>(); + URI endpoint; + Integer maxConnections; + public static FeedClientBuilder create() { return new FeedClientBuilder(); } private FeedClientBuilder() {} + public FeedClientBuilder setMaxConnection(int max) { this.maxConnections = max; return this; } + + public FeedClientBuilder setEndpoint(URI endpoint) { this.endpoint = endpoint; return this; } + + public FeedClientBuilder setSslContext(SSLContext context) { this.sslContext = context; return this; } + + public FeedClientBuilder setHostnameVerifier(HostnameVerifier verifier) { this.hostnameVerifier = verifier; return this; } + + public FeedClientBuilder addRequestHeader(String name, String value) { return addRequestHeader(name, () -> value); } + + public FeedClientBuilder addRequestHeader(String name, Supplier<String> valueSupplier) { + this.requestHeaders.put(name, valueSupplier); + return this; + } + public FeedClient build() { return new HttpFeedClient(this); } } diff --git a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java index 6cf56ac9cdd..a7e39001117 100644 --- a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java +++ b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java @@ -1,15 +1,85 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.feed.client; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.http2.config.H2Config; +import org.apache.hc.core5.pool.PoolConcurrencyPolicy; +import org.apache.hc.core5.reactor.IOReactorConfig; +import org.apache.hc.core5.util.TimeValue; +import org.apache.hc.core5.util.Timeout; + +import java.io.IOException; +import java.net.URI; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Future; +import java.util.function.Supplier; /** + * HTTP implementation of {@link FeedClient} + * * @author bjorncs */ class HttpFeedClient implements FeedClient { + private final CloseableHttpAsyncClient httpClient; + private final URI endpoint; + private final Map<String, Supplier<String>> requestHeaders; + HttpFeedClient(FeedClientBuilder builder) { + this.httpClient = createHttpClient(builder); + this.endpoint = getEndpoint(builder); + this.requestHeaders = new HashMap<>(builder.requestHeaders); + } + + private static CloseableHttpAsyncClient createHttpClient(FeedClientBuilder builder) { + HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClientBuilder.create() + .setUserAgent(String.format("vespa-feed-client/%s", Vespa.VERSION)) + .setDefaultHeaders(Collections.singletonList(new BasicHeader("Vespa-Client-Version", Vespa.VERSION))) + .disableCookieManagement() + .disableRedirectHandling() + .disableConnectionState() + .setIOReactorConfig(IOReactorConfig.custom() + .setSoTimeout(Timeout.ofSeconds(10)) + .build()) + .setDefaultRequestConfig( + RequestConfig.custom() + .setConnectTimeout(Timeout.ofSeconds(10)) + .setConnectionRequestTimeout(Timeout.DISABLED) + .setResponseTimeout(Timeout.ofMinutes(5)) + .build()) + .setH2Config(H2Config.custom() + .setMaxConcurrentStreams(128) + .setPushEnabled(false) + .build()); + int maxConnections = builder.maxConnections != null ? builder.maxConnections : 4; + PoolingAsyncClientConnectionManagerBuilder connectionManagerBuilder = PoolingAsyncClientConnectionManagerBuilder.create() + .setConnectionTimeToLive(TimeValue.ofMinutes(10)) + .setMaxConnTotal(maxConnections) + .setMaxConnPerRoute(maxConnections) + .setPoolConcurrencyPolicy(PoolConcurrencyPolicy.LAX); + if (builder.sslContext != null) { + ClientTlsStrategyBuilder tlsStrategyBuilder = ClientTlsStrategyBuilder.create() + .setSslContext(builder.sslContext); + if (builder.hostnameVerifier != null) { + tlsStrategyBuilder.setHostnameVerifier(builder.hostnameVerifier); + } + connectionManagerBuilder.setTlsStrategy(tlsStrategyBuilder.build()); + } + httpClientBuilder.setConnectionManager(connectionManagerBuilder.build()); + return httpClientBuilder.build(); + } + + private static URI getEndpoint(FeedClientBuilder builder) { + if (builder.endpoint == null) throw new IllegalArgumentException("Endpoint must be specified"); + return builder.endpoint; } @Override @@ -26,4 +96,7 @@ class HttpFeedClient implements FeedClient { public Future<Result> update(String documentId, String documentJson, OperationParameters params, ResultCallback callback) { return null; } + + @Override public void close() throws IOException { this.httpClient.close(); } + } |