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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.