views:

745

answers:

3

I have a single Rails 2.2.2 app that I want to 'share' with multiple clients. Each client has his own domain name and database. The purpose is to allow one Rails app to 'host' many websites.

I am using Apache as a front end to a mongrel cluster, as the web server. To enable Rails to know which request is for which client, Apache adds a 'client_id' header to each request. Rails uses this 'client_id' to choose the correct database.

This works perfectly well as long as I am only accessing it from one domain name at at time. Say 'example1.com'.

It even works fine -- mostly -- when many users are accessing the application from multiple domain names at the same time.

The one problem I have is that when two users are accessing the application from two domain names at the same time, then cookies are reset in an unexpected way.

The problem is illustrated in the log snippet below:

The 1st request is from User 1 logged into example1.com.

The 2nd request is from User 2, for the example2.com home page.

The 3rd request is from User 1, for another page in the application. Presumably, the request included the original cookie. The question is, why did Rails send a different cookie back???

Note that, unlike several other questions, I am not trying to share the same cookie across multiple domains. User 1 and User 2 in the example above are accessing different domains.

-- John

**1st Request from USER 1 for example1.com**
    Processing Admin::CmsController#index (for 75.127.142.66 at 2009-01-27 13:15:27) [GET]
      Session ID: 00b9cfb6fd397e5c9934ea58eaef648d
    >>> Request for client 90873721, EXAMPLE1.COM
    Rendering template within layouts/admin/standard
    Rendering admin/cms/list
    Completed in 114ms (View: 14, DB: 81) | 200 OK [https://example1.com/admin/cms]

**2nd Request from User 2 for example2.com**    
    Processing CmsController#cms_show (for 64.1.215.163 at 2009-01-27 13:16:15) [GET]
      Session ID: 4fed1c59001f7484a63fb6280376825a
      Parameters: {"alias"=>"home.html"}
    >>> Request for client 48218343, EXAMPLE2.COM
    ### alias: home.html
    Rendering template within layouts/two-column
    Rendering cms/cms_show
    Completed in 23ms (View: 13, DB: 3) | 200 OK [http://example2.com/]

**3rd Request from User 1 for example1.com -- note session ID changes!!!**    
    Processing Admin::CmsController#index (for 75.127.142.66 at 2009-01-27 13:16:18) [GET]
      Session ID: 85c178aa70ed2bef6a767e844bf6c6d6
    >>> Request for client 90873721, EXAMPLE1.COM
    ####### 'admin/cms', 'index'
    Redirected to actionsignincontroller/admin/user
    Filter chain halted as [:check_authentication] rendered_or_redirected.
    Completed in 4ms | 302 Found [https://example1.com/admin/cms]

**4th request -- redirected from 3rd request**    
    Processing Admin::UserController#signin (for 75.127.142.66 at 2009-01-27 13:16:18) [GET]
      Session ID: 85c178aa70ed2bef6a767e844bf6c6d6
    >>> Request for client 90873721, EXAMPLE1.COM
    Rendering template within layouts/admin/standard
    Rendering admin/user/signin
    Completed in 10ms (View: 6, DB: 0) | 200 OK [https://example1.com/admin/user/signin]
A: 

Cookies are domain-dependent, so you should use a different technique - a single server issuing cookies/creating sessions. Check out http://stackoverflow.com/questions/216430/cross-domain-user-tracking

Spikolynn
A: 

I'm not trying to track users across different domains. In fact, if one user has two browsers open, and is using two domains at the same time, then he has two different session cookies, one for each domain.

John
+1  A: 

Well, I 'solved' the problem by eliminating the shared mongrel_cluster, and giving each domain it's own mongrel instance.

I was hoping that I could save some server resources by sharing a single mongrel cluster, but to do so, I'll need to figure out how to solve this cookie problem.

By the way, I found a partial solution in "Advanced Rails Recipes" Recipe 83, "Give Users Their Own Subdomain". The recipe also explains how to give users their own domain names, but it uses a different approach than the one I was trying.

John