Encoding/decoding REST path parameters

Tags: , , , ,



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?

Answer

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.



Source: stackoverflow