Get the configuration of Apache's HttpClient - java

Once I've created an Apache HttpClient, how do I get the configuration values from it (what used to be HttpParams)?
For example, if I do something like this to create a client:
RequestConfig requestConfig = RequestConfig.custom()
.setCircularRedirectsAllowed(true)
.setAuthenticationEnabled(true)
.setExpectContinueEnabled(true)
.setConnectionRequestTimeout(10000);
.build();
HttpClient client = HttpClientBuilder
.create()
.setConnectionManager(new PoolingHttpClientConnectionManager(createSchemeRegistry()))
.setDefaultRequestConfig(requestConfig)
.build();
How would I get the value of the connection request timeout from the org.apache.http.client.HttpClient instance? other configuration items?
For AbstractHttpClient there was a method getParams (or similar) but that's all gone away in favour of the HttpClient interface. There's an InternalHttpClient instance that's generated along the way but I think that's not exposed.
The reason I'm interested in this is firstly for testing - I want to verify a HTTP Client was configured correctly, the other case is to present that information in a UI when debugging HTTP traffic - think of something like Charles proxy.

Related

Override restTemplate timeout settings for certain URLs

In my spring-boot (2.4.0) app I have set up a connection pool and the timeout for outgoing HTTP requests (30 seconds):
#Bean
public RequestConfig requestConfig() {
return RequestConfig.custom()
.setConnectionRequestTimeout(30000)
.setConnectTimeout(30000)
.setSocketTimeout(30000)
.build();
}
#Bean
public CloseableHttpClient httpClient(PoolingHttpClientConnectionManager poolingHttpClientConnectionManager,
RequestConfig requestConfig) {
return HttpClientBuilder
.create()
.setConnectionManager(poolingHttpClientConnectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
}
#Bean
public RestTemplate restTemplate(HttpClient httpClient) {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
return new RestTemplate(requestFactory);
}
I autowire restTemplate bean in my Gateway classes and use this restTemplate.exchange(...) to perform HTTP requests. The timeout itself works fine and is applied to all outgoing requests.
But for certain URLs I need to set the timeout to 5 seconds.
Is there a way to override generic timeout settings for certain URLs?
I had this very this problem recently and had two versions of RestTemplate, one for "short timeout" and one for "long timeout". See here.
RestTemplate was really designed to be built with pre-configured timeouts and for those timeouts to stay untouched after initialization. If you use Apache HttpClient then yes you can set a RequestConfig per request and that is the proper design in my opinion.

WebClient logging without deprecated method tcpClient.bootstrap()

I'm trying do some logging in my middleware application, where I want to log request and response of backend system. I would like to use Netty (because we have implemented difficult SslContext).
I'm trying to learn it by this tutorial: https://www.baeldung.com/spring-log-webclient-calls (chapter 4.2. Logging with Netty HttpClient).
For better looking logs, there is part of code:
HttpClient httpClient = HttpClient
.create()
.tcpConfiguration(
tc -> tc.bootstrap(
b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class))))
.build()
but bootstrap(...) method is deprecated. What can I use instead?
If you need CustomLogger for request/response (as per comment above) then you can do the following:
CustomLogger customLogger = new CustomLogger(HttpClient.class);
HttpClient httpClient = HttpClient
.create()
.doOnRequest((request, connection) -> {
connection.addHandlerFirst(customLogger);
});

How to disable cookies with Spring WebClient

Does anyone know if there's a way to disable cookie management in Spring WebClient using Reactor Netty HttpClient?
I noticed both WebClient.Builder and HttpClient APIs provide a means to add cookies to an outbound request but I am looking for a way to inhibit them altogether if such exists. That is akin to disableCookieManagement on Apache's HttpComponentClientBuilder.
It looks like there's no way to disable the cookie handling per se but this seems to work: Create your own HttpClient, then use HttpClient.doOnRequest to register a callback to be called before sending the request. In the callback, call HttpClientRequest.requestHeaders() to retrieve the request headers, then delete the Cookie header.
Sample code that removes User-Agent header before sending the request.
public class Main {
public static void main(String[] args) {
HttpClient httpClient = HttpClient.create().doOnRequest((request, connection) -> {
request.requestHeaders().remove("User-Agent");
});
WebClient client = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
Mono<String> r = client.get().uri("https://www.google.com").retrieve()
.bodyToMono(String.class);
System.out.println(r.block());
}
}
In my testing, I'm not seeing that Reactor Netty HttpClient is doing anything at all with the cookies that come back in the response. I was actually looking to enable a cookie store like the Apache HttpClient supports, but to all indications the Netty HttpClient has no such feature.
In the entire codebase of Reactor Netty, there is no usage of the "set-cookie" header except in one of their unit tests. This tells me cookies are ignored by default unless the client code chooses to look for them.

Okhttp 3.x dynamically add/remove authenticator / interceptor

Is it possible to add/remove Authenticators and/or Interceptors to an existing Okhttp instance? If yes, how?
No, it is not possible.
However, you can create a builder from an existing client, and make changes to that. This will share the dispatcher, connectionPool etc.
OkHttpClient.Builder clientBuilder = client1.newBuilder();
clientBuilder.networkInterceptors().add(0, serviceInterceptor);
OkHttpClient client2 = clientBuilder.build();
There is an example for adjusting the timeout of a client in the javadoc https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html

Setting timeouts in Spring Rest Template

Application is using Spring rest template to call a webservice and i am using
restTemplate.exchage(url) to call the webservice.
Currently we are not passing any timeout value for this webservice call, How can i set a timeout value for Spring Rest template.
You can use code similar to following for setting connection timeout:
RestTemplate restTemplate = new RestTemplate();
((SimpleClientHttpRequestFactory)restTemplate.getRequestFactory()).setConnectTimeout(2000);
If your wish to set read timeout, you can have code similar to following:
((SimpleClientHttpRequestFactory)restTemplate.getRequestFactory()).setReadTimeout(2000);
The time is given in milliseconds here. For more info, you can visit the documentation page.
RestTemplateBuilder introduced since Spring 1.4 could be used to set read and connect timeout settings for RestTemplate object. Here is sample code -
final RestTemplate restTemplate =
new RestTemplateBuilder()
.setConnectTimeout(Duration.ofMillis(connectTimeoutMillis))
.setReadTimeout(Duration.ofMillis(readTimeoutMillis))
.build();
I use this approach based on these threads
int DEFAULT_TIMEOUT = 5000;
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(DEFAULT_TIMEOUT)
.setConnectionRequestTimeout(DEFAULT_TIMEOUT)
.setSocketTimeout(DEFAULT_TIMEOUT)
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.build();
Spring RestTemplate Connection Timeout is not working
Java : HttpClient 4.1.2 : ConnectionTimeout, SocketTimeout values set are not effective

Categories