Conditional cache

I’ve been trying to set up two separate proxy caches, one for logged in
users, one for guests. The one for guests had a very long expiry as
guest pages don’t change much, User pages are very dynamic and expiry is
very short.

Using cookies i can tell if a page request is by a user or guest, but I
cannot see any easy way to alter the proxy as all the proxy_cache
commands can’t be put inside an if.

I’ve managed the following workaround, which works fine but it seems
strange i have to use this method when there must be an easier and more
straightforward way that i am just not seeing

set $memcached_key “pages:$uri:$cache_key”; ### dummy key, will never
exist as i’m not using memcache for nginx
if ($cache_key = “guest”){error_page 404 = @guests;} #set 404 for quest
if ($cache_key != “guest”){error_page 404 = @users;} #set 404 for users
memcached_pass 127.0.01:11220; ## this server is empty, has no keys will
ALWAYS return 404

location @users {
proxy_cache users;
proxy_cache_key “$request_uri$cache_key”;
proxy_cache_valid 502 504 1m;
proxy_cache_valid any 5m;
proxy_pass http://127.0.0.1:10098;
}

location @guests {
proxy_cache guests;
proxy_cache_key “$request_uri$cache_key”;
proxy_cache_valid 502 504 1m;
proxy_cache_valid any 60m;
proxy_pass http://127.0.0.1:10098;
}

Posted at Nginx Forum:

Hello!

On Wed, Sep 01, 2010 at 03:00:30PM -0400, paul2791 wrote:

strange i have to use this method when there must be an easier and more
straightforward way that i am just not seeing

set $memcached_key “pages:$uri:$cache_key”; ### dummy key, will never
exist as i’m not using memcache for nginx
if ($cache_key = “guest”){error_page 404 = @guests;} #set 404 for quest
if ($cache_key != “guest”){error_page 404 = @users;} #set 404 for users
memcached_pass 127.0.01:11220; ## this server is empty, has no keys will
ALWAYS return 404

It’s good idea to avoid using anything in “if” except “return” and
“rewrite … last”. See If is Evil… when used in location context | NGINX.

Also it’s probably better use 418 status code here ;). I would
recommend something like this:

location / {
error_page 418 = @guests;

   if (...detect guests...) {
       return 418;
   }

   proxy_cache users;
   ...

}

location @guests {
proxy_cache guests;

}

proxy_cache_key “$request_uri$cache_key”;
proxy_cache_valid 502 504 1m;
proxy_cache_valid any 60m;
proxy_pass http://127.0.0.1:10098;
}

Alternatively you may want to just set correct Cache-Control /
Expires / X-Accel-Expires headers in backend’s response and avoid
explicitly setting validity via proxy_cache_valid.

Maxim D.

Maxim,
Thats brilliant, thanks
Would proxy_pass be considered as a rewrite and safe within an IF as i
use it a lot to bypass cache?

Also, 418 is great code, had never seen that before. I do have some
logic elsewhere in my conf where i have more than two ifs. Does Nginx
allow the use of nondefined codes? 419 for instance? so i could have

location / {
error_page 418 = @cache1;
error_page 419 = @cache2;

if (…needtoshowcache1…) {
return 418;
}
if (…needtoshowcache2…) {
return 419;
}

proxy_cache cache3;

}

location @cache1 {
proxy_cache cache1;

}
location @cache2 {
proxy_cache cache2;

}

Ive got as far as testing the error_page 419 =@cache2 ; line and nginx
didn’t choke on that, but haven’t tested the actual return yet

And yes, all of this would be easier of the developers set expires in
backend, but until they do, im using nginx to make sure our site flies
as fast as it can no matter how slow their code is

Posted at Nginx Forum:

Hello!

On Thu, Sep 02, 2010 at 11:15:14AM -0400, paul2791 wrote:

I just tried a quick test, using your first method for users/guests ,
with 419 instead of 418. Seems to work fine. Any reason I couldn’t or
shouldn’t use these codes to redirect to different interal @locations???

418 is one from RFC 2324, “Hyper Text Coffee Pot Control
Protocol”. It means “I’m a teapot”. Good code to say request
should be processed elsewhere. :wink:

You are free to use any 4xx/5xx code otherwise unused in a
particular location (and it’s good idea to avoid overloading codes
which may happen to be returned due to other reasons).

Maxim D.

I just tried a quick test, using your first method for users/guests ,
with 419 instead of 418. Seems to work fine. Any reason I couldn’t or
shouldn’t use these codes to redirect to different interal @locations???

Posted at Nginx Forum:

On Thu, Sep 2, 2010 at 5:52 PM, Maxim D. [email protected] wrote:

418 is one from RFC 2324, “Hyper Text Coffee Pot Control
Protocol”. Â It means “I’m a teapot”. Â Good code to say request
should be processed elsewhere. :wink:

Isn’t that non-canonical? it’s for coffee machines, not for normal
servers or proxies.
(Only joking, I guess the Internet won’t stop working because of this
non standard usage)
:wink: