ColdFusion, URLEncoding and RFC 3986

On November 19, 2011, in ColdFusion, by Anuj Gakhar

ColdFusion has an inbuilt function for encoding URL vars. URLEncodedFormat – which does the job well, but it does not follow the RFC 3986 , the Internet standards document that describes the encoding of URLs, very strictly. This does not cause problems 98% of the times but I recently found out while working with some API’s that require signed signatures to be sent in order to authenticate the API request e.g. Amazon Web Services, that it does indeed cause some problems. Your signature will not match with the signature on the other end.

RFC 3986 basically says this -> keep ALPHA, DIGIT, ‘-‘, ‘.’, ‘_’, ‘~’ and encode the rest

The problem is that ColdFusion encodes some characters that should not be encoded. These characters are :-

  • . (dot)
  • – (hyphen)
  • _ (underscore)
  • ~ (tilde)

The solution is to use either of the 2 options below :-

[cf]string = replacelist(
urlencodedformat(string),
"%2D,%2E,%5F,%7E",
"-,.,_,~"
);[/cf]

or use Java

[cf]function rfc3986_encodedFormat(string stringToEncode){
var encoder = createObject("java","java.net.URLEncoder");
return encoder.encode(stringToEncode, "utf-8")
.replace("+", "%20")
.replace("*", "%2A")
.replace("%7E", "~");
}[/cf]

Example

Let’s take an example encoding the same string with both CF and Java :-
[cf]string = "part1.part2-part3_part4~part5";
cfEncoding = URlEncodedFormat(string);

javaEncoder = createObject("java","java.net.URLEncoder");
javaEncoding = javaEncoder.encode(string,"utf-8"));
[/cf]
cfEncoding outputs this – part1%2Epart2%2Dpart3%5Fpart4%7Epart5

javaEncoding outputs this – part1.part2-part3_part4%7Epart5

So, it looks like Java encoding is a bit better but it still needs to have the “~” character replaced back from “%7E” to “~”.

Tagged with:  

8 Responses to ColdFusion, URLEncoding and RFC 3986

  1. James Moberg says:

    Another option would be to file it as a bug and hope that Adobe patches this in CF9 and fixes this in the 10th version of ColdFusion (Zeus) that they are working on. Does the mess up form posted values too? (I don’t normally post variables to third party services in the URL scope if I have a choice.)

  2. Anuj Gakhar says:

    Hi James, I don’t think it messes up form posted variables. I mean, it wouldn’t make a difference at all if you were URL encoding in ColdFusion and decoding in ColdFusion as well. The only time it matters is when you sign a signature in ColdFusion and send that as a parameter to a third party API and normally they would be creating the same signature their end using the parameters passed and that’s when the signatures don’t match because of the irregularity in URLEncodedFormat()..

  3. Philip says:

    Good post, Anuj, looks like java has the same issue, why encoding with java lib and you still have to decode?

  4. Consider adding ‘all’ to the replaces. I found that only every other space/+ was changed to %20.
    This edit fixed that issue:

    return encoder.encode(stringToEncode, “utf-8”)
    .replace(“+”, “%20”, “all”)
    .replace(“*”, “%2A”, “all”)
    .replace(“%7E”, “~”, “all”);
    }

    • Jules – I ran into the same thing today. As far as I can tell this is because the CF11 introduced “member functions” which means that in CF11 and upwards “.replace” refers to ColdFusion’s replace, whereas prior to CF11 it would have been calling not java.lang.String.replace on the underlying java object. Bit of a trap!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

© 2011 Anuj Gakhar
%d bloggers like this: