'How to extract response header & status code from Spring 5 WebClient ClientResponse
I am new to Spring Reactive framework & trying to convert Springboot 1.5.x code into Springboot 2.0. I need to return response header after some filtering, body & status code from Spring 5 WebClient ClientResponse. I do not want to use block() method as it will convert it into sync call. I am able to get responsebody pretty easily using bodyToMono. Also, I am getting status code, headers & body if I am just returning ClientResponse but I need to process response based on statusCode & header parameters. I tried subscribe, flatMap etc. but nothing works.
E.g. - Below code will return response Body
Mono<String> responseBody = response.flatMap(resp -> resp.bodyToMono(String.class));
But similar paradigm is not working to get statusCode & Response headers. Can someone help me in extracting statusCode & header parameters using Spring 5 reactive framework.
Solution 1:[1]
You can use the exchange function of webclient e.g.
Mono<String> reponse = webclient.get()
.uri("https://stackoverflow.com")
.exchange()
.doOnSuccess(clientResponse -> System.out.println("clientResponse.headers() = " + clientResponse.headers()))
.doOnSuccess(clientResponse -> System.out.println("clientResponse.statusCode() = " + clientResponse.statusCode()))
.flatMap(clientResponse -> clientResponse.bodyToMono(String.class));
then you can convert bodyToMono etc
Solution 2:[2]
I needed to check the response details(headers, status, etc) and body as well.
The only way I was able to do it was by using .exchange()
with two subscribe()
as the following example:
Mono<ClientResponse> clientResponse = WebClient.builder().build()
.get().uri("https://stackoverflow.com")
.exchange();
clientResponse.subscribe((response) -> {
// here you can access headers and status code
Headers headers = response.headers();
HttpStatus stausCode = response.statusCode();
Mono<String> bodyToMono = response.bodyToMono(String.class);
// the second subscribe to access the body
bodyToMono.subscribe((body) -> {
// here you can access the body
System.out.println("body:" + body);
// and you can also access headers and status code if you need
System.out.println("headers:" + headers.asHttpHeaders());
System.out.println("stausCode:" + stausCode);
}, (ex) -> {
// handle error
});
}, (ex) -> {
// handle network error
});
I hope it helps. If someone knows a better way to do it, please let us know.
Solution 3:[3]
After Spring Boot 2.4.x / Spring 5.3, WebClient exchange
method is deprecated in favor of retrieve
, so you have to get the headers and response status using ResponseEntity like the following example:
webClient
.method(HttpMethod.POST)
.uri(uriBuilder -> uriBuilder.path(loginUrl).build())
.bodyValue(new LoginBO(user, passwd))
.retrieve()
.toEntity(LoginResponse.class)
.filter(
entity ->
entity.getStatusCode().is2xxSuccessful()
&& entity.getBody() != null
&& entity.getBody().isLogin())
.flatMap(entity -> Mono.justOrEmpty(entity.getHeaders().getFirst(tokenHeader)));
Solution 4:[4]
As discussed above, the exchange has been deprecated so we are using retrieve(). This is how I'm returning the code after making a request.
public HttpStatus getResult() {
WebClient.ResponseSpec response = client
.get()
.uri("/hello")
.accept(MediaType.APPLICATION_JSON)
.retrieve();
return Optional.of(response.toBodilessEntity().block().getStatusCode()).get();
}
Another option as per the comment, I've tried recently. This is usually recommended for Async calls but we can use it for both.
MyClass responseMono = this.webClient
.get()
.uri("myapipath"}")
.retrieve()
.bodyToMono(MyClass.class)
.block();
return responseMono;
Solution 5:[5]
For status code you can try this:
Mono<HttpStatus> status = webClient.get()
.uri("/example")
.exchange()
.map(response -> response.statusCode());
For headers:
Mono<HttpHeaders> result = webClient.get()
.uri("/example")
.exchange()
.map(response -> response.headers().asHttpHeaders());
Solution 6:[6]
You can configure spring boot >= 2.1.0 to log request and response if you are using the WebClient
:
spring.http.log-request-details: true
logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions: TRACE
As desribed in the sprint boot docs, if you want headers to be logged, too, you have to add
Consumer<ClientCodecConfigurer> consumer = configurer ->
configurer.defaultCodecs().enableLoggingRequestDetails(true);
WebClient webClient = WebClient.builder()
.exchangeStrategies(ExchangeStrategies.builder().codecs(consumer).build())
.build();
But be aware that this can log sensitve information.
Solution 7:[7]
httpClient
.get()
.uri(url)
.retrieve()
.toBodilessEntity()
.map(reponse -> Tuple2(reponse.statusCode, reponse.headers))
Solution 8:[8]
You can use flatMap
to extract the object from Mono
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | dazito |
Solution 2 | Rafael Amaral |
Solution 3 | jkamcc |
Solution 4 | |
Solution 5 | |
Solution 6 | Tobske |
Solution 7 | Juan Rada |
Solution 8 | Trippletech Magabe |