Fix custom config with older HttpClient
Since HttpClient 4.3, custom configuration such as the connection timeout and the socket timeout are set in a RequestConfig object stored in the HttpContext. Unfortunately, older HttpClients are not supporting this infrastructure and new clients throw an exception when the deprecated API is used. This commit detects if the client is an "old" implementation and set the configuration through the deprecated means to restore full backward compatibility with these features. Issue: SPR-11442
This commit is contained in:
parent
bea94d5302
commit
7a6ec69523
|
@ -70,6 +70,9 @@ final class HttpComponentsClientHttpRequest extends AbstractBufferingClientHttpR
|
|||
return this.httpRequest.getURI();
|
||||
}
|
||||
|
||||
HttpContext getHttpContext() {
|
||||
return httpContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
|
||||
|
|
|
@ -113,6 +113,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest
|
|||
public void setConnectTimeout(int timeout) {
|
||||
Assert.isTrue(timeout >= 0, "Timeout must be a non-negative value");
|
||||
this.connectTimeout = timeout;
|
||||
setLegacyConnectionTimeout(getHttpClient(), connectTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,6 +124,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest
|
|||
public void setReadTimeout(int timeout) {
|
||||
Assert.isTrue(timeout >= 0, "Timeout must be a non-negative value");
|
||||
this.socketTimeout= timeout;
|
||||
setLegacyReadTimeout(getHttpClient(), socketTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,6 +224,44 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the specified custom connection timeout for deprecated {@link HttpClient}
|
||||
* instances.
|
||||
* <p>As from HttpClient 4.3, default parameters have to be set in a
|
||||
* {@link RequestConfig} instance instead of setting the parameters
|
||||
* on the client.
|
||||
* <p>Unfortunately, this behaviour is not backward compatible and older
|
||||
* {@link HttpClient} implementations will ignore the {@link RequestConfig}
|
||||
* object set in the context.
|
||||
* <p>If the specified client is an older implementation, we set the
|
||||
* custom connection timeout through the deprecated API. Otherwise, we just
|
||||
* return as it is set per request with newer clients
|
||||
* @param client the client to handle
|
||||
* @param connectionTimeout the custom connection timeout
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setLegacyConnectionTimeout(HttpClient client, int connectionTimeout) {
|
||||
if (org.apache.http.impl.client.AbstractHttpClient.class.isInstance(client)) {
|
||||
client.getParams().setIntParameter(
|
||||
org.apache.http.params.CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the specified read timeout for deprecated {@link HttpClient}
|
||||
* instances.
|
||||
* @param client the client to handle
|
||||
* @param readTimeout the custom read timeout
|
||||
* @see #setLegacyConnectionTimeout(org.apache.http.client.HttpClient, int)
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setLegacyReadTimeout(HttpClient client, int readTimeout) {
|
||||
if (org.apache.http.impl.client.AbstractHttpClient.class.isInstance(client)) {
|
||||
client.getParams().setIntParameter(
|
||||
org.apache.http.params.CoreConnectionPNames.SO_TIMEOUT, readTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown hook that closes the underlying
|
||||
* {@link org.apache.http.conn.HttpClientConnectionManager ClientConnectionManager}'s
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,6 +16,16 @@
|
|||
|
||||
package org.springframework.http.client;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.params.CoreConnectionPNames;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
|
@ -32,4 +42,36 @@ public class HttpComponentsClientHttpRequestFactoryTests extends AbstractHttpReq
|
|||
assertHttpMethod("patch", HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void assertLegacyCustomConfig() {
|
||||
HttpClient httpClient = new DefaultHttpClient(); // Does not support RequestConfig
|
||||
HttpComponentsClientHttpRequestFactory hrf = new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||
hrf.setConnectTimeout(1234);
|
||||
assertEquals(1234, httpClient.getParams().getIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 0));
|
||||
|
||||
hrf.setReadTimeout(4567);
|
||||
assertEquals(4567, httpClient.getParams().getIntParameter(CoreConnectionPNames.SO_TIMEOUT, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertCustomConfig() throws Exception {
|
||||
HttpClient httpClient = HttpClientBuilder.create().build();
|
||||
HttpComponentsClientHttpRequestFactory hrf = new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||
hrf.setConnectTimeout(1234);
|
||||
hrf.setReadTimeout(4567);
|
||||
|
||||
URI uri = new URI(baseUrl + "/status/ok");
|
||||
HttpComponentsClientHttpRequest request = (HttpComponentsClientHttpRequest)
|
||||
hrf.createRequest(uri, HttpMethod.GET);
|
||||
|
||||
Object config = request.getHttpContext().getAttribute(HttpClientContext.REQUEST_CONFIG);
|
||||
assertNotNull("Request config should be set", config);
|
||||
assertTrue("Wrong request config type" + config.getClass().getName(),
|
||||
RequestConfig.class.isInstance(config));
|
||||
RequestConfig requestConfig = (RequestConfig) config;
|
||||
assertEquals("Wrong custom connection timeout", 1234, requestConfig.getConnectTimeout());
|
||||
assertEquals("Wrong custom socket timeout", 4567, requestConfig.getSocketTimeout());
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue