spring-cloud-gateway
spring-cloud-gateway copied to clipboard
In spring cloud gateway mvc, an exception occurs when the request address contains spaces
Describe the bug
Exception occurs when the request address contains spaces: Invalid character ' ' for QUERY_PARAM in "2023-12-11 00:00:00"
Before this, I was using the webflux gateway and this problem did not occur.
Details spring boot 3.2.0 spring cloud 2023.0.0 spring cloud starter gateway mvc 4.1.0 request url: http://localhost:8080/enterprise-service/api/v3/enterprise?start_created_time=2023-12-11 00:00:00&end_created_time=2023-12-12 00:00:00
I hope your team can help us analyze the possible causes and provide some solutions as soon as possible. Thank you very much!
In the future, please paste text rather than screenshots.
How are you accessing that URL? Through a browser it automatically URL encodes it.
@spencergibb I tried using the browser and Apifox but got the same error.
URL: http://localhost:8080/enterprise-service/api/v3/enterprise?start_created_time=2023-12-11%2000%3A00%3A00&end_created_time=2023-12-12%2000%3A00%3A00
Replacing spaces
with a +
things go through. I'm just not sure it's the responsibility of the gateway to do that.
Maybe @rstoyanchev might have an opinion?
Hi, we're facing issues with all encoded characters in query parameters. like the norwegian æøå
, among others (including space). I think this may be the same issue. I tried debugging the issue, and it seems we end up in a state where the encoded
variable is true
(based on the raw url) and then trying to add the decoded params (from serverRequest.params()
) here:
https://github.com/spring-cloud/spring-cloud-gateway/blob/main/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunction.java#L69-L77
Flipping the encoded
value works fine. Not sure the fix is as simple as negating it, though.
Stack trace as text:
java.lang.IllegalArgumentException: Invalid character ' ' for QUERY_PARAM in " "
at org.springframework.web.util.HierarchicalUriComponents.verifyUriComponent(HierarchicalUriComponents.java:422) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.util.HierarchicalUriComponents.lambda$verify$4(HierarchicalUriComponents.java:390) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.util.UnmodifiableMultiValueMap.lambda$forEach$0(UnmodifiableMultiValueMap.java:114) ~[spring-core-6.1.1.jar:6.1.1]
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[?:?]
at org.springframework.util.MultiValueMapAdapter.forEach(MultiValueMapAdapter.java:179) ~[spring-core-6.1.1.jar:6.1.1]
at org.springframework.util.UnmodifiableMultiValueMap.forEach(UnmodifiableMultiValueMap.java:114) ~[spring-core-6.1.1.jar:6.1.1]
at org.springframework.web.util.HierarchicalUriComponents.verify(HierarchicalUriComponents.java:387) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.util.HierarchicalUriComponents.<init>(HierarchicalUriComponents.java:146) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.util.UriComponentsBuilder.buildInternal(UriComponentsBuilder.java:445) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.util.UriComponentsBuilder.build(UriComponentsBuilder.java:433) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.cloud.gateway.server.mvc.handler.ProxyExchangeHandlerFunction.handle(ProxyExchangeHandlerFunction.java:76) ~[spring-cloud-gateway-server-mvc-4.1.0.jar:4.1.0]
at org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions$LookupProxyExchangeHandlerFunction.handle(HandlerFunctions.java:98) ~[spring-cloud-gateway-server-mvc-4.1.0.jar:4.1.0]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$ofRequestProcessor$3(HandlerFilterFunction.java:83) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$andThen$0(HandlerFilterFunction.java:58) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$ofRequestProcessor$3(HandlerFilterFunction.java:83) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$andThen$0(HandlerFilterFunction.java:58) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$ofRequestProcessor$3(HandlerFilterFunction.java:83) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$andThen$1(HandlerFilterFunction.java:59) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$andThen$1(HandlerFilterFunction.java:59) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.HandlerFilterFunction.lambda$apply$2(HandlerFilterFunction.java:70) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.function.support.HandlerFunctionAdapter.handle(HandlerFunctionAdapter.java:107) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.1.jar:6.1.1]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.1.1.jar:6.1.1]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.16.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.1.jar:6.1.1]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.16.jar:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.cloud.gateway.server.mvc.filter.WeightCalculatorFilter.doFilter(WeightCalculatorFilter.java:229) ~[spring-cloud-gateway-server-mvc-4.1.0.jar:4.1.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.cloud.gateway.server.mvc.filter.FormFilter.doFilter(FormFilter.java:97) ~[spring-cloud-gateway-server-mvc-4.1.0.jar:4.1.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.1.jar:6.1.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.1.jar:6.1.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:109) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.1.jar:6.1.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.1.jar:6.1.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.1.jar:6.1.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:673) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-10.1.16.jar:10.1.16]
at java.base/java.lang.Thread.run(Thread.java:833) [?:?]
@spencergibb @rstoyanchev When I use Webflux-based spring-cloud-gateway, I have no problem including space characters in my requests, Therefore, I think the logic of spring-cloud-gateway-mvc processing should be consistent with the behavior of spring-cloud-gateway-webflux
@tomgag There has been no effective official reply so far. How did you solve this problem based on the current version? Please help provide some solution ideas, thank you very much!
@tomgag
There has been no effective official reply so far. How did you solve this problem based on the current version?
Please help provide some solution ideas, thank you very much!
By holding our change. We own both sides, so might rewrite this to a POST.
@tomgag There has been no effective official reply so far. How did you solve this problem based on the current version? Please help provide some solution ideas, thank you very much!
By holding our change. We own both sides, so might rewrite this to a POST.
To rewrite the GET request into POST, we need to do a lot of adaptation work, and it does not conform to the style of restful api, so we hope there are other better ways to handle it.
@spencergibb @rstoyanchev @spring-cloud-issues
I think the core cause of this issue is the inconsistent behavior of the queryParam passed in the image below:
I hope the official can fix this problem as soon as possible. There has been no progress for three months.
Same issue with accentuated letters.
java.lang.IllegalArgumentException: Invalid character 'é' for QUERY_PARAM in "Veszprém_HU"
at org.springframework.web.util.HierarchicalUriComponents.verifyUriComponent(HierarchicalUriComponents.java:422) ~[spring-web-6.1.3.jar:6.1.3]
at org.springframework.web.util.HierarchicalUriComponents.lambda$verify$4(HierarchicalUriComponents.java:390) ~[spring-web-6.1.3.jar:6.1.3]
at org.springframework.util.UnmodifiableMultiValueMap.lambda$forEach$0(UnmodifiableMultiValueMap.java:114) ~[spring-core-6.1.3.jar:6.1.3]