Search code examples
javaescapingjax-rsresteasyjersey-client

Escaping `%` symbol in query parameter in JAX-RS


I try to send GET request with some URL string as a parameter using any of Jersey or Resteasy

Response response = new ResteasyClientBuilder()
        .build()
        .target(UriBuilder.fromPath("https://foo.bar"))
        .queryParam("url", "http://hostname.com/The%20URL%20with spaces.jpg")
        .request()
        .get();

Both implementations send
https://foo.bar?url=http%3A%2F%2Fhostname.com%2FThe%20URL%20with%20spaces.jpg

I assume that original space is escaped with %20 and original %20 is double-escaped in the query parameter.
But it isn't.
Original space and %20 are mixed, and on the server side I get unescaped string with all %20 converted to spaces and the string gets broken.

According to source code of Resteasy, it "Keeps encoded values "%..." and template parameters intact". But I haven't found any word in the JEE docs about this behavior.

Should I escape my string before adding it as a parameter?
What escaper should I use to be sure that it escapes all of "%..." and template parameters, and everithing it escapes in a parameter is successfully unescaped by server?


Solution

  • The solution for standard JAX-RS WebTarget is to not apply parameters directly but apply them as template parameters.

    Response response = new ResteasyClientBuilder()
            .build()
            .target(UriBuilder.fromPath("https://foo.bar"))
            .queryParam("url", "{urlTemplate}")
            .resolveTemplate("urlTemplate", "http://hostname.com/The%20URL%20with spaces.jpg")
            .request()
            .get();
    

    First, we add some template {urlTemplate} as a parameter value, and then render this template with the real value.
    WebTarget always assumes that the given parameter as a possible template, and doesn't escape some characters
    But .resolveTemplate() guarantees escaping of all characters that should be escaped