1

I am using FRiCKLE's ngx_cache_purge module to invalidate proxy caches. I ran into a problem of not being able to purge caches when accessing the invalidation url with a different HOST part of url than the one used to access the original content. For example, if I access the content like this:

curl -H 'Content-Type: application/json' -d '{ "token": "pts7v4nqf7stfq35qeb570v5n2" }' -X POST -D - http://api.example.com/news/article/cache-testing

The cache file is created with a propper key and it works, the subsequent requests are served right. When the content changes, in order to purge the cached data, the backend does the equivalent on all webservers:

curl -D - http://10.200.100.101:8080/invalidate_cached_url/POST/news/article/cache-testing

And this returns 404 since the cache file is somehow being generated with host part of the url in mind, and in order to purge it, I have to call the invalidation url with the same host in line. This is a problem since I have a loadbalancer infront of the webstack.

To prove this, I saved the cache file generated with the above method and cleared the cache, then I visited the api endpoint directly with the IP address:

curl -H 'Content-Type: application/json' -d '{ "token": "pts7v4nqf7stfq35qeb570v5n2" }' -X POST -D - http://10.200.100.101:8080/news/article/cache-testing

Now when I try to purge the cache like above, it works. And true enough the cache files are different but on a binary level, but the keys are the same.

Is there a way around this?

Here's my config:

proxy_cache_path /tmp/nginx/example-api levels=1:2 keys_zone=example_api_zone:300m inactive=1h;

upstream origin_api {
    server localhost:8888;
}

server {
    listen 8080 default_server;
    server_name  api.example.com;

    proxy_buffering on;
    proxy_buffer_size 1k;
    proxy_buffers 24 4k;
    proxy_busy_buffers_size 8k;
    proxy_max_temp_file_size 2048m;
    proxy_temp_file_write_size 32k;

    proxy_cache_key $request_method$uri;

    access_log /var/log/nginx/example-api.access.log;
    error_log /var/log/nginx/example-api.error.log;

    error_page 500 502 /502.html;
    location = /502.html {
      internal;
      root /opt/errors;
    }

    location / {
      gzip on;
      include example_proxy_params.conf;
      proxy_cache_bypass $http_cache_control;
      proxy_cache_methods POST GET;
      proxy_pass http://origin_api;
    }

    location ~ ^/news/singlearticle/ {
      gzip on;
      proxy_hide_header Cache-Control;
      add_header Cache-Control 'max-age=10s, no-cache ,public';
      include example_proxy_params.conf;
      proxy_cache_bypass $http_cache_control;
      proxy_cache_methods POST GET;
      proxy_pass http://origin_api;
    }

    location ~ ^/news/subcategory/ {
      proxy_cache_key "$request_method$request_uri|$request_body";
      include example_proxy_params.conf;
      proxy_cache_bypass $http_cache_control;
      proxy_cache_methods POST GET;
      proxy_pass http://origin_api;
    }

    location ~ /invalidate_cached_url/(.*) {
      allow 127.0.0.1;
      allow 10.200.100.101;
      allow 10.200.100.102;
      deny all;
      proxy_cache_purge example_api_zone $1;
    }

}

2 Answers 2

0

Set the hostname in your curl command, e.g.:

curl -H "Host: api.example.com" -D - http://192.168.255.230:8080/invalidate_cached_url/....
2
  • Wow, funny thing is this is the first thing I tried but it didn't work for some reason. The configuration has changed a lot since then. Thanks!
    – Athropos
    Feb 2, 2016 at 18:46
  • Sorry, I realised this wasn't the solution. It turns out to be the Origin header.
    – Athropos
    Feb 3, 2016 at 7:47
0

It turns out the solution is to add a Origin header, as nginx actually uses it to create the hash file, and also it does make sense if you think about it. This succeeds from any allowed IP:

curl -H 'Origin: http://testing.bktvnews.com' -D - http://10.200.100.101:8080/invalidate_cached_url/POST/news/article/cache-testing

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .