Christopher Smith opened SPR-14256 and commented
UriComponentsBuilder
does not encode query parameters, expecting them to be encoded by the client already. The documentation does not indicate one way or another whether pre-encoding is necessary, and it would be helpful to note that it is.
Affects: 4.3 RC1
Comment From: spring-projects-issues
Rossen Stoyanchev commented
Query parameters it does encode, so I'm not quite sure what scenario you're looking at. The following works and is documented in the Javadoc:
UriComponents uriComponents = UriComponentsBuilder.fromUriString("/path?q={var}")
.buildAndExpand("a=b")
.encode();
assertEquals("q=a%3Db", uriComponents.getQuery());
Comment From: spring-projects-issues
Tristan Lins commented
Here are two issues I have with the UriComponentsBuilder:
The `&` will be encoded twice:
```java
@Grab(group='org.springframework', module='spring-web', version='4.3.10.RELEASE')
import org.codehaus.groovy.runtime.InvokerHelper
import org.springframework.web.util.UriComponentsBuilder
URI source = new URI("http://example.com?foo=b%26r") // ?foo=b&r
URI target = UriComponentsBuilder.fromUri(source).build().toUri()
assert Objects.equals(source, target): "${source} != ${target}"
Ends with AssertionError: http://example.com?foo=b%26r != http://example.com?foo=b%2526r
The &
will not be encoded either:
@Grab(group='org.springframework', module='spring-web', version='4.3.10.RELEASE')
import org.codehaus.groovy.runtime.InvokerHelper
import org.springframework.web.util.UriComponentsBuilder
URI source = new URI("http://example.com?foo=b%26r") // ?foo=b&r
URI target = UriComponentsBuilder.newInstance()
.scheme("http")
.host("example.com")
.queryParam("foo", "b&r")
.build().toUri()
assert Objects.equals(source, target): "${source} != ${target}"
Ends with AssertionError: http://example.com?foo=b%26r != http://example.com?foo=b&r
Comment From: spring-projects-issues
Rossen Stoyanchev commented
In the second example, you're missing the instruction to encode:
URI target = UriComponentsBuilder.newInstance()
.scheme("http")
.host("example.com")
.queryParam("foo", "b&r")
.build()
.encode()
.toUri();
The reason the first encodes is because the constructor of URI encodes "%". In that case the source URI is already encoded and you could specify that through a flag on the build method:
URI target = UriComponentsBuilder.fromUri(source).build(true).toUri();
That said arguably when fromUri(URI)
is used, the "encoded" flag should be assumed. That's an improvement we can make but please open a separate ticket since it's much more specific, i.e. something like "Double encoding issue when using UriComponents#fromUri(URI)".
Comment From: spring-projects-issues
Rossen Stoyanchev commented
Resolving as "Works as designed" based on original description.
Comment From: spring-projects-issues
Tristan Lins commented
Thanks for explanation, I give it a try :-)
Comment From: theaspect
For those who will come here, example with multiple params
UriComponentsBuilder.fromHttpUrl("http://localhost/path")
.queryParam("v1","{v1}")
.queryParam("v2", "{v2}")
.buildAndExpand("a=b", "10")
.encode()
// http://localhost/path?v1=a%3Db&v2=10
Comment From: nitesr
UriComponentsBuilder doesn't encode + in the value .. here is the test which it fails
UriComponents components = UriComponentsBuilder.fromHttpUrl("http://localhost/path")
.queryParam("p","{v}")
.buildAndExpand("a+b=")
.encode();
assertEquals("p=a%2Bb%3D", components.getQuery());
Comment From: bclozel
@nitesr please avoid commenting on an old issue and creating a new one, this is duplicating efforts. See #29838