Configure Spring-WebClient for test environments
Spring has been providing a reactive web client for some time. Although this client provides many settings, not everything is so obvious and simple. For example, during development I often want to see exactly how the server is responding or ignore certain errors. For this I would like to configure the client in such a way that I can notice such errors and react accordingly.
Disable TLS/SSL verification
Especially in test environments, I keep encountering very questionable TLS constructions. In the best case, self-signed certificates are still used, which you only have to trust in the specific case. In the worst case, however, incorrect or invalid certificates are sometimes used here. In large companies in particular, you often have to trust a central CA and make it known everywhere.
Of course, these problems should be addressed immediately by letting people know about their mistakes.
While the bugs are fixed, we can still try our code with the right configuration. To do this, we need to disable TLS checking from the web client as follows:
SslContext sslContext =
SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build(); (1)
HttpClient httpClient = HttpClient.create()
.secure(t -> t.sslContext(sslContext)); (2)
WebClient webClient =
WebClient.builder()
.clientConnector(
new ReactorClientHttpConnector(httpClient)) (3)
.build();
1 | We need a {ssl-context-url}[SslContext], which trusts all certificates through the {ssl-insecure-trust-manager-url}[InsecureTrustManagerFactory]. |
2 | We can then create an {http-client-url}[HttpClient] that uses the insecure SSL context |
3 | Finally, we need to configure the WebClient to use the new HttpClient |
The web client created in this way ignores most TLS errors and allows us to continue to connect the API. In cases where this adjustment is not sufficient to create an interim solution, alarm bells should be ringing one way or another. Say then probably much more is broken than just a certificate.
This setting should never be adopted in production code as it makes TLS completely absurd. |
Log requests and responses
A completely different problem often only becomes apparent during the actual development work. Namely that the API doesn’t seem to be doing what we expect. There comes JSON, sometimes XML, sometimes a CSV, then suddenly a completely unknown structure is returned. These problems are annoying, but many providers manage to make the documentation say something different than the API does.
In order not to be completely left out in the rain and to be completely dependent on the support, I always like to see the transmitted data here. Luckily, you can setup the WebClient to log all of the request and response. Unfortunately, this setting is again not so obvious:
HttpClient httpClient = HttpClient.create()
.wiretap(
this.getClass().getSimpleName(),
LogLevel.INFO,
AdvancedByteBufFormat.TEXTUAL); (1)
WebClient webClient =
WebClient.builder()
.clientConnector(
new ReactorClientHttpConnector(httpClient)) (2)
.build();
1 | We initialize a {http-client-url}[HttpClient] again, which is instructed to log all traffic in text form |
2 | Then all we have to do is configure the WebClient to use the new HttpClient |
The web client created in this way always logs out all request and response information.
This setting should not be adopted in productive code, as sensitive data such as access information is also logged. |
Closing words
As you can see, the WebClient can be configured extensively and very flexibly. Unfortunately, however, part of the configuration does not take place in the WebClient Builder itself. Instead, we need to customize the underlying Http client.
Happy debugging.