Switching backends based on a cookie

Marcus Clyne ngx.eugaia at gmail.com
Fri Jan 29 13:54:56 MSK 2010


saltyflorida wrote:
> saltyflorida Wrote:
> -------------------------------------------------------
>   
>> Eugaia Wrote:
>> --------------------------------------------------
>> -----
>>     
>>> saltyflorida wrote:
>>>       
>>>> I forgot to mention that I am using caching
>>>>         
>> with
>>     
>>> the HTTP Proxy module and that I only want to
>>> cache responses from the production servers.
>>>       
>> When
>>     
>>> I have the cookie set to "testing" or
>>>       
>> "staging",
>>     
>>> I'd like to bypass the cache and talk directly
>>>       
>> to
>>     
>>> the backend. Does this sound feasible?
>>>       
>>>>   
>>>>         
>>> Sure.  Do a rewrite using your $backend
>>>       
>> variable
>>     
>>> under the 'location /' 
>>> block to one of three other blocks, which have
>>>       
>> the
>>     
>>> different definitions 
>>> of your proxy_pass, proxy_cache_valid...
>>>
>>> e.g.
>>>
>>> map $cookie_  $backend {
>>>
>>>     default   production;
>>>     test      test;
>>>     ...
>>> }
>>>
>>> location   / {
>>>     rewrite   ^(.*)$   /$backend/$1;
>>> }
>>>
>>> location   /production/ {
>>>     proxy_pass           
>>> http://backend_production;
>>>     proxy_cache_valid   ...
>>> }
>>>
>>> location   /test/ {
>>>     proxy_pass
>>>     # no proxy_cache_valid
>>>     ...
>>> }
>>>
>>> Note, you'll need some way to catch the case of
>>>       
>> no
>>     
>>> cookie variable, so 
>>> it's unwise to put $cookie_ directly in the
>>> rewrite result (you'll 
>>> get an infinite loop on such results).
>>>
>>> Marcus.
>>>
>>> _______________________________________________
>>> nginx mailing list
>>> nginx at nginx.org
>>> http://nginx.org/mailman/listinfo/nginx
>>>       
>> Marcus,
>> Thank you for your help. I had wondered if I could
>> use a rewrite, but I don't 
>> understand how this works. I tried to implement
>> your suggestion, but I am
>> being redirected to /testing/ or /production/.
>> These show up as part of the 
>> URL in the browser. Also, trying to visit pages
>> other than the root return a
>> 404 error. Here is my configuration. Can you point
>> out what I'm doing wrong?
>>
>> http {
>>     upstream backend_testing {
>>             ip_hash;
>>         server ...
>>     }
>>     upstream backend_staging {
>>             ip_hash;
>>         server ...
>>     }
>>     upstream backend_production {
>>             ip_hash;
>>         server ...
>>     }
>>     proxy_cache_path /mnt/nginx_cache levels=1:2
>>                      keys_zone=one:100m
>>                      inactive=7d max_size=10g;
>>     proxy_temp_path /var/www/nginx_temp;
>>
>>     map $cookie_uslnn_env $backend {
>>         default      http://backend_production;
>>         testing      http://backend_testing;
>>         staging      http://backend_staging;
>>         production   http://backend_production;
>>     }
>>
>>     server {
>>         location / {
>>             rewrite ^(.*)$ /$backend/$1;
>>         }
>>         location /testing/ {
>>             proxy_pass http://backend_testing;
>>         }
>>         location /staging/ {
>>             proxy_pass http://backend_staging;
>>         }
>>         location /production/ {
>>             proxy_pass http://backend_production;
>>             proxy_cache one;
>>             proxy_cache_key $my_cache_key;
>>             proxy_cache_valid  200 302 304 10m;
>>             proxy_cache_valid  301 1h;
>>             proxy_cache_valid  any 1m;
>>             proxy_cache_use_stale updating error
>> timeout invalid_header http_500 http_502 http_503
>> http_504;
>>         }
>>         location /wp-admin {
>>             proxy_pass http://backend_production;
>>             proxy_read_timeout 300;
>>         }
>>     }
>> }
>>
>> Thanks,
>> Eliot
>>     
>
> Correction:
> The configuration I tried looks like this:
>
> http {
>     upstream backend_testing {
>             ip_hash;
>         server ...
>     }
>     upstream backend_staging {
>             ip_hash;
>         server ...
>     }
>     upstream backend_production {
>             ip_hash;
>         server ...
>     }
>     proxy_cache_path /mnt/nginx_cache levels=1:2
>                      keys_zone=one:100m
>                      inactive=7d max_size=10g;
>     proxy_temp_path /var/www/nginx_temp;
>
>     map $cookie_uslnn_env $backend {
>         default production;
>         production production;
>         testing testing;
>         staging staging;
>     }
>
>     server {
>         location / {
>             rewrite ^(.*)$ /$backend/$1;
>         }
>         location /testing/ {
>             proxy_pass http://backend_testing;
>         }
>         location /staging/ {
>             proxy_pass http://backend_staging;
>         }
>         location /production/ {
>             proxy_pass http://backend_production;
>             proxy_cache one;
>             proxy_cache_key $my_cache_key;
>             proxy_cache_valid  200 302 304 10m;
>             proxy_cache_valid  301 1h;
>             proxy_cache_valid  any 1m;
>             proxy_cache_use_stale updating error timeout invalid_header http_500 http_502 http_503 http_504;
>         }
>         location /wp-admin {
>             proxy_pass http://backend_production;
>             proxy_read_timeout 300;
>         }
>     }
> }
>   
Sorry, my fault.  That should have read  'proxy_pass   
htttp://backend_production/;'.  The final slash 'deletes' the first part 
of the location that's passed.

Note that you will want to add the slash for the /production/, 
/testing/... blocks, but not for the /wp-admin block.

Marcus.




More information about the nginx mailing list