Wednesday 3 June 2009

Having trouble with HTTP sessions in an Apache httpd, mod_proxy and Tomcat setup?

Today I ran into an issue where a new HTTP session was created for each HTTP request. Besides wasting resources, this can obviously lead to unwanted behaviour, such as locale settings not being remembered, etc. My infrastructural setup was as follows:
  • Apache Tomcat 5.5.25
  • Apache HTTPd 2.2.3
  • mod_proxy (no clue what version)
Before we dive into the solution, let's first try to understand the problem. So, here's what happens:
  1. One of your beloved users sends an HTTP request to your application, for example http://www.example.com/my-app.
  2. Apache httpd receives the request and your mod_proxy configuration matches the request and forwards it to http://localhost:8080/internal-app.
  3. Apache Tomcat receives the request. Let's assume no session has been created before, so your app creates a new one and in response sends a cookie to the browser, which holds the session id for later reference. Now, a cookie needs to have a path set and the default is your context path. Aha! So now a cookie has been created for domain www.example.com and path /internal-app, which is wrong, since the outside world sees the application running on path /my-app.
  4. Your beloved user now sends another HTTP request to your application and the cookie (with the session id) is not sent with it, since the request is for path /my-app and the cookie is set to /internal-app.
  5. Mod_proxy once again forwards the request to Tomcat. Your app will attempt to read a session id from the cookie, but it can't find it. Hence, a new session is created (for each subsequent request, since the paths will never match).
OK, now that we understand the problem, lets try to fix it. I see two possible solutions.

Tell mod_proxy to rewrite cookie paths

The least intrusive method is  to let mod_proxy rewrite the path of cookies being created by your application, which can be done using the ProxyPassReverseCookiePath directive. For example:

        ProxyVia on
        ProxyPassReverse /my-app http://localhost:8080/internal-app 
        ProxyPassReverseCookiePath /internal-app /my-app
        ProxyPass /my-app http://localhost:8080/internal-app

If you're using Apache httpd 2.2 you are in luck, otherwise this won't work :-(

Let Tomcat set the path of session cookies to root

Another way to go around our problem is to configure Tomcat to set the path of the cookie for the session id to the root (/). You can do this by adding the emptySessionPath="true" attribute to your connector configuration in your server.xml (which is located in the conf directory of your Tomcat installation).

A disadvantage of this solution is that it affects your entire Tomcat installation (please correct me if I'm wrong about this).

If you have any other solutions, please feel free to comment!

No comments:

Post a Comment