When a use exchange.getFormData(), the spring cloud gateway produces java.lang.IllegalStateException: Only one connection receive subscriber allowed., anyone can help me?
Follow snippet (follow a simple example of what I'm trying to):
@Component
public class SampleFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return exchange.getFormData()
.flatMap(s -> chain.filter(exchange));
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
Stacktrace:
java.lang.IllegalStateException: Only one connection receive subscriber allowed.
at reactor.ipc.netty.channel.FluxReceive.startReceiver(FluxReceive.java:276) ~[reactor-netty-0.7.8.RELEASE.jar:0.7.8.RELEASE]
at reactor.ipc.netty.channel.FluxReceive.lambda$subscribe$2(FluxReceive.java:127) ~[reactor-netty-0.7.8.RELEASE.jar:0.7.8.RELEASE]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.25.Final.jar:4.1.25.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-common-4.1.25.Final.jar:4.1.25.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:313) ~[netty-transport-native-epoll-4.1.25.Final-linux-x86_64.jar:4.1.25.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) ~[netty-common-4.1.25.Final.jar:4.1.25.Final]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
NOTES:
spring cloud version: Finchley.RELEASE
spring cloud gateway core version: 2.0.1.RELEASE
Thanks :smile:
This happens in a core test as well.
Looks like this is only in snapshots based on spring framework 5.1.x
@spencergibb Thanks to comment... I not found the point of code that have a this error... I have interesting in help to solve this 馃槵
I think my problem is in my test, since I can send form data thru to httpbin.org without it failing.
Indeed, I do call exchange.getFormData() in my test similar to what you do in the filter.
form data is the body, so I suspect there will be similar problems to reading a normal body in a filter, multiple subscribers being one of them.
@spencergibb when you say "normal body" is a GET request? because when a use getQueryParams works normal...
get requests don't have a body, but a post that isn't form urlencoded may have a body.
@spencergibb Understood... but I tested send in form urlencoded and a "form normal" and same error :/
non-formurlencoded data wouldn't be available via getFormData(). Calling that method will cause the error regardless.
Hi @spencergibb , I writed a example in my GitHub ... to try let more evident the problem https://github.com/RenanPalmeira/spring-cloud-gateway-sample ... also I get this screenshot of my postman

Thanks 馃榾
I dont see this as a bug in the Gateway rather a bug in your filter. The limitation here is that the body can only be read once. Since your filter runs first and reads the body, the NettyRoutingFilter runs into this error when trying to read the body a second time to route the request. You need to do some additional work in your filter to make sure the NettyRoutingFilter can successfully read the body to route the request. See the ModifyRequestBodyFilter for an example.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
@ryanjbaxter Got it! But I did not find the ModifyRequestBodyFilter, can you help to found it ? 馃槃
@ryanjbaxter Thanks, but i continue get error "Only one connection receive subscriber allowed." even following your example ... :( a question, why this happens just in the form-data while get the query params works?
Thanks :D
@ryanjbaxter Is not my problem similar to this issue? 馃槃 https://github.com/spring-cloud/spring-cloud-gateway/issues/541
I dont think so, can you update your sample?
@ryanjbaxter I tried follow this lines to solve my problem https://github.com/spring-cloud/spring-cloud-gateway/blob/master/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyRequestBodyGatewayFilterFactory.java#L59 but even writing ServerRequest serverRequest = new DefaultServerRequest(exchange); serverRequest.formData(); the error continue "Only one connection receive subscriber allowed."
Thanks 馃槃
can you update your sample?
You are not doing what ModifyRequestBodyGatewayFilterFactory. The body needs to be read and a new request needs to be created and put in the exchange.
Hey @ryanjbaxter , i tried use ModifyRequestBodyGatewayFilterFactory https://github.com/RenanPalmeira/spring-cloud-gateway-sample/commit/37433fc5583e7d5599a62a573c624f5c80a50e1f and same error
And also tried copy some code of ModifyRequestBodyGatewayFilterFactory https://github.com/RenanPalmeira/spring-cloud-gateway-sample/commit/c6d21cc4873b33e33ccbf39febb4d65fef1298e4
You are not doing what I am suggesting. Your filter needs to do something similar to what ModifyRequestBodyGatewayFilterFactory does except with getFormData instead of bodyToMono.
Hey @ryanjbaxter , I copied some parts of ModifyRequestBodyGatewayFilterFactory and solved my question... but just get the data of post... how change the response with checking form data, for example:
if (key in data of post) {
// continue chain
return chain.filter(exchange);
}
else {
return "mutate request with forbidden text"
}
I updated my github https://github.com/RenanPalmeira/spring-cloud-gateway-sample/blob/8471ea19de8703675c5b4a26856c5acbf53656e1/src/main/java/com/spring/gateway/GatewayApplication.java#L59
Thanks
I dont understand, if you want to modify the body that is exactly what the filter already does, just follow the code.
I want change response like the ModifyResponseBodyGatewayFilterFactory but checking if exist a field in form-data... i tried change response here but in this place i can just change form-data https://github.com/RenanPalmeira/spring-cloud-gateway-sample/blob/8471ea19de8703675c5b4a26856c5acbf53656e1/src/main/java/com/spring/gateway/GatewayApplication.java#L58-L61 ... i tried merge some code of ModifyRequestBodyGatewayFilterFactory and ModifyResponseBodyGatewayFilterFactory... but same error
I am not sure what else I can do, I have given you pointers for how to make this work, you are just looking at formdata instead of the body/
@ryanjbaxter Hey I got obtain form-data and make a if to return a page forbidden or continue chain... i don't know is the best way... to reference i used https://github.com/spring-cloud/spring-cloud-gateway/blob/master/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/ReadBodyPredicateFactory.java#L88
My solution:
Thanks for everthing