Skip to content

Commit 1b73b49

Browse files
authored
Merge pull request #58 from MosheElisha/new_httpClientContext_for_every_request
New http client context for every request
2 parents d5d6890 + 6a78335 commit 1b73b49

File tree

3 files changed

+96
-16
lines changed

3 files changed

+96
-16
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>org.sourcelab</groupId>
88
<artifactId>kafka-connect-client</artifactId>
9-
<version>3.1.2</version>
9+
<version>3.1.3-SNAPSHOT</version>
1010
<packaging>jar</packaging>
1111

1212
<!-- Require Maven 3.3.9 -->
@@ -386,4 +386,4 @@
386386
</build>
387387
</profile>
388388
</profiles>
389-
</project>
389+
</project>

src/main/java/org/sourcelab/kafka/connect/apiclient/rest/HttpClientRestClient.java

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.http.client.methods.HttpGet;
3131
import org.apache.http.client.methods.HttpPost;
3232
import org.apache.http.client.methods.HttpPut;
33+
import org.apache.http.client.methods.HttpUriRequest;
3334
import org.apache.http.client.protocol.HttpClientContext;
3435
import org.apache.http.client.utils.URIBuilder;
3536
import org.apache.http.entity.StringEntity;
@@ -85,7 +86,15 @@ public class HttpClientRestClient implements RestClient {
8586
*/
8687
private CloseableHttpClient httpClient;
8788

88-
private HttpClientContext httpClientContext;
89+
/**
90+
* The AuthCache used when creating the HttpClientContext.
91+
*/
92+
private AuthCache authCache;
93+
94+
/**
95+
* The CredentialsProvider used when creating the HttpClientContext.
96+
*/
97+
private CredentialsProvider credsProvider;
8998

9099
/**
91100
* Constructor.
@@ -121,13 +130,10 @@ public void init(final Configuration configuration) {
121130
requestConfigBuilder.setConnectTimeout(configuration.getRequestTimeoutInSeconds() * 1_000);
122131

123132
// Define our Credentials Provider
124-
final CredentialsProvider credsProvider = new BasicCredentialsProvider();
125-
126-
// Define our context
127-
httpClientContext = HttpClientContext.create();
133+
credsProvider = new BasicCredentialsProvider();
128134

129135
// Define our auth cache
130-
final AuthCache authCache = new BasicAuthCache();
136+
authCache = new BasicAuthCache();
131137

132138
// If we have a configured proxy host
133139
if (configuration.getProxyHost() != null) {
@@ -180,10 +186,6 @@ public void init(final Configuration configuration) {
180186
}
181187
}
182188

183-
// Configure context.
184-
httpClientContext.setAuthCache(authCache);
185-
httpClientContext.setCredentialsProvider(credsProvider);
186-
187189
// Attach Credentials provider to client builder.
188190
clientBuilder.setDefaultCredentialsProvider(credsProvider);
189191

@@ -272,7 +274,7 @@ private <T> T submitGetRequest(final String url, final Map<String, String> getPa
272274
logger.debug("Executing request {}", get.getRequestLine());
273275

274276
// Execute and return
275-
return httpClient.execute(get, responseHandler, httpClientContext);
277+
return execute(get, responseHandler);
276278
} catch (final ClientProtocolException | SocketException | URISyntaxException | SSLHandshakeException connectionException) {
277279
// Typically this is a connection or certificate issue.
278280
throw new ConnectionException(connectionException.getMessage(), connectionException);
@@ -305,7 +307,7 @@ private <T> T submitPostRequest(final String url, final Object requestBody, fina
305307
logger.debug("Executing request {} with {}", post.getRequestLine(), jsonPayloadStr);
306308

307309
// Execute and return
308-
return httpClient.execute(post, responseHandler, httpClientContext);
310+
return execute(post, responseHandler);
309311
} catch (final ClientProtocolException | SocketException | SSLHandshakeException connectionException) {
310312
// Typically this is a connection issue.
311313
throw new ConnectionException(connectionException.getMessage(), connectionException);
@@ -337,7 +339,7 @@ private <T> T submitPutRequest(final String url, final Object requestBody, final
337339
logger.debug("Executing request {} with {}", put.getRequestLine(), jsonPayloadStr);
338340

339341
// Execute and return
340-
return httpClient.execute(put, responseHandler, httpClientContext);
342+
return execute(put, responseHandler);
341343
} catch (final ClientProtocolException | SocketException | SSLHandshakeException connectionException) {
342344
// Typically this is a connection issue.
343345
throw new ConnectionException(connectionException.getMessage(), connectionException);
@@ -368,7 +370,7 @@ private <T> T submitDeleteRequest(final String url, final Object requestBody, fi
368370
logger.debug("Executing request {} with {}", delete.getRequestLine(), jsonPayloadStr);
369371

370372
// Execute and return
371-
return httpClient.execute(delete, responseHandler, httpClientContext);
373+
return execute(delete, responseHandler);
372374
} catch (final ClientProtocolException | SocketException | SSLHandshakeException connectionException) {
373375
// Typically this is a connection issue.
374376
throw new ConnectionException(connectionException.getMessage(), connectionException);
@@ -378,6 +380,18 @@ private <T> T submitDeleteRequest(final String url, final Object requestBody, fi
378380
}
379381
}
380382

383+
/**
384+
* Creates an HttpClientContext and executes the HTTP request.
385+
*
386+
* @param request The request to execute
387+
* @param responseHandler The response Handler to use to parse the response
388+
* @param <T> The type that ResponseHandler returns.
389+
* @return Parsed response.
390+
*/
391+
private <T> T execute(HttpUriRequest request, ResponseHandler<T> responseHandler) throws IOException {
392+
return httpClient.execute(request, responseHandler, createHttpClientContext());
393+
}
394+
381395
/**
382396
* Internal helper method for generating URLs w/ the appropriate API host and API version.
383397
* @param endPoint The end point you want to hit.
@@ -386,4 +400,18 @@ private <T> T submitDeleteRequest(final String url, final Object requestBody, fi
386400
private String constructApiUrl(final String endPoint) {
387401
return configuration.getApiHost() + endPoint;
388402
}
403+
404+
/**
405+
* Creates a new HttpClientContext with the authCache and credsProvider.
406+
* @return the created HttpClientContext.
407+
*/
408+
private HttpClientContext createHttpClientContext() {
409+
// Define our context
410+
HttpClientContext httpClientContext = HttpClientContext.create();
411+
// Configure context.
412+
httpClientContext.setAuthCache(authCache);
413+
httpClientContext.setCredentialsProvider(credsProvider);
414+
415+
return httpClientContext;
416+
}
389417
}

src/test/java/org/sourcelab/kafka/connect/apiclient/rest/HttpClientRestClientTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
package org.sourcelab.kafka.connect.apiclient.rest;
1919

20+
import org.apache.http.client.ResponseHandler;
21+
import org.apache.http.client.methods.HttpUriRequest;
22+
import org.apache.http.client.protocol.HttpClientContext;
23+
import org.apache.http.impl.client.CloseableHttpClient;
2024
import org.apache.http.impl.client.HttpClientBuilder;
2125
import org.junit.BeforeClass;
2226
import org.junit.Test;
@@ -26,10 +30,16 @@
2630
import testserver.TestHttpServer;
2731

2832
import java.io.File;
33+
import java.io.IOException;
34+
import java.util.concurrent.atomic.AtomicReference;
2935

3036
import static org.junit.Assert.assertEquals;
37+
import static org.junit.Assert.assertNotSame;
38+
import static org.mockito.Mockito.any;
3139
import static org.mockito.Mockito.mock;
40+
import static org.mockito.Mockito.times;
3241
import static org.mockito.Mockito.verify;
42+
import static org.mockito.Mockito.when;
3343

3444
public class HttpClientRestClientTest {
3545

@@ -103,6 +113,48 @@ protected HttpClientBuilder createHttpClientBuilder() {
103113
verify(builderMock).build();
104114
}
105115

116+
/**
117+
* Test that the every request uses a new HttpClientContext.
118+
*/
119+
@Test
120+
public void doHttp_verifyNewHttpContextOnEveryRequest() throws IOException {
121+
AtomicReference<HttpClientContext> firstContext = new AtomicReference<>();
122+
CloseableHttpClient httpClientMock = mock(CloseableHttpClient.class);
123+
when(httpClientMock.execute(any(HttpUriRequest.class), any(ResponseHandler.class), any(HttpClientContext.class)))
124+
.then(invocation -> {
125+
// Store the context of first request
126+
HttpClientContext context = invocation.getArgument(2);
127+
firstContext.set(context);
128+
return null;
129+
})
130+
.then(invocation -> {
131+
// Compare the context of second request with the first context
132+
HttpClientContext context = invocation.getArgument(2);
133+
assertNotSame(context, firstContext.get());
134+
return null;
135+
});
136+
137+
// Create a mock builder and a rest client that uses the mock builder
138+
final HttpClientBuilder builderMock = mock(HttpClientBuilder.class);
139+
HttpClientRestClient restClient = new HttpClientRestClient() {
140+
@Override
141+
protected HttpClientBuilder createHttpClientBuilder() {
142+
return builderMock;
143+
}
144+
};
145+
when(builderMock.build()).thenReturn(httpClientMock);
146+
147+
// Init the rest client
148+
final Configuration configuration = new Configuration("http://localhost:" + HTTP_PORT);
149+
restClient.init(configuration);
150+
151+
restClient.submitRequest(new DummyRequest());
152+
restClient.submitRequest(new DummyRequest());
153+
154+
verify(httpClientMock, times(2))
155+
.execute(any(HttpUriRequest.class), any(ResponseHandler.class), any(HttpClientContext.class));
156+
}
157+
106158
/**
107159
* Test against Https server.
108160
*/

0 commit comments

Comments
 (0)