-
Notifications
You must be signed in to change notification settings - Fork 38.5k
UriComponentBuilder doesn't work with encoded HTTP URL having '+'. [SPR-14828] #19394
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
Comments
Rossen Stoyanchev commented According to the URI spec RFC 3986, a "+" is allowed in the query (i.e. pchar > sub-delimiters > ";"). This matches our own Arjen Poutsma what's your take on this? Is the "+" encoded as an extra precaution against it being decoded and interpreted as a space? I found an old discussion on this here. Or could it be based on the older version of the spec RFC 2396 which does seem to call out "+" as a reserved character in the query? |
Arjen Poutsma commented It's been a while since I wrote that code, so I can't remember what was the reason for excluding the '+'. My guess would be the same as yours: it was based on an older version of the RFC. |
Alexandre Navarro commented I have exactly the same problem. Interested to fix it in a future version. |
Kazuki Shimizu commented Hi, Probably by this changes, @Test
public void test() {
// http://localhost:8080/?q=+
System.out.println(UriComponentsBuilder.fromHttpUrl(
"http://localhost:8080/").queryParam("q", "+").build().encode()
.toUri());
// http://localhost:8080/?q=%20
System.out.println(UriComponentsBuilder.fromHttpUrl(
"http://localhost:8080/").queryParam("q", " ").build().encode()
.toUri());
// http://localhost:8080/?q=%26
System.out.println(UriComponentsBuilder.fromHttpUrl(
"http://localhost:8080/").queryParam("q", "&").build().encode()
.toUri());
// http://localhost:8080/?q=%3D
System.out.println(UriComponentsBuilder.fromHttpUrl(
"http://localhost:8080/").queryParam("q", "=").build().encode()
.toUri());
} |
Rossen Stoyanchev commented This is by design indeed. Only reserved characters are reserved but "+" is allowed. Is this through the RestTemplate? If yes take a look at the |
Kazuki Shimizu commented Thanks for quick answer!
No, I don't use the |
Kazuki Shimizu commented Oh... Sorry, I click the "Add" button by mistake. I understood that need to change to use an another APIs. |
Dmitry Katsubo commented Rossen Stoyanchev: I've tried to locate "strict" mode in
Now I have difficulty in how to escape query part. Actually in my case I start from unencoded URL string, hence all characters that have special meaning should be encoded. How to do it?
|
Rossen Stoyanchev commented Dmitry Katsubo, the EncodingMode is an enum with 3 values. You need this: DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
factory.setEncodingMode(EncodingMode.VALUES_ONLY);
URI uri = factory.uriString("http://localhost:8080/{path}/print?value=%EA%B0%80+%EB%82%98").build("test+"); Note that strict encoding is only applied to expanded URI variable values (and the same is true for DefaultUriTemplateHandler). This is why your query is not getting encoded. See the Javadoc for details. Kazuki Shimizu the above List<String> vars = UriUtils.encodeUriVariables("+");
System.out.println(UriComponentsBuilder.fromHttpUrl(
"http://localhost:8080/?").queryParam("q", "{value}").build().expand(vars)
.toUri()); |
Dmitry Katsubo commented OK, here is an example which I expect to succeeded because I set query parameter as unencoded value with intent that
|
Rossen Stoyanchev commented Did you miss this part "strict encoding is only applied to expanded URI variable values" ? |
Dmitry Katsubo commented Is it possible to further extend API so that one can encode URL query parameters in one go? Namely:
|
Rossen Stoyanchev commented I've made |
Dmitry Katsubo commented
|
Rossen Stoyanchev commented I see, or you could build a MultiValueMap of query params, use UriUtils to encode, and pass into UriComponentsBuilder#query. The only catch is we need to enhance UriUtils to support MultiValueMaps. I think adding another encoding mode to DefaultUriBuilderFactory.EncodingMode would be perfectly okay to do. It's exactly what it's meant for -- provide control over encoding strategies. However I am not sure I understand exactly what the new mode is, i.e. aside from fully encoding query params, how does it work for others? |
Dmitry Katsubo commented I tried somehow to apply the behaviour I need using the strategies that I've mentioned above, but honestly I've failed. The problem is that once I replace At the moment I've decided to switch to If somebody is interested in code I came up with, here it goes:
|
Rossen Stoyanchev commented Dmitry Katsubo, Kazuki Shimizu I've created #21577 which should provide a solution. |
I know this is an old issue, but we are facing the exact same issue. We are using Spring webclient directly. So something like WebClient.builder()
.baseUrl("http://some-base-url")
.build()
.get()
.uri {
val uriBuilder = it.path("/some-path")
uriBuilder.queryParam("search", searchText)
uriBuilder.build()
}
.retrieve()
.awaitBody()
The So the workaround for us is we do something like: val factory = DefaultUriBuilderFactory("http://some-base-url")
factory.encodingMode = DefaultUriBuilderFactory.EncodingMode.NONE
WebClient.builder()
.uriBuilderFactory(factory)
.build()
.get()
.uri {
val uriBuilder = it.path("/some-path")
uriBuilder.queryParam("search", urlEncode(searchText))
uriBuilder.build()
}
.retrieve()
.awaitBody() So disable encoding and do the encoding our side. Here, urlEncode is just wrapper around Please let me know if I should open a new issue. I posted here, since this has correct context. |
Having same issue. UriComponentsBuilder doesn't encode '+'. So I take responsibility of encoding it myself using URLEncoder and it generates %2B but this time UriComponentsBuilder encodes % to 25 I don't know why? original query param => 2024-10-22T16:42:38+03:00 and it doesn't encode it but it encodes Issue should be re-opened |
@hviranicitco please review the section on encoding in the documentation. You can apply full encoding through URI variables: val uriBuilder = it.path("/some-path")
uriBuilder.queryParam("search", "{search}")
uriBuilder.build(searchText) |
Johnny Lim opened SPR-14828 and commented
'+' is valid for a space but with the following code:
I got the following error:
Affects: 4.3.3
Reference URL: https://github.com/izeye/spring-boot-throwaway-branches/blob/rest-and-logback-access/src/test/java/learningtest/org/springframework/web/UriComponentBuilderTests.java
Issue Links:
Referenced from: commits f2e293a
1 votes, 6 watchers
The text was updated successfully, but these errors were encountered: