I am instantiating an Apache HTTP Components HttpClient using the following code:
CloseableHttpClient httpClient = HttpClients.custom()
.setProxy(new HttpHost(proxyServerAddress, proxyServerPort))
.disableConnectionState()
.disableCookieManagement()
.build();
But I would like to set the proxy only if an property (e.g. useProxy) is set to true. I can use an if-then-else pair of blocks based on the property value, but I was wondering if there is a better way to achieve this? My goal is to externalize the control of whether or not to use a proxy, using a configuration file property or via JAVA_OPTS.
How about:
HttpClientBuilder builder = HttpClients.custom()
.disableConnectionState()
.disableCookieManagement();
if( useProxy )
builder = builder.setProxy(new HttpHost(proxyServerAddress, proxyServerPort));
CloseableHttpClient httpClient = builder.build();
Related
I use a httpClient of apache in java to call REST APIs which is configured as below in a static block of class, what I want is to change the connection timeout per request. is it possible? how?
static {
PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager();
pool.setMaxTotal(ChatSettings.HTTP_CLIENT_THREAD_POOL_SIZE);
httpClient = HttpClients
.custom()
.setConnectionManager(pool)
.setDefaultRequestConfig(
RequestConfig
.custom()
.setConnectTimeout(DEFAULT_HTTP_TIMEOUT)
.setSocketTimeout(DEFAULT_HTTP_TIMEOUT)
.build()
)
.build();
}
One thing you can implement for sure is to follow this example: https://github.com/apache/httpcomponents-client/blob/5.1.x/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientAbortMethod.java
It demonstrates how a client can fire a request, but eventually change it's mind and tell the server it no longer wants to receive the response.
Combine this with a 'watchdog' thread that fires after some time/when the time runs out.
I know that a read and a connection timeouts can be configured in reactor-netty HttpClient, like:
public WebClient xsdWebClient() {
HttpClient httpClient = createHttpClient(config.getConnectionTimeout(), config.getReadTimeout());
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient.followRedirect(true)))
.baseUrl(config.getHost())
.build();
}
private static HttpClient createHttpClient(int connectionTimeout, int readTimeout) {
return HttpClient.create()
.option(
ChannelOption.CONNECT_TIMEOUT_MILLIS,
(int) TimeUnit.SECONDS.toMillis(connectionTimeout))
.doOnConnected(c -> c.addHandlerLast(new ReadTimeoutHandler(readTimeout)));
}
But what are the default read and connection timeouts for reactor-netty HttpClient?
I would recommend you to use the response timeout configuration provided by Reactor Netty instead of ReadTimeoutHandler. You can configure the response timeout either globally on HttpClient level for all requests or per request.
The default values for various timeouts provided by Reactor Netty you can find in the reference documentation.
Referring to answer given by one of the devs of reactor-netty, the read default time is 10 seconds.
Today I was trying to configure the HttpComponentsMessageSender which uses Apache's org.apache.httpcomponents.httpclient library. Before I used the standard Java classes (I think java.net.HttpUrlMessageSender or something along those lines).
My HTTP methods need to authenticate using NTLM and the software is running under Linux so I cannot use the default Windows mechanism to do authentication, but instead I must configure authentication inside the Java application.
Originally I was just using a custom implementation of java.net.Authenticator which I used to set the username and password
for the NTLM access. But when I switched to HttpComponentsMessageSender this approach did not work anymore. When I tried to setup a custom HttpClient configuration with the HttpComponentsMessageSender I ran into various issues which I thought I would document here.
I am going to post my own answer but if anyone has a better solution, please feel free to add your solution.
I solved this adding a custom build HttpClient object which I built with the HttpClientBuilder. However adding this caused the following exception to appear:
org.apache.http.ProtocolException: Content-Length header already present
The solution which I found in this answer was to add a HttpRequestInterceptor.
Using the setConnectionTimeout on the HttpComponentsMessageSender did not work anymore with my custom HttpClient object. Instead I had to inject a RequestConfig object into the HttpClientBuilder.
The NTCredentials object required the domain name as a parameters. Earlier when I was using the Authenticator interface from java.net it was enough to just supply the username and password.
This is the code I am using currently:
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender ();
AuthScope authscope;
NTCredentials credentials;
CredentialsProvider credentialsProvider;
Registry<AuthSchemeProvider> registry;
RequestConfig requestConfig;
authscope = new AuthScope (HOST_IP, HOST_PORT);
credentials = new NTCredentials ("user", "pass", null, "domain");
credentialsProvider = new BasicCredentialsProvider ();
credentialsProvider.setCredentials (authscope, credentials);
registry = RegistryBuilder.<AuthSchemeProvider>create ()
.register(AuthSchemes.NTLM, new NTLMSchemeFactory ())
.build ();
HttpRequestInterceptor interceptor
= (request, context) -> request.removeHeaders(HTTP.CONTENT_LEN);
requestConfig = RequestConfig.custom ()
.setConnectTimeout (3000)
.build ();
HttpClient httpClient
= HttpClientBuilder.create ()
.setDefaultRequestConfig (requestConfig)
.setDefaultAuthSchemeRegistry (registry)
.setDefaultCredentialsProvider (credentialsProvider)
.addInterceptorFirst (interceptor)
.build ();
messageSender.setHttpClient (httpClient);
I have a problem I can't seem to grasp.
My relevant code is
final Builder requestConfigBuilder = RequestConfig.custom();
...
final HttpClientBuilder clientBuilder = HttpClientBuilder.create();
clientBuilder.setDefaultCookieStore();
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
...
If I use this client I get from my builder, I can see all cookies being sent in my request as I would expect.
However, adding a cookie spec, like this:
final Builder requestConfigBuilder = RequestConfig.custom();
...
requestConfigBuilder.setCookieSpec(CookieSpecs.DEFAULT); //this causes problems
final HttpClientBuilder clientBuilder = HttpClientBuilder.create();
clientBuilder.setDefaultCookieStore(someCookieStoreVariable);
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
...
I see no cookies being sent in my request. The result is the same no matter which spec I choose from CookieSpecs.
Am I misunderstanding or misusing this, why doesn't this work? Is there some problem with me setting another cookiestore? I do need it for future references so it has to stay.
Check whether cookie domain and path are set properly.
I'm using Apache Httpclient for Ajax-calls on a website. In some cases requests to external webservice fail, often with:
I/O exception (java.net.ConnectException) caught when processing request: Connection timed out: connect.
In that case, more often than not, I want to skip retrying the request (something that Httpclient seems to do automatically) .
However, I can't find any method, param, etc. to skip retrying.
anyone?
Thanks Geert-Jan
From httpclient 4.3 use HttpClientBuilder
HttpClientBuilder.create().disableAutomaticRetries().build();
client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
That would do it.
OK. There is issue in the Documentation. Also there has been change in API and methods.
So if you want to use DefaultHttpRequestRetryHandler , here are the ways to do that,
DefaultHttpClient httpClient = new DefaultHttpClient();
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(0, false);
httpClient.setHttpRequestRetryHandler(retryHandler);
or
HttpClient httpClient = new DefaultHttpClient();
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(0, false);
((AbstractHttpClient)httpClient).setHttpRequestRetryHandler(retryHandler);
In first one, we use concrete DefaultHttpClient (which is a subclass of AbstractHttpClient and so has the setHttpRequestRetryHandler() method.)
In second one, we are programming to the HttpClient interface (which sadly doesn't expose that method, and this is weird !! ehh), so we have to do that nasty cast.
There's a description in the HttpClient tutorial.
client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
See the tutorial for more information, for instance this may be harmful if the request has side effects (i.e. is not idempotent).
The cast to AbstractHttpClient is not necessary. Another way is to use a strategy with AutoRetryHttpClient with DefaultServiceUnavailableRetryStrategy set to 0 for retry parameter. A better way would be to extend the AbstractHttpClient or implement HttpClient to expose the desired method.