Friday, November 2, 2012

Grails URL Encoding

Bug: Form data being encoded twice in Grails 2.1.1


I recently run into a bug related to character encoding in Grails 2.1.1 application that manifested a priory only when the web app was deployed into production.  
All tests where passing during CI builds as well as local development environment.
It was a tricky issue to figure it out, so I want to share it here, hopping to save you some time if you encounter this problem and are fortunate enough to find this post :)  

Say you're dealing with i18n and have UTF-8 form encoded text data (application/x-www-form-urlencoded), somehow after posting a text in Cyrillic, the contents were being doubly encoded, messing up the original text data..

The issue does not manifest in development mode,  or rather, I discovered that if you use IntelliJ IDE to launch the web application ("exploded mode" )  all is normal, that is the Cyrillic text is properly encoded.  Instead,  if you build the war using "grails war" command and manually deploy it to Tomcat, then this bug happens.

Digging deeper we had the following sloppy code to encode the form data:

URLEncoder.encode(formData)

As you can see from the Java Doc API,  this is a deprecated method, where the resulting string may vary depending on the platform's default.

I'm not sure why the platform default changes when packaging the war via "grails war" command versus running the war from within the IDE, but the fact is that this had cost us a few hours spent on debugging.

Method Summary
static Stringencode(String s)
          Deprecated. The resulting string may vary depending on the platform's default encoding. Instead, use the encode(String,String) method to specify the encoding.
static Stringencode(String s, String enc)
          Translates a string into application/x-www-form-urlencoded format using a specific encoding scheme.

To fix, simply change the code to URLEncoder.encode(formData, "UTF-8")

So, discovering the behavior about packaged versus exploded war phenomena  was half the battle to be able to reproduce this bug.   However, this could have been avoided altogether if the developer had paid attention to compiler deprecated warnings. Or  not done this:

-Dgrails.log.deprecated=false  //to turn off for development mode  

Hope this post can help some fellow developers !

Happy Coding !




 

No comments:

Post a Comment