I have a filter created where I access the body of the payload and do some logic on it (for now let's say I log the body). In the last step, I return Mono but when the request proceeds through the controller to services it throws a bad request error that the body is missing.
Code for the filter:
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
HttpHeaders headers = serverWebExchange.getRequest().getHeaders();
String domain = headers.getFirst("domain");
return serverWebExchange.getRequest().getBody()
.single()
.flatMap(body -> Mono.just(parseBody(body)))
.flatMap(s -> webFilterChain.filter(serverWebExchange));
}
private String parseBody(DataBuffer fbody) {
System.out.println("parsing body");
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
Channels.newChannel(baos).write(fbody.asByteBuffer().asReadOnlyBuffer());
} catch (IOException e) {
e.printStackTrace();
}
return baos.toString(StandardCharsets.UTF_8);
}
The error: org.springframework.web.server.ServerWebInputException: 400 BAD_REQUEST "Request body is missing"
What can cause this behavior?
The reason is that you can only read the body once (https://github.com/spring-cloud/spring-cloud-gateway/issues/1587)
You are reading it here: serverWebExchange.getRequest().getBody() and therefore it is omitted in the request.
A solution is to cache the body, you can use for instance the ReadBodyRoutePredicateFactory (https://github.com/spring-cloud/spring-cloud-gateway/issues/1307).
Make sure the RemoveCachedBodyFilter is enabled so the body is released so you do not have memory leaks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With