Leaving cookie path empty in module configuration causes nginx+browser confusion

Issue #7 resolved
Julio Morimoto created an issue

We had a small discussion about this problem in the old repo, at googlecode.com

https://code.google.com/p/nginx-sticky-module/issues/detail?id=29

It's been marked as "won't fix", so we decided to move the discussion here so it can have a proper feedback.

Details about the problem can be found in the old repo ticket. If necessary, we can reproduce it here. Basically, it boils down to the following situation:

Given that nginx routes between two different backend application servers, each application will manage its own session data and will be accessible through its own context path.

## root app manages its own session at location /
upstream rootapp_cluster {
  sticky name=route;
  server 127.0.0.1:9000;
  server 127.0.0.2:9001;
}

## app1 manages its own session at location /app1
upstream app1_cluster {
  sticky name=route;
  server 127.0.0.3:9000;
  server 127.0.0.4:9001;
}

## app2 manages its own session at location /app2
upstream app2_cluster {
  sticky name=route;
  server 127.0.0.5:9000;
  server 127.0.0.6:9001;
}

Using this configuration will cause nginx to set route cookies without a path. During our tests, we found the client browser will assume the cookie path to be whatever the URL was in the address bar. This could be / or /app1 or /app2 etc. Depending on the initial request, the following requests will set different cookies. At some point, there will be more than one cookie named "route" sent by the browser and nginx will pick any of them at random. That causes the sticky feature to misbehave.

The only way around this, we found, is to explicitely set the path in the configuration for each upstream.

## root app manages its own session at location /
upstream rootapp_cluster {
  sticky name=route path=/;
  server 127.0.0.1:9000;
  server 127.0.0.2:9001;
}

## app1 manages its own session at location /app1
upstream app1_cluster {
  sticky name=route path=/app1;
  server 127.0.0.3:9000;
  server 127.0.0.4:9001;
}

## app2 manages its own session at location /app2
upstream app2_cluster {
  sticky name=route path=/app2;
  server 127.0.0.5:9000;
  server 127.0.0.6:9001;
}

In this case, each upstream will manage its own "route" cookie, keeping users for that location in the same backend server.

Given the way the module works today, not setting the cookie path can lead to unpredictable results. The solution is open to discussion. My suggestion is to always set the cookie path, giving it a default of / if none is specified.

Comments (7)

  1. Yarkov

    I've added the change in bugfix/cookiepath. I'm not 100% sure that will resolve all issues though (an edge case would be two upstreams on different paths having the same upstream server, but that should never happen anyway).

    Please confirm the change works in the way you expect it to, otherwise just post again.

  2. gattu sevalkar

    Is there a way to keep the server same with different path.. or cluster. Basically for http and https, both requests should go to same server.

    upstream webcluster { sticky; server web1:8080; server web2:8080; }

    upstream sslwebcluster { sticky; server web1:8443; server web2:8443; }

    location /a/ {
    proxy_pass http://webcluster; }

    location /a/ { proxy_pass https://sslwebcluster; }

  3. S. Goodman repo owner

    cookie-path defaults now to /

    i'll make an addition to the docs on that issue, and if no one jumps in, close this ticket within the nexte days

  4. Log in to comment