Error when using ModifyRequestBody and Retry filters
Describe the bug
Using the ModifyRequestBody and Retry filters causes an IllegalReferenceCountException on technical error of the target (e.g. premature closed error):
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
I witnessed this on 2.7 & 3.4 versions.
Sample
Using this code, creating a route that uses the ModifyRequestBody and Retry filters, it will trigger the exception:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public RouteLocator rewrittenAndRetriedRoute(RouteLocatorBuilder builder) {
return builder.routes()
.route(p -> p
.path("/route/*")
.filters(f -> f
.modifyRequestBody(config -> {
config.setInClass(String.class);
config.setOutClass(String.class);
config.setRewriteFunction((exchange, body) -> Mono.just("{}"));
})
.retry(config -> {
config.setRetries(5);
config.setSeries();
config.setStatuses(HttpStatus.BAD_GATEWAY, HttpStatus.GATEWAY_TIMEOUT);
config.setExceptions(IOException.class);
config.setMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.PATCH);
config.setBackoff(new RetryGatewayFilterFactory.BackoffConfig(Duration.ofMillis(5), Duration.ofMillis(10), 2, false));
})
)
.uri("http://localhost:9880/"))
.build();
}
}
I am using this simple NodeJS server to reproduce a technical error:
const net = require("net");
const server = net.createServer(function(socket) {
console.log('opening connection');
setTimeout(function() { socket.destroy(); }, 20);
});
server.listen(9880);
And curl:
$ curl localhost:8080/route/fail -XPOST -H 'Content-Type: application/json' -d '{"Hello": "World"}'
2.7 and 3.4 must be versions of spring boot. What versions of gateway?
I used the Spring Boot initializer for 3.4.4, and it seems to be using the 4.2.1 version for the gateway.
On our project, we are using 3.1.3 version of the gateway with a 2.6 Spring Boot version (I managed to reproduce the same way with 2.6, 2.7 and 3.4 though)
I also tried using something else than a String for the modified request body, using a buffer thanks to DefaultDataBufferFactory for instance, with the same error.