Wednesday, December 7, 2011

Tomcat truncating cookie values problem

The Problem
When using Java running in the Tomcat servlet container you may observe cookie values fetched from javax.servlet.http.Cookie using getValue() seem incomplete.

Example
I like to parse various cookies in Java code, one particular high value cookie for me is Google Anaytics' Campaign Tracking Cookie the UTMZ.
UTMZ typically looks like:
__utmz=1.1322309384.1.1.utmcsr=anothersite.com|utmccn=(referral)|utmcmd=referral|utmctr=9371183|utmcct=/

However when reading and displaying this cookie in Java and Tomcat you'll see the value:
1.1322309384.1.1.utmcsr

This is because Tomcat 6.0.18 now adheres to the cookie spec more tightly than previous versions.
This may cause you multiple issues including:

  • The value you expect to see is incomplete (a quick look with Google Chrome -> Inspect Element -> Network -> Headers -> Request Headers shows that the browser is sending the full cookie value to Tomcat).
  • Code that did work on a previous Tomcat suddenly breaks.
Solution
If you are in control of the cookie, i.e. you write it then you need to ensure a version 0 cookie doesn't contain any of the following characters: equals =, parentheses (), colon :

If like the above example you are powerless to control the cookie format, you need to run Tomcat with some additional system properties set. The following added to catalina.properties will do the trick:

org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUALS_IN_VALUE=true
org.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0=true

Further info can be found in the Tomcat Config Docs







4 comments:

  1. Thanks! That's exactly what I needed!!

    ReplyDelete
  2. Is it working for you? For me is not working at all... Maybe an update from ga.js to analytics.js is needed?

    ReplyDelete
  3. This seem to work only in tomcat 7 (v7.0.42) for me. In tomcat 6 (v6.0.29) it truncates from the second equals character.

    ReplyDelete
    Replies
    1. Hi,
      Exactly!
      In the tomcat 6 doc (http://tomcat.apache.org/tomcat-6.0-doc/config/systemprops.html) you find the parameter ALLOW_EQUALS_IN_VALUE, but *not* the parameter ALLOW_HTTP_SEPARATORS_IN_V0.

      Therefore, the utmz cookie value may contain equal signs, but is still truncated right when it comes across a http separator sign, e.g. the first opening parenthesis. In the following example after "utmccn=":

      __utmz=12322452.1123230062.42.2.utmcsr=google|utmccn=(organic)|u

      Because of this missing config parameter in tomcat 6, I had to work around it by manually parsing the http cookie header:

      E.g.:

      String cookieHeader = request.getHeader("Cookie");
      String utmzCookie = StringUtils.substringBetween(cookieHeader, "__utmz=", ";");
      ...further parsing...

      Let me know if I'm wrong or if there are better possiblities to work around it. At least for me, this worked.

      Regards,
      Joachim

      Delete