Currently developing with Spring Boot 2.0.4 a WebFilter that logs HTTP request and response informations (URL, response status code, duration, etc) in a Spring WebFlux application.
Works fine except that exchange.getResponse().getStatusCode() remains null.
Tried two different impls of filter(ServerWebExchange exchange, WebFilterChain chain), first one:
return chain.filter(exchange).doAfterTerminate(
() -> System.out.println("Status=" + exchange.getResponse().getStatusCode()));
Second one:
Mono<Void> filtered = chain.filter(exchange);
exchange.getResponse().beforeCommit(() -> {
System.out.println("Status=" + exchange.getResponse().getStatusCode());
return Mono.empty();
});
return filtered;
Also tried various orders on the filter: none, @Order(100000), @Order(-100000).
Status code remains null.
What is the proper implementation?
Update 1
Wrote a minimalistic working example based on KevH solution, see https://github.com/fbeaufume/webflux-filter-sample but it's not working yet, the status is still null. The MWE exposes two REST endpoints: /hello and /pause/1000 (a 1 sec pause).
Note that when called the pause endpoint logs:
11:06:20.644 INFO 9536 --- [ctor-http-nio-2] com.adeliosys.sample.LogFilter : Request [/pause/1000] started, traceId [bb3fe67d-170b-4070-837d-816fe1420a1f]
11:06:20.673 INFO 9536 --- [ctor-http-nio-2] com.adeliosys.sample.HelloController : Pausing for 1000 msec
11:06:21.683 INFO 9536 --- [ parallel-2] com.adeliosys.sample.LogFilter : Request [/pause/1000] completed, statusCode [null], time [1039], traceId [bb3fe67d-170b-4070-837d-816fe1420a1f]
11:06:21.684 INFO 9536 --- [ parallel-2] com.adeliosys.sample.HelloController : Paused for 1000 msec
I'm surprised that the second message of the filter is displayed before the second message of the endpoint.
Update 2
It seems that the filter implementation using doAfterTerminate (or similar methods) was correct, but this correctly retrieves the HTTP response status only with REST controller methods that use a ResponseEntity in the return type.
Not supported (i.e. status is null): void, Mono<Void>, String, Mono<String>, MyBean, Mono<MyBean>, etc.
Supported (i.e. status is 200): ReponseEntity<Void>, Mono<ResponseEntity<Void>>, ReponseEntity<String>, Mono<ResponseEntity<String>>, ReponseEntity<MyBean>, Mono<ResponseEntity<MyBean>>, etc.
Bug?
Spring Boot 2.0.5 has the same behavior.
Update 3
Opened an issue on the subject, see https://jira.spring.io/browse/SPR-17368