javax UriBuilder doesn't escape '}' correctly

1k Views Asked by At

javax.ws.rs.core.UriBuilder is not escaping } correctly:

import javax.ws.rs.core.UriBuilder;
public void test() {
    final UriBuilder builder = UriBuilder.fromUri("http://host");
    builder.path("dir}one");
    l.info(builder.toString());
}

Will output http://host/dir}one, leaving } unescaped.

Whereas org.apache.http.client.utils.URIBuilder:

org.apache.http.client.utils.URIBuilder;
public void testApache() {
    final URIBuilder builder = new URIBuilder(URI.create("http://host"));
    builder.setPath("dir}one");
    l.info(builder.toString());
}

Will output http://hostdir%7Done, escaping } with %7D as expected.

Is this a bug in the javax.ws.rs.core.UriBuilder?

2

There are 2 best solutions below

4
On

According to RFC 3986 the character } is not a reserved character and therefore it need not be escaped. It can be escaped with %7D, but that is not necessary.

So both UriBuilder implementations behave correctly.

0
On

Actually, if you don't escape braces, RestEasy (containing an implementation of UriBuilder) will complain by throwing a jakarta.ws.rs.core.UriBuilderException: RESTEASY003330: Failed to create URI caused by a java.net.URISyntaxException: Illegal character in query at index. However, I'm not sure that it can be fixed in jakarta.​ws.​rs.​core.UriBuilder because it's a template-aware builder, it uses the curly braces to delimit templates. Therefore, in my humble opinion, it's up to the caller to indicate that some curly braces aren't used for building templates so that RestEasy (or Jersey) doesn't try to interpret the string between curly braces as a template and to avoid sending unencoded curly braces to java.base/java.net.URI$Parser.checkChars() that rejects them for sure, no matter what the RFC says.

Personally, I simply do that:

final String encoded = unencoded.replace("{", "%7B").replace("}", "%7D");

Keep in mind that you can break template management by using this dirty kludge unwisely.

P.S: RestEasy's documentation seems to confirm my findings.