5

I’m on Nginx 0.8.54 trying to achieve the following as DRYly as possible:

  • Proxy straight to localhost:8060 if cookie no_cache is true or if request method isn’t GET.
  • Otherwise serve static files from $document_root/static/$uri.
  • If no such file exists, try $document_root/cache/$uri and $document_root/cache/$uri.html.
  • If the request path is /, try no static files and only $document_root/cache/index.html.
  • Finally fall back to localhost:8060 if neither static nor cached files are found.

Current configuration file:

server {
    root /srv/web/example.com;
    server_name example.com;

    location @backend { proxy_pass http://localhost:8060; }

    location / {
        if ($cookie_no_cache = true) { proxy_pass http://localhost:8060; }
        if ($request_method != GET) { proxy_pass http://localhost:8060; }
        try_files /static/$uri /cache/$uri /cache/$uri.html @backend;
    }

    location = / {
        if ($cookie_no_cache = true) { proxy_pass http://localhost:8060; }
        if ($request_method != GET) { proxy_pass http://localhost:8060; }
        try_files /cache/index.html @backend;
    }
}
freyaariel
  • 153
  • 4

1 Answers1

4
http {
  map $cookie_no_cache $cacheZone {
    default "";
    true    X;
  }

  server {
    root /srv/web/example.com;
    server_name example.com;

    error_page 405 = @backend;

    location / {
      try_files /cache$cacheZone/$uri.html /static$cacheZone/$uri
                /cache$cacheZone/$uri @backend;
    }

    location @backend {
      proxy_pass http://localhost:8060;
    }
  }
}

Explanation.

  1. Regarding "no_cache" cookie check. We are replacing it with Nginx map. Variable $cacheZone depends on the value of $cookie_no_cache. By default it's empty, but if there is a "no_cache=true" cookie, we set $cacheZone to any value to modify static file search path in try_files -- I hope you have no /cacheX and /staticX folders under your server root (if yes, choose another value for $cacheZone)
  2. Nginx cannot apply HTTP methods PUT or POST to static files (this is meaningless), so that it issues HTTP error 405 "Not Allowed" in this case. We intercept it by error_page and pass the request to @backend location.

Alternative approach

Otherwise, use proxy_cache:

http {
  proxy_cache_path example:1m;

  server {
    root  /srv/web/example.com;
    server_name example.com;

    location / {
      proxy_cache example;
      proxy_cache_bypass $cookie_no_cache;
      proxy_cache_valid 200 10s;
      proxy_pass http://localhost:8060;
    }
  }
}
Alexander Azarov
  • 3,510
  • 20
  • 19