views:

760

answers:

2

I am trying to find the best way of getting round a design flaw in a web app I'm helping to support. One part of the service passes a parameter ("myparam") to a .jsp page, which in turn calls a REST service including our myparam as a path parameter. The design flaw bit is that myparam should be passed as a form parameter, since it can be free text. However, we cannot change the implementation as other parties are involved at the .jsp end of things.

My solution was to encode the myparam using hex encoding (url encoding alone doesn't work as you end up with "%" etc. which the org.restlet implementation of REST doesn't like seeing in path parameters). Using the Apache codec library, I have something like this:

Option 1 (just hex):

String decodedParam = new String(Hex.decodeHex(myparam.toCharArray()));

which works for our purposes. What I really wanted to do was to combine URL- and Hex-encoding, so that I can really cover all posibilities:

Option 2 (hex + url-decoding):

Parameter preparation:

String workText = URLEncoder.encode(inText, encoding); // a
char[] encodedBytes = Hex.encodeHex(workText.getBytes()); // b
String myparam = new String(encodedBytes);

Decoding (REST):

String decodedParam = new String(Hex.decodeHex(myparam.toCharArray())); // c
String doubleDecodedParam = URLDecoder.decode(decodedParam, "UTF-8"); // d

I have two questions:

  1. why doesn't the second option work? (whenever I try and URL-decode my string at d) I get a java.lang.IllegalArgumentException). I've tested the double-encoding-and-decoding of my parameter values at http://ostermiller.org/calc/encode.html without problem.

  2. is there a better way to encode path parameters with REST?

+1  A: 

There's a bunch of stuff that doesn't look quite right to me in the above code concerning character sets. In the encoding step you are assuming that whatever the Hex class does (which framework is that one from?) is returning bytes that can be interpreted as a String in the encoding your JVM is running in. I guess this works if the contract of Hex.encodeHex() supports it.

Then there's the other side. First off, you're decoding the hex string using UTF-8. You've silently assumed that your JVM is running in UTF-8, as you are passing in the result of a new String(), which assumes that the char arrays from Hex.decodeHex() are in the encoding the JVM is currently running at, which can only be UTF-8 if you're decoding it as such. I also don't see the point of that URL encoding pass there. It seems like it's completely redundant.

I guess none of this is really the core issue. There's another problem of what is exactly happening in the intermediate JSP. It likely decodes whatever it gets and re-encodes it. That should be transparent, but I'm not sure on what level you're taking in this data. If you see it before it's decoded as a parameter a wrong interpretation might result.

wds
thanks for your comments, wds. My problem was that I reyling on the ostermiller site to provide me with example strings which I then tested in the REST interface: without checking on the encoding which was being used. More rigourous tests show that the double encoding works (test string -> URL encoded -> hex encoded and back again), but you're right: what happens in the middle is a bit of a black box. Since the parameters are email addresses with a couple of other allowable characters thrown in ("#", "," etc.) I've gone with the Hex encoding on its own.
davek
A: 

The percentage character always messes with the jersey webservice, why? im trying to send an enconded parameter from android, and im having trouble.

Maxrunner
what I've recently been doing is to encode my parameters i) in Base64 and then ii) URL-encode the base64-encoded value. Thst way I know I'm safe with my URLs.
davek