Query string parameters with equals in the value throw and exception in build method:
@Test
public void equals_in_query_string_value() {
var str = "https://localhost:8080/callback?param1=a%20b¶m2=1=2";
var uri = URI.create(str);
var actual = UriComponentsBuilder.fromUri(uri)
.build(true)
.toUri();
assertEquals(uri, actual);
}
Exception:
java.lang.IllegalArgumentException: Invalid character '=' for QUERY_PARAM in "1=2"
I use true
because the source is already a valid URI and I do not want a doble escape in the param1.
I did not find anything in any standard or convention that says that this character is forbidden, I tried different implementations and they worked as espected: URLSearchParams in any browser, node queryparams, etc.
Expected behaviour:
- Both URIs in the test should be equal.
- No exception should be thrown.
param2
equals1=2
References:
- https://www.rfc-editor.org/rfc/rfc3986#section-3.4
URL (Web API) example:
new URL('https://localhost:8080/callback?param1=a%20b¶m2=1=2').searchParams
URLSearchParams { 'param1' => 'a b', 'param2' => '1=2' }
Comment From: poutsma
UriComponentsBuilder
has stricter requirements than java.net.URI
. Most of these were requested by users, for instance see here for someone who does want to encode =
characters.
There are ways to bypass the validation, for instance:
var str = "https://localhost:8080/callback?param1=a%20b¶m2=1=2";
var uri = URI.create(str);
var uriString = UriComponentsBuilder.fromUri(uri).build().toUriString();
var actual = URI.create(uriString);
assertEquals(uri, actual);
Comment From: victorherraiz
I have the following use case: the URI that I am calling is a callback sent by third parties. Those URIs, with equals in the value part, are understood and processed correctly in Tomcat, Netty, Node, and are valid from a standards point of view. After that, depending on the outcome of preceding operations, I add more parameters to the URI before the actual call.
In my opinion, there is a difference between validation and encoding. Not only the characters that you want to encode are valid ones, but there are also several examples and different recommendations. I suggest splitting the method
public abstract boolean isAllowed(int c)
in the class Type into two, one for validation and another for encoding. This will cover the user request and accept valid URIs at the same time, and in some cases, it could use the same implementation.
Another problem is that the UriComponentBuilder is at the heart of WebClient and RestClient, which makes the workaround a little bit messy.
@poutsma, any thoughts?