I can't seem to find this mentioned explicitly, but it seems that you can't send an escaped plus sign ("%2b") as a query arg value if you're using java.net.URI, since the query arg is escaped.
// bad: http://example.com/foo?a=%252b
new URI("http", null, "example.com", 80, "/foo", "a=%2b", null);
Tried an actual "+" character, but that gets sent as-is, so the server will interpret it as a space.
// bad: http://example.com/foo?a=+
new URI("http", null, "example.com", 80, "/foo", "a=+", null);
So I guess you just have to do the percent-encoding of the query arg keys and values yourself and use the single-argument URI constructor that doesn't escape? Maybe let URI escape the "path", since the rules are tricky (eg, the "+" character means a plus character, not a space, when in the path):
// good: http://example.com/foo?a=%2b
new URI(new URI("http", null, "example.com", 80, "/foo", null, null).toASCIIString() + "?a=%2b");
Also, the docs claim you can create a URI like this and it will be identical to the source URI:
URI u = ...;
URI identical = new URI(u.getScheme(),
u.getUserInfo(),
u.getPath(), u.getQuery(),
u.getFragment());
but that's not true when it contains %2b
URI u = new URI("http://example.com:80/foo?a=%2b");
URI identical = ...; // not identical! http://example.com:80/foo?a=+
Frustrating, I guess that's why everyone uses apache commons or spring classes instead?
PS: http://docs.oracle.com/javase/6/docs/api/java/net/URI.html references a URI constructor that does not exist in "the following identities also hold" section. It needs to remove the "authority" parameter.
I run into same trouble. After some researching, I think that if you need an %2b encoding of plus symbol, it is better not to use URI class as a result. I am using code like this:
URI uri = new URI(...);
String asciiUrl = uri.toASCIIString();
String plusReplaced = asciiUrl.replace("+", "%2b");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With