Our application’s UI consists of 2 types of screens: the usual web pages and the game screen. We wanted our users to get to the game screen as quickly as possible, because that’s where all the fun happens. So when you get to the homepage, you click Play and you’re in. You don’t need to sign up or deposit at this point, you can do that on the game screen after you have seen how fun the game is.

We’ve already had a working signup, login, ID verification, depositing pages implemented, so a logical solution was to pop up an iframe with the existing signup page and a minimal layout, so the user doesn’t have to leave the game.

Our game client uses ajax polling, i.e. makes a request to the server about every second. We decided to do this, so we can release our new game sooner, and it will be good enough under the current load with a little help from memcached.
If every request would take 0 seconds from the browser’s point of view, we would have had no problems. However, because we store the session in a cookie, when an Ajax request and session-changing request in the iframe overlap, there was a major cookie-fight between:

Set-Cookie header when the session was accessed, and it doesn’t know about B, because that’s not stored anywhere on the backend. So the browser set the cookie to A.The first fix was to avoid accessing the session variable in Rails for requests that don’t need authentication. I wrote a SessionDisabler mixin for controllers, and invoked it as filters:
# in the superclass of all API controllers:
prepend_before_filter :disable_session
# some controllers that need authentication:
skip_before_filter :disable_session, :only => :create
The problem has apparently gone away, but a user reported a problem where he was repeatedly logged out automatically. This must have been caused by the fact that requests that still need authentication keep resetting the session cookie. Actually, even if these requests need authentication, they don’t need to set the cookie, none of them is doing login or logout.
So all we had to do is to remove this Set-Cookie header from the responses for all API requests.
There is a directive in Nginx’s HttpProxyModule, proxy_hide_header, but Nginx was unhelpful, as it only matches a single location directive for a request.
The last thing we want to do is to duplicate everything in the location / section for location /api/v1/.
Luckily, we use chef, which can generate the config file from an erb template:
# vhost.conf.erb
…
<% ['/', '/api/v1/'].each do |path| -%>
location <%= path %> {
…
<% if path == '/api/v1/' -%>
proxy_hide_header Set-Cookie;
<% end -%>
…
}
<% end -%>
…
This way, the duplication will only exist in the generated config file.
Posted on 23 August 2011 by Levente @leente. blog comments powered by Disqus