diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/ExchangeIdGenerator.java b/httpclient5/src/main/java/org/apache/hc/client5/http/ExchangeIdGenerator.java
new file mode 100644
index 0000000000..fcc48ec666
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/ExchangeIdGenerator.java
@@ -0,0 +1,49 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+package org.apache.hc.client5.http;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+
+/**
+ * Generates exchange identifiers for message exchanges.
+ *
+ * @since 5.7
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public interface ExchangeIdGenerator {
+
+ /**
+ * Generates the next exchange identifier.
+ *
+ * The returned identifier must be unique, non-null, and non-blank.
+ *
+ *
+ * @return the next exchange identifier
+ */
+ String getNextExchangeId();
+}
\ No newline at end of file
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultExechangeIdGenerator.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultExechangeIdGenerator.java
new file mode 100644
index 0000000000..35b60ea413
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultExechangeIdGenerator.java
@@ -0,0 +1,47 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+package org.apache.hc.client5.http.impl;
+
+import org.apache.hc.client5.http.ExchangeIdGenerator;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+
+/**
+ * The default implementation of {@link ExchangeIdGenerator}.
+ *
+ * @since 5.7
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public class DefaultExechangeIdGenerator implements ExchangeIdGenerator {
+
+ public static final ExchangeIdGenerator INSTANCE = new DefaultExechangeIdGenerator();
+
+ @Override
+ public String getNextExchangeId() {
+ return ExecSupport.getNextExchangeId();
+ }
+}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
index f5cfc4de08..e9c213e977 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
@@ -37,6 +37,7 @@
import org.apache.hc.client5.http.AuthenticationStrategy;
import org.apache.hc.client5.http.DnsResolver;
+import org.apache.hc.client5.http.ExchangeIdGenerator;
import org.apache.hc.client5.http.HttpRequestRetryStrategy;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.async.AsyncExecChainHandler;
@@ -51,6 +52,7 @@
import org.apache.hc.client5.http.impl.ChainElement;
import org.apache.hc.client5.http.impl.CookieSpecSupport;
import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
+import org.apache.hc.client5.http.impl.DefaultExechangeIdGenerator;
import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
@@ -182,6 +184,7 @@ private ExecInterceptorEntry(
private LinkedList responseInterceptors;
private LinkedList execInterceptors;
+ private ExchangeIdGenerator exchangeIdGenerator;
private HttpRoutePlanner routePlanner;
private RedirectStrategy redirectStrategy;
private HttpRequestRetryStrategy retryStrategy;
@@ -563,6 +566,17 @@ public final H2AsyncClientBuilder setDefaultHeaders(final Collection extends H
return this;
}
+ /**
+ * Sets {@link ExchangeIdGenerator} instance.
+ *
+ * @return this instance.
+ * @since 5.7
+ */
+ public final H2AsyncClientBuilder setExchangeIdGenerator(final ExchangeIdGenerator exchangeIdGenerator) {
+ this.exchangeIdGenerator = exchangeIdGenerator;
+ return this;
+ }
+
/**
* Sets {@link HttpRoutePlanner} instance.
*
@@ -855,6 +869,11 @@ public CloseableHttpAsyncClient build() {
ChainElement.RETRY.name());
}
+ ExchangeIdGenerator exchangeIdGeneratorCopy = this.exchangeIdGenerator;
+ if (exchangeIdGeneratorCopy == null) {
+ exchangeIdGeneratorCopy = DefaultExechangeIdGenerator.INSTANCE;
+ }
+
HttpRoutePlanner routePlannerCopy = this.routePlanner;
if (routePlannerCopy == null) {
SchemePortResolver schemePortResolverCopy = this.schemePortResolver;
@@ -983,6 +1002,7 @@ public CloseableHttpAsyncClient build() {
pushConsumerRegistry,
threadFactory != null ? threadFactory : new DefaultThreadFactory("httpclient-main", true),
connPool,
+ exchangeIdGeneratorCopy,
routePlannerCopy,
cookieSpecRegistryCopy,
authSchemeRegistryCopy,
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
index 1c39b2c314..e24df05267 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
@@ -42,6 +42,7 @@
import org.apache.hc.client5.http.AuthenticationStrategy;
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
import org.apache.hc.client5.http.EarlyHintsListener;
+import org.apache.hc.client5.http.ExchangeIdGenerator;
import org.apache.hc.client5.http.HttpRequestRetryStrategy;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.UserTokenHandler;
@@ -59,6 +60,7 @@
import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
import org.apache.hc.client5.http.impl.DefaultClientConnectionReuseStrategy;
import org.apache.hc.client5.http.impl.DefaultConnectionKeepAliveStrategy;
+import org.apache.hc.client5.http.impl.DefaultExechangeIdGenerator;
import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
@@ -233,6 +235,7 @@ private ExecInterceptorEntry(
private LinkedList responseInterceptors;
private LinkedList execInterceptors;
+ private ExchangeIdGenerator exchangeIdGenerator;
private HttpRoutePlanner routePlanner;
private RedirectStrategy redirectStrategy;
private HttpRequestRetryStrategy retryStrategy;
@@ -695,6 +698,17 @@ public final HttpAsyncClientBuilder setProxy(final HttpHost proxy) {
return this;
}
+ /**
+ * Sets {@link ExchangeIdGenerator} instance.
+ *
+ * @return this instance.
+ * @since 5.7
+ */
+ public final HttpAsyncClientBuilder setExchangeIdGenerator(final ExchangeIdGenerator exchangeIdGenerator) {
+ this.exchangeIdGenerator = exchangeIdGenerator;
+ return this;
+ }
+
/**
* Sets {@link HttpRoutePlanner} instance.
*
@@ -1140,6 +1154,10 @@ public CloseableHttpAsyncClient build() {
execChainDefinition.addFirst(new TlsRequiredAsyncExec(), ChainElement.TLS_REQUIRED.name());
}
+ ExchangeIdGenerator exchangeIdGeneratorCopy = this.exchangeIdGenerator;
+ if (exchangeIdGeneratorCopy == null) {
+ exchangeIdGeneratorCopy = DefaultExechangeIdGenerator.INSTANCE;
+ }
HttpRoutePlanner routePlannerCopy = this.routePlanner;
if (routePlannerCopy == null) {
@@ -1277,6 +1295,7 @@ public CloseableHttpAsyncClient build() {
pushConsumerRegistry,
threadFactory != null ? threadFactory : new DefaultThreadFactory("httpclient-main", true),
connManagerCopy,
+ exchangeIdGeneratorCopy,
routePlannerCopy,
tlsConfig,
cookieSpecRegistryCopy,
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
index 6c1679604f..5527a298e0 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
@@ -40,6 +40,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
+import org.apache.hc.client5.http.ExchangeIdGenerator;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.async.AsyncExecCallback;
import org.apache.hc.client5.http.async.AsyncExecChain;
@@ -50,7 +51,6 @@
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.CookieSpecFactory;
import org.apache.hc.client5.http.cookie.CookieStore;
-import org.apache.hc.client5.http.impl.ExecSupport;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.routing.RoutingSupport;
import org.apache.hc.core5.concurrent.Cancellable;
@@ -88,6 +88,7 @@ abstract class InternalAbstractHttpAsyncClient extends AbstractHttpAsyncClientBa
private static final Logger LOG = LoggerFactory.getLogger(InternalAbstractHttpAsyncClient.class);
private final AsyncExecChainElement execChain;
+ private final ExchangeIdGenerator exchangeIdGenerator;
private final Lookup cookieSpecRegistry;
private final Lookup authSchemeRegistry;
private final CookieStore cookieStore;
@@ -103,6 +104,7 @@ abstract class InternalAbstractHttpAsyncClient extends AbstractHttpAsyncClientBa
final AsyncPushConsumerRegistry pushConsumerRegistry,
final ThreadFactory threadFactory,
final AsyncExecChainElement execChain,
+ final ExchangeIdGenerator exchangeIdGenerator,
final Lookup cookieSpecRegistry,
final Lookup authSchemeRegistry,
final CookieStore cookieStore,
@@ -112,6 +114,7 @@ abstract class InternalAbstractHttpAsyncClient extends AbstractHttpAsyncClientBa
final List closeables) {
super(ioReactor, pushConsumerRegistry, threadFactory);
this.execChain = execChain;
+ this.exchangeIdGenerator = exchangeIdGenerator;
this.cookieSpecRegistry = cookieSpecRegistry;
this.authSchemeRegistry = authSchemeRegistry;
this.cookieStore = cookieStore;
@@ -232,7 +235,7 @@ protected Future doExecute(
resolvedTarget,
request,
clientContext);
- final String exchangeId = ExecSupport.getNextExchangeId();
+ final String exchangeId = exchangeIdGenerator.getNextExchangeId();
clientContext.setExchangeId(exchangeId);
if (LOG.isDebugEnabled()) {
LOG.debug("{} preparing request execution", exchangeId);
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncClient.java
index 3c27051000..1093dc22c9 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncClient.java
@@ -31,6 +31,7 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.hc.client5.http.ExchangeIdGenerator;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.async.AsyncExecRuntime;
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
@@ -79,6 +80,7 @@ public final class InternalH2AsyncClient extends InternalAbstractHttpAsyncClient
final AsyncPushConsumerRegistry pushConsumerRegistry,
final ThreadFactory threadFactory,
final InternalH2ConnPool connPool,
+ final ExchangeIdGenerator exchangeIdGenerator,
final HttpRoutePlanner routePlanner,
final Lookup cookieSpecRegistry,
final Lookup authSchemeRegistry,
@@ -87,7 +89,7 @@ public final class InternalH2AsyncClient extends InternalAbstractHttpAsyncClient
final RequestConfig defaultConfig,
final List closeables,
final int maxQueuedRequests) {
- super(ioReactor, pushConsumerRegistry, threadFactory, execChain,
+ super(ioReactor, pushConsumerRegistry, threadFactory, execChain, exchangeIdGenerator,
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider, HttpClientContext::castOrCreate,
defaultConfig, closeables);
this.connPool = connPool;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
index 1604039f30..2962bc1f28 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
@@ -32,6 +32,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
+import org.apache.hc.client5.http.ExchangeIdGenerator;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.async.AsyncExecRuntime;
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
@@ -85,6 +86,7 @@ public final class InternalHttpAsyncClient extends InternalAbstractHttpAsyncClie
final AsyncPushConsumerRegistry pushConsumerRegistry,
final ThreadFactory threadFactory,
final AsyncClientConnectionManager manager,
+ final ExchangeIdGenerator exchangeIdGenerator,
final HttpRoutePlanner routePlanner,
final TlsConfig tlsConfig,
final Lookup cookieSpecRegistry,
@@ -95,7 +97,7 @@ public final class InternalHttpAsyncClient extends InternalAbstractHttpAsyncClie
final RequestConfig defaultConfig,
final List closeables,
final int maxQueuedRequests) {
- super(ioReactor, pushConsumerRegistry, threadFactory, execChain,
+ super(ioReactor, pushConsumerRegistry, threadFactory, execChain, exchangeIdGenerator,
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider, contextAdaptor,
defaultConfig, closeables);
this.manager = manager;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java
index 671b7e5de7..ef130620a8 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java
@@ -41,6 +41,7 @@
import org.apache.hc.client5.http.AuthenticationStrategy;
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
+import org.apache.hc.client5.http.ExchangeIdGenerator;
import org.apache.hc.client5.http.HttpRequestRetryStrategy;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.UserTokenHandler;
@@ -61,6 +62,7 @@
import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
import org.apache.hc.client5.http.impl.DefaultClientConnectionReuseStrategy;
import org.apache.hc.client5.http.impl.DefaultConnectionKeepAliveStrategy;
+import org.apache.hc.client5.http.impl.DefaultExechangeIdGenerator;
import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
@@ -194,6 +196,7 @@ private ExecInterceptorEntry(
}
private HttpRequestExecutor requestExec;
+ private ExchangeIdGenerator exchangeIdGenerator;
private HttpClientConnectionManager connManager;
private boolean connManagerShared;
private SchemePortResolver schemePortResolver;
@@ -257,6 +260,17 @@ public final HttpClientBuilder setRequestExecutor(final HttpRequestExecutor requ
return this;
}
+ /**
+ * Sets {@link ExchangeIdGenerator} instance.
+ *
+ * @return this instance.
+ * @since 5.7
+ */
+ public final HttpClientBuilder setExchangeIdGenerator(final ExchangeIdGenerator exchangeIdGenerator) {
+ this.exchangeIdGenerator = exchangeIdGenerator;
+ return this;
+ }
+
/**
* Sets {@link HttpClientConnectionManager} instance.
*
@@ -865,6 +879,10 @@ public CloseableHttpClient build() {
if (requestExecCopy == null) {
requestExecCopy = new HttpRequestExecutor();
}
+ ExchangeIdGenerator exchangeIdGeneratorCopy = this.exchangeIdGenerator;
+ if (exchangeIdGeneratorCopy == null) {
+ exchangeIdGeneratorCopy = DefaultExechangeIdGenerator.INSTANCE;
+ }
HttpClientConnectionManager connManagerCopy = this.connManager;
if (connManagerCopy == null) {
final PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create();
@@ -1139,6 +1157,7 @@ public CloseableHttpClient build() {
return new InternalHttpClient(
connManagerCopy,
requestExecCopy,
+ exchangeIdGeneratorCopy,
execChain,
routePlannerCopy,
cookieSpecRegistryCopy,
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/InternalHttpClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/InternalHttpClient.java
index 07265fcb4b..c4674d362f 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/InternalHttpClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/InternalHttpClient.java
@@ -34,6 +34,7 @@
import java.util.function.Function;
import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.ExchangeIdGenerator;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
import org.apache.hc.client5.http.auth.CredentialsProvider;
@@ -43,7 +44,6 @@
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.CookieSpecFactory;
import org.apache.hc.client5.http.cookie.CookieStore;
-import org.apache.hc.client5.http.impl.ExecSupport;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.routing.HttpRoutePlanner;
@@ -85,6 +85,7 @@ class InternalHttpClient extends CloseableHttpClient implements Configurable {
private final HttpClientConnectionManager connManager;
private final HttpRequestExecutor requestExecutor;
+ private final ExchangeIdGenerator exchangeIdGenerator;
private final ExecChainElement execChain;
private final HttpRoutePlanner routePlanner;
private final Lookup cookieSpecRegistry;
@@ -98,6 +99,7 @@ class InternalHttpClient extends CloseableHttpClient implements Configurable {
public InternalHttpClient(
final HttpClientConnectionManager connManager,
final HttpRequestExecutor requestExecutor,
+ final ExchangeIdGenerator exchangeIdGenerator,
final ExecChainElement execChain,
final HttpRoutePlanner routePlanner,
final Lookup cookieSpecRegistry,
@@ -110,6 +112,7 @@ public InternalHttpClient(
super();
this.connManager = Args.notNull(connManager, "Connection manager");
this.requestExecutor = Args.notNull(requestExecutor, "Request executor");
+ this.exchangeIdGenerator = Args.notNull(exchangeIdGenerator, "Exchange id generator");
this.execChain = Args.notNull(execChain, "Execution chain");
this.routePlanner = Args.notNull(routePlanner, "Route planner");
this.cookieSpecRegistry = cookieSpecRegistry;
@@ -173,7 +176,7 @@ protected CloseableHttpResponse doExecute(
resolvedTarget,
request,
localcontext);
- final String exchangeId = ExecSupport.getNextExchangeId();
+ final String exchangeId = exchangeIdGenerator.getNextExchangeId();
localcontext.setExchangeId(exchangeId);
if (LOG.isDebugEnabled()) {
LOG.debug("{} preparing request execution", exchangeId);
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestInternalHttpClient.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestInternalHttpClient.java
index bbe7292dd2..2518d39efb 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestInternalHttpClient.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestInternalHttpClient.java
@@ -31,6 +31,7 @@
import java.util.Arrays;
import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.ExchangeIdGenerator;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
import org.apache.hc.client5.http.auth.CredentialsProvider;
@@ -39,6 +40,7 @@
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.CookieSpecFactory;
import org.apache.hc.client5.http.cookie.CookieStore;
+import org.apache.hc.client5.http.impl.ExecSupport;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.routing.HttpRoutePlanner;
@@ -69,6 +71,8 @@ class TestInternalHttpClient {
@Mock
private ExecChainHandler execChain;
@Mock
+ private ExchangeIdGenerator exchangeIdGenerator;
+ @Mock
private HttpRoutePlanner routePlanner;
@Mock
private Lookup cookieSpecRegistry;
@@ -90,10 +94,10 @@ class TestInternalHttpClient {
@BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
- client = new InternalHttpClient(connManager, requestExecutor, new ExecChainElement(execChain, null), routePlanner,
+ client = new InternalHttpClient(connManager, requestExecutor, exchangeIdGenerator,
+ new ExecChainElement(execChain, null), routePlanner,
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider,
HttpClientContext::castOrCreate, defaultConfig, Arrays.asList(closeable1, closeable2));
-
}
@Test
@@ -101,6 +105,7 @@ void testExecute() throws Exception {
final HttpGet httpget = new HttpGet("http://somehost/stuff");
final HttpRoute route = new HttpRoute(new HttpHost("somehost", 80));
+ Mockito.when(exchangeIdGenerator.getNextExchangeId()).thenReturn(ExecSupport.getNextExchangeId());
Mockito.when(routePlanner.determineRoute(
Mockito.eq(new HttpHost("somehost")),
Mockito.any(),
@@ -122,6 +127,7 @@ void testExecuteHttpException() throws Exception {
final HttpGet httpget = new HttpGet("http://somehost/stuff");
final HttpRoute route = new HttpRoute(new HttpHost("somehost", 80));
+ Mockito.when(exchangeIdGenerator.getNextExchangeId()).thenReturn(ExecSupport.getNextExchangeId());
Mockito.when(routePlanner.determineRoute(
Mockito.eq(new HttpHost("somehost")),
Mockito.any(),
@@ -143,6 +149,7 @@ void testExecuteDefaultContext() throws Exception {
final HttpGet httpget = new HttpGet("http://somehost/stuff");
final HttpRoute route = new HttpRoute(new HttpHost("somehost", 80));
+ Mockito.when(exchangeIdGenerator.getNextExchangeId()).thenReturn(ExecSupport.getNextExchangeId());
Mockito.when(routePlanner.determineRoute(
Mockito.eq(new HttpHost("somehost")),
Mockito.any(),
@@ -166,6 +173,7 @@ void testExecuteRequestConfig() throws Exception {
final HttpGet httpget = new HttpGet("http://somehost/stuff");
final HttpRoute route = new HttpRoute(new HttpHost("somehost", 80));
+ Mockito.when(exchangeIdGenerator.getNextExchangeId()).thenReturn(ExecSupport.getNextExchangeId());
Mockito.when(routePlanner.determineRoute(
Mockito.eq(new HttpHost("somehost")),
Mockito.any(),
@@ -187,6 +195,7 @@ void testExecuteLocalContext() throws Exception {
final HttpGet httpget = new HttpGet("http://somehost/stuff");
final HttpRoute route = new HttpRoute(new HttpHost("somehost", 80));
+ Mockito.when(exchangeIdGenerator.getNextExchangeId()).thenReturn(ExecSupport.getNextExchangeId());
Mockito.when(routePlanner.determineRoute(
Mockito.eq(new HttpHost("somehost")),
Mockito.any(),
@@ -240,6 +249,7 @@ void testClientCloseIOException() throws Exception {
void testDoExecuteThrowsWhenNoTargetOrHost() throws Exception {
final ClassicHttpRequest request = ClassicRequestBuilder.get("/foo").build();
final HttpClientContext context = HttpClientContext.create();
+ Mockito.when(exchangeIdGenerator.getNextExchangeId()).thenReturn(ExecSupport.getNextExchangeId());
Mockito.when(routePlanner.determineRoute(
Mockito.eq(null),
Mockito.any(),
@@ -247,4 +257,22 @@ void testDoExecuteThrowsWhenNoTargetOrHost() throws Exception {
Assertions.assertThrows(ClientProtocolException.class, () ->
client.executeOpen(null, request, context));
}
+
+ @Test
+ void testExchangeIdGenerator() throws Exception {
+ final HttpGet httpget = new HttpGet("http://somehost/stuff");
+ final HttpRoute route = new HttpRoute(new HttpHost("somehost", 80));
+
+ Mockito.when(exchangeIdGenerator.getNextExchangeId()).thenReturn(ExecSupport.getNextExchangeId());
+ Mockito.when(routePlanner.determineRoute(
+ Mockito.eq(new HttpHost("somehost")),
+ Mockito.any(),
+ Mockito.any())).thenReturn(route);
+ Mockito.when(execChain.execute(
+ Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(
+ CloseableHttpResponse.adapt(new BasicClassicHttpResponse(200)));
+
+ client.execute(httpget, response -> null);
+ Mockito.verify(exchangeIdGenerator).getNextExchangeId();
+ }
}