Spring-WebClient für Testumgebungen konfigurieren
Seit einiger Zeit schon liefert Spring einen reactiven Web-client. Dieser Client liefert zwar viele Einstellungen aber nicht alles ist so offensichtlich und einfach. Häufig möchte ich während der Entwicklung zum Beispiel genau sehen, wie der Server antwortet, oder bestimmte Fehler ignorieren. Hierzu möchte ich den Client so konfigurieren, dass ich solche Fehler mitbekommen und entsprechend reagieren kann.
TLS/SSL checks deaktivieren
Gerade bei Testumgebungen begegnen mir immer wieder sehr fragwürdige TLS-Konstruktionen. Im besten Falle werden noch selbst-signierte Zertifikate verwendet, denen man lediglich für den konkreten Fall vertrauen muss. Im schlimmsten Fall jedoch werden hier auch schonmal falsche oder ungültige Zertifikate verwendet. Insbesondere in großen Unternehmen muss man dazu oft noch einer zentralen CA vertrauen und diese überall bekannt machen.
Natürlich sollten diese Missstände sofort adressiert werden, indem wir die Leute über ihre Fehler informieren.
Während die Fehler behoben werden können wir mittels der richtigen Konfiguration trotzdem schon unseren Code ausprobieren. Dazu müssen wir die TLS-Prüfung vom Webclient wie folgt deaktivieren:
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 | Wir benötigen eine SslContext, welcher durch die InsecureTrustManagerFactory allen Zertifikaten vertraut |
2 | Anschließend können wir einen HttpClient erstellen, der den unsicheren SSL-Context verwendet |
3 | Zuletzt müssen wir noch den WebClient so konfigurieren, dass er den neue HttpClient nutzt |
Der so erstellte Webclient ignoriert die meisten TLS-Fehler und ermöglicht uns erstmal weiter die API anzubinden. In den Fällen in denen diese Anpassung nicht ausreicht, um eine Übergangslösung zu schaffen, sollten so oder so alle Alarmglocken schrillen. Sprich dann ist wahrscheinlich viel mehr kaputt, als nur ein Zertifikat.
Diese Einstellung sollte niemals in produktiven Code übernommen werden, da sie TLS komplett ad absurdum führt. |
Requests und Responses loggen
Ein ganz anderes Problem zeigt sich häufig erst während der konkreten Entwicklungsarbeit. Nämlich, dass die API scheinbar nicht das tut, was wir erwarten. Da kommt mal JSON, mal XML mal eine CSV, dann wird auf einmal eine ganz andere Struktur zurück gegeben, als wie dachten. Diese Problem sind nervig aber viele Anbieter schaffen es immer wieder, dass die Doku etwas anderes sagt als die API tut.
Um hier nicht komplett im Regen zu stehen und voll und ganz abhängig vom Support zu sein, sehe ich hier immer gerne die übertragenen Daten. Zum Glück kann man dem WebClient beibringen, den gesamten Request und die Response zu loggen. Leider ist diese Einstellung aber wieder nicht so offensichtlich:
HttpClient httpClient = HttpClient.create()
.wiretap(
this.getClass().getSimpleName(),
LogLevel.INFO,
AdvancedByteBufFormat.TEXTUAL); (1)
WebClient webClient =
WebClient.builder()
.clientConnector(
new ReactorClientHttpConnector(httpClient)) (2)
.build();
1 | Wir initialisieren wieder einen HttpClient, welcher angewiesen wird den gesamten Datenverkehr in Text-form zu loggen |
2 | Anschließend müssen wir nur noch den WebClient so konfigurieren, dass er den neue HttpClient nutzt |
Der so erstellte Webclient loggt stets alle Request- und Response-Informationen aus.
Diese Einstellung sollte nicht in produktiven Code übernommen werden, da auch sensible Daten, wie Zugangsinformation, geloggt werden. |
Abschluss
Wie man sieht kann der WebClient recht umfangreich und sehr flexibel konfiguriert werden. Leider findet ein Teil der Konfiguration jedoch nicht im WebClient-Builder selbst statt. Stattdessen müssen wir den zugrunde liegenden Http-Client anpassen.
Happy debugging.