Reverse Proxy Cache Setup

I’m trying to use nginx as a reverse cahce for my website which may
require people to be logged in. I’m trying to figure out how to
configure it so that users that don’t have a certain cookie set receive
cached pages while others will receive non-cached responses, assuming
the cookie is “logmein”.

Posted at Nginx Forum:

Ryan M. Wrote:

you’re using for
all.


RPM


nginx mailing list
[email protected]
nginx Info Page

Thanks Ryan. I don’t have much control over the application itself, so I
guess I’d need to enforce the caching somehow for users that are logged
in and disable it for those that aren’t from nginx.

Posted at Nginx Forum:

On Mon, Mar 29, 2010 at 8:41 AM, royo [email protected] wrote:

I’m trying to use nginx as a reverse cahce for my website which may require people to be logged in. I’m trying to figure out how to configure it so that users that don’t have a certain cookie set receive cached pages while others will receive non-cached responses, assuming the cookie is “logmein”.

Use $http_cookie_$logmein appended to whatever you’re using for
proxy_cache_key, so that you get a unique cache key for each user.
This assumes that $logmein has a different value for every logged-in
user (i.e. it is a session ID).

You can also have the back-end explicitly set “Cache-Control:
no-cache” for logged in pages, so they don’t get stored by nginx at
all.


RPM

On Mon, Mar 29, 2010 at 11:44 AM, royo [email protected] wrote:

Thanks Ryan. I don’t have much control over the application itself, so I guess I’d need to enforce the caching somehow for users that are logged in and disable it for those that aren’t from nginx.

If you include a unique string in your nginx proxy_cache_key, then
logged-in user requests should never be in cache (again, assuming the
back-end sets cache-control headers).

So, assuming you have “proxy_cache_key
$http_host$request_uri$http_cookie_logmein” in your nginx config:

A request for http://mine.example.com/foo from an anonymous user would
get nginx cache key:
http://mine.example.com/foo ← logmein is empty
This result could be served from cache for future anonymous requests

A request for http://mine.example.com/foo from a a logged in user user
would get nginx cache key:
http://mine.example.com/fooAB324494354CD43254DC ← logmein
contains user’s session ID
In this case, there would not be a cache hit on the nginx side, and a
logged in user’s request is passed to the back-end and they get a
customized version of the page. No anonymous users would ever see that
because they don’t have that session ID. Presumably, the back-end must
set “Cache-Control: private” or “Cache-Control: no-cache” for
logged-in users. If it doesn’t, you’re really going to have problems.

I do not think that nginx proxy directives are allowed inside an “if”
block. You might be able to use “if $http_cookie_logmein” to redirect
internally to a named nginx location that does not have any caching.

Can you post your nginx configuration?


RPM

Ryan M. Wrote:

logged-in user requests should never be in cache
http://mine.example.com/foo ← logmein is
In this case, there would not be a cache hit on
going to have problems.


RPM


nginx mailing list
[email protected]
nginx Info Page

The app sets “Cache-Control: private” right now for everyone, and with
the following setup even users that are not logged in receive a fresh
copy of the page every time. The said cookie is set when logging in to
the domain xyz.com(not actual domain) as well as other cookies but when
using the nginx proxy only the other cookies are set and the logmein
cookie isn’t visible.

http {
include mime.types;
default_type application/octet-stream;

#log_format  main  '$remote_addr - $remote_user [$time_local] 

“$request” ’
# '$status $body_bytes_sent “$http_referer” ’
# ‘“$http_user_agent” “$http_x_forwarded_for”’;

#access_log  logs/access.log  main;

client_body_buffer_size 128K;
client_header_buffer_size 128K;
client_max_body_size 1M;
large_client_header_buffers 1 1k;

client_body_timeout 60;
client_header_timeout 60;
keepalive_timeout 60 60;
send_timeout 60;

ignore_invalid_headers on;
keepalive_requests 100;
limit_zone gulag $binary_remote_addr 5m;
recursive_error_pages on;

sendfile        on;

server_name_in_redirect off;
server_tokens off;
tcp_nodelay on;
tcp_nopush on;

gzip on;
gzip_buffers 16 8k;
gzip_comp_level 6;
gzip_http_version 1.0;
gzip_min_length 0;
gzip_types text/plain text/css image/x-icon application/x-perl
application/x-httpd-cgi;
gzip_vary on;

proxy_buffering on;
proxy_cache_path /optimum/nginx/cache levels=1:2
keys_zone=my-cache:8m max_size=1000m inactive=600m;
proxy_temp_path /optimum/nginx/cache/tmp;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_connect_timeout 30;
proxy_send_timeout 30;
proxy_read_timeout 30;
proxy_cache_valid any 10m;

server {
    listen       80;
    server_name  localhost;

    location / {

  proxy_pass http://xyz.com;
  proxy_cache my-cache;

proxy_pass_header Set-Cookie;

proxy_cache_key $host$request_uri$http_cookie_logmein;

  proxy_cache_valid  404      1m;

        index index.php index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

Posted at Nginx Forum:

On Mon, Mar 29, 2010 at 1:29 PM, royo [email protected] wrote:

The app sets “Cache-Control: private” right now for everyone,
and with the following setup even users that are not logged in
receive a fresh copy of the page every time. The said cookie
is set when logging in to the domain xyz.com(not actual
domain) as well as other cookies but when using the nginx
proxy only the other cookies are set and the logmein cookie
isn’t visible.

If nginx can see one cookie for /, it should see them all unless it is
scoped improperly. Have you used fiddler or Firebug to be sure that
the cookie isn’t ebing set and passed?

Secondly, if the back-end is setting Cache-Control: private, then
nginx will obey and not cache anything. Changing the back-end to set
“Cache-Control: public,max-age=3600” or whatever is the easiest route.

If you can’t do that, you can do something like this with “if” and
rewrite, to a location that does not use the cache at all for logged
in user requests. $http_cookie_logmein should be accessible for such
requests, you can echo it back for debuggin using:

add_header “X-Logmein-Received” $http_cookie_logmein

Once again, debugging with Fiddler or Firebug will let you see these
headers and work out the kinks.