I want to impose a request limit for uncached content on my NGINX reverse proxy. I have multiple locations defined and content can get cached or won't get cached due to other rules. So I can not set a request limit just for a location, I have to handle this differently.
According to the documentation in https://www.nginx.com/blog/rate-limiting-nginx/#Advanced-Configuration-Examples, I can use the map feature in order to impose a request limit. So I tried this and created following configuration snippet:
map $upstream_cache_status $limit {
default 1;
MISS 1;
HIT 0;
}
map $limit $limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
So in order to test my map first, I have added following to my location:
add_header X-Test $limit;
And I see that it works! Every resource that is cached ($upstream_cache_status = HIT), $limit seems to be 0. Every uncached content ($upstream_cache_status = MISS), $limit is 1.
Now comes the weird behaviour. As soon as I add limit_req zone=req_zone burst=10 nodelay;
into my location, $limit seems to be stuck at 1, no matter if the $upstream_cache_status is HIT or MISS.
The location looks like this:
location ~* \.(jpg|jpeg|png|gif|webp|svg|svgz|ico|pdf|doc|docx|xls|xlsx|csv|zip|gz|woff|woff2|ttf|otf|eot)$ {
limit_req zone=req_zone burst=10 nodelay;
[...]
add_header X-Test $limit;
[...]
}
Is this a NGINX bug or am I missing something here? NGINX version is 1.20.1 on AlmaLinux 8.5.
Rate limiting works first, on request phase. Caching works later, on content phase (guess).
So, when limiter works, there is no information about cache status yet.