Skip navigation and jump to content

Felix Nehrke

I write about software development and software architecture.

deutsch

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();
1We need a {ssl-context-url}[SslContext], which trusts all certificates through the {ssl-insecure-trust-manager-url}[InsecureTrustManagerFactory].
2We can then create an {http-client-url}[HttpClient] that uses the insecure SSL context
3Finally, 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();
1We initialize a {http-client-url}[HttpClient] again, which is instructed to log all traffic in text form
2Then 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.