users@jersey.java.net

Re: [Jersey] UriComponent.validate does not allow brackets []?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 22 Jul 2008 13:19:56 +0200

Martin Grotzke wrote:
> Hi,
>
> we have a resource method that accepts some query parameter named fq
> (filter query). The fq param accepts ranges for e.g. a price filter, so
> that the value for the fq param might be "price:[160%20TO%20200]".
>

According to the URI ABNF:

    sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
                / "*" / "+" / "," / ";" / "="

    unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
    pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
    query = *( pchar / "/" / "?" )

'[' and ']' characters are not valid characters of a URI query component.


> When a client performs a request with such a param value, the
> UriComponent.validate says that this is not valid:
>
> [ERROR] 17 Jul 2008 15:50:45,166 btpool0-1 com.sun.jersey.spi.spring.container.servlet.SpringServlet.service:
> Caught exception.
>
> java.lang.IllegalArgumentException: The string 'q=foo&fq=price:[160%20TO%20200]' for the URI component QUERY contains an invalid character, '[', at index 15
> at com.sun.jersey.api.uri.UriComponent.validate(UriComponent.java:95)
> at com.sun.jersey.impl.uri.UriBuilderImpl.encode(UriBuilderImpl.java:353)
> at com.sun.jersey.impl.uri.UriBuilderImpl.replaceQueryParams(UriBuilderImpl.java:286)
> at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:273)
>
> I think this should be valid, even UriComponent.decode handles this
> correctly.
>

The JavaDoc states:

/**
  * Decodes characters of a string that are percent-encoded octets using
  * UTF-8 decoding (if needed).
  * <p>
  * It is assumed that the string is valid according to an (unspecified)
URI
  * component type. If a sequence of contiguous percent-encoded octets is
  * not a valid UTF-8 character then the octets are replaced with '\uFFFD'.
  * <p>
  * If the URI component is of type HOST then any "%" found between "[]" is
  * left alone. It is an IPv6 literal with a scope_id.
  * <p>
  * @param s the string to be decoded.
  * @param t the URI component type, may be null.
  * @return the decoded string.
  * @throws IllegalArgumentException if a malformed percent-encoded octet is
  * detected
  */

Paul.

> One possible patch I can think of is in
> UriComponent.creatingEncodingTables:
>
> Index: src/api/com/sun/jersey/api/uri/UriComponent.java
> ===================================================================
> --- src/api/com/sun/jersey/api/uri/UriComponent.java (revision 1166)
> +++ src/api/com/sun/jersey/api/uri/UriComponent.java (working copy)
> @@ -243,6 +243,8 @@
> tables[Type.PATH.ordinal()] = creatingEncodingTable(l);
>
> l.add("?");
> + l.add("[");
> + l.add("]");
>
> tables[Type.QUERY.ordinal()] = creatingEncodingTable(l);
> tables[Type.FRAGMENT.ordinal()] = tables[Type.QUERY.ordinal()];
>
> This test goes through then:
>
> Index: test/com/sun/jersey/impl/UriComponentValidateTest.java
> ===================================================================
> --- test/com/sun/jersey/impl/UriComponentValidateTest.java (revision 1166)
> +++ test/com/sun/jersey/impl/UriComponentValidateTest.java (working copy)
> @@ -54,4 +54,8 @@
> assertEquals(true, UriComponent.valid("/x20y", UriComponent.Type.PATH));
> assertEquals(true, UriComponent.valid("/x%20y", UriComponent.Type.PATH));
> }
> +
> + public void testQuery() {
> + assertEquals(true, UriComponent.valid("fq=price:[1%20TO%20100]", UriComponent.Type.QUERY));
> + }
> }
>
> Please notice that I took this diff in a branch, so line numbers might
> be wrong.
>
> Any thoughts on this?
>
> Thanx && cheers,
> Martin
>
>

-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109