Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In spring cloud gateway mvc, an exception occurs when the request address contains spaces #3185

Closed
zengqinglei opened this issue Dec 14, 2023 · 10 comments
Assignees
Labels
Milestone

Comments

@zengqinglei
Copy link

zengqinglei commented Dec 14, 2023

Describe the bug
Exception occurs when the request address contains spaces: Invalid character ' ' for QUERY_PARAM in "2023-12-11 00:00:00"
image

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!

@spencergibb
Copy link
Member

In the future, please paste text rather than screenshots.

How are you accessing that URL? Through a browser it automatically URL encodes it.

@zengqinglei
Copy link
Author

@spencergibb
Copy link
Member

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?

@tomgag
Copy link

tomgag commented Dec 21, 2023

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) [?:?]

@zengqinglei
Copy link
Author

@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

@zengqinglei
Copy link
Author

@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
Copy link

tomgag commented Jan 11, 2024

@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.

@zengqinglei
Copy link
Author

@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.

@zengqinglei
Copy link
Author

@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:
image

I hope the official can fix this problem as soon as possible. There has been no progress for three months.

@spencergibb spencergibb self-assigned this Feb 7, 2024
@spencergibb spencergibb added this to the 4.1.2 milestone Feb 7, 2024
@spencergibb spencergibb changed the title When using the new version of spring cloud gateway mvc, an exception occurs when the request address contains spaces In spring cloud gateway mvc, an exception occurs when the request address contains spaces Feb 7, 2024
@frichard97
Copy link

frichard97 commented Mar 1, 2024

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]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
No open projects
Status: Done
Development

No branches or pull requests

5 participants