users@jersey.java.net

[Jersey] How to force URIBuilder.path(.) to encode parameters like "%AD"?

From: Carlos Santos Canelles <csantos_at_denodo.com>
Date: Mon, 3 Feb 2014 10:21:55 +0100

How to force "URIBuilder.path(...)" to encode parameters like "%AD"?

The methods "path", "replacePath" and "segment" of "URIBuilder" do not
always encode parameters with percentage, correctly.

When a parameter contains the character "%" followed by two characters that
together form an URL-encoded character, the "%" is not encoded as "%25".

 

For example

URI uri = UriBuilder.fromUri("https://dummy.com").queryParam("param",
"%AD");

String test = uri.build().toString();

 

"test" is "https://dummy.com?param=%AD"

But it should be "https://dummy.com?param=%25AD" (with the character "%"
encoded as "%25")

 

The method "UriBuilderImpl.queryParam(...)" behaves like this when the two
characters following the "%" are hexadecimal. I.e, the method
"com.sun.jersey.api.uri.UriComponent.isHexCharacter(char)" returns true for
the characters following the "%".

I think the behavior of "UriBuilderImpl" is correct because I guess it tries
to not encode parameters that already are encoded. But in my scenario, I
will never try to create URLs with parameters that already encoded.

 

What should I do?

My Web application uses Jersey and in many places I build URIs using the
class "UriBuilder" or invoke the method "getBaseUriBuilder" of "UriInfo"
objects.

I can replace "%" with "%25", every time I invoke the methods "queryParam",
"replaceQueryParam" or "segment". But I am looking for a less cumbersome
solution.

 

How can I make Jersey to return my own implementation of "UriBuilder"?

I thought of creating a class that extends "UriBuilderImpl" that overrides
these methods and that perform this replacing before invoking
super.queryParam(...) or whatever.

Is there any way of making Jersey to return my own "UriBuilder" instead of
"UriBuilderImpl", when invoking "UriBuilder.fromURL(...)",
"UriInfo.getBaseUriBuilder(...)", etc?

 

Looking at the method "RuntimeDelegate", I thought of extending
"RuntimeDelegateImpl". My implementation would override the method
"createUriBuilder(...)", which would return my own "UriBuilder", instead of
"UriBuilderImpl". Then, I would add the file
"META-INF/services/javax.ws.rs.ext.RuntimeDelegate" and in it, a the full
class name of my "RuntimeDelegateImpl".

The problem is that the jersey-bundle.jar already contains a
"META-INF/services/javax.ws.rs.ext.RuntimeDelegate" that points to
"com.sun.jersey.server.impl.provider.RuntimeDelegateImpl", so the container
loads that file instead of my "javax.ws.rs.ext.RuntimeDelegate". Therefore,
it does not load my "RuntimeDelegateimplementation".

 

Is it possible to provide my own implementation of RuntimeDelegate? Or
should I take a different approach?