I have been trying to do rate limiting in some api endpoints that I am hitting asynchronously, requests return 200 ok as expected before rate limiting, but when the limit is reached instead of returning a 429 error my api endpoints come back with CORS Error in the browser, I read here that it might be due to some headers, but I tried that and still I get the same cors error.
Sharing my humble nginx config below, in this example I would like to get a 429 when rate limit is reached for endpoint api.domain.com/custom/url
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/m;
server {
listen 80;
server_name domain.com api.domain.com;
location .../my-acme-challenge/ {
root .../my-certbot;
}
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl;
server_name api.domain.com;
.../mychain.pem;
.../myprivkey.pem;
include .../my-options-ssl-nginx.conf;
ssl_dhparam .../my-ssl-dhparams.pem;
Relevant Piece !!!!!!
location /custom/url {
add_header Access-Control-Allow-Credentials 'true' always;
add_header Access-Control-Allow-Origin '*' always;
limit_req zone=mylimit burst=5 nodelay;
limit_req_log_level error;
limit_req_status 429;
proxy_pass http://myip:myport/custom/url;
}
location / {
proxy_pass http://myip:myport;
}
}
...
}
Any idea of what might be going on? Tried to simplify my config here as much as I could.
My nginx logs:
[error] 9#9: *51 limiting requests, excess: 5.697 by zone "mylimit", client: myip, server: api.example.com, request: "OPTIONS /custom/url HTTP/1.1", host: "api.example.com", referrer: "https://example.com/"
myip - - [23/Nov/2021:01:10:32 +0000] "OPTIONS /custom/url HTTP/1.1" 429 571 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
Update:
Curiously enough, when I copy the curl request from the network (right click > Copy > Copy as curl) I get this html page which appears to be an 429, but instead I should be getting this error in the browser when I hit with an async request not in curl.
2
Answers
Answering in case someone else goes through the same situation, the problem was actually a composition of multiple things:
server {}
level (notice thealways
keyword, this is pivotal for adding the headers to error responses) i.e:Adding your headers outside of the
location
block should ensure they are included in the rate limiting response too.