Hello! On Thu, Jun 02, 2022 at 05:44:26PM -0400, acidiclight wrote:
> I'm trying to customize my response to rate-limited requests by keeping > limit_req_dry_run on, and using an if statement depending on the value of > $limit_req_status: > > This works as expected: > > limit_req_zone $binary_remote_addr zone=one:1m rate=2r/m; > > server { > > listen 80; > server_name localhost; > > location / { > # set rate limiting for this location > limit_req zone=one burst=10 nodelay; > limit_req_dry_run on; > > add_header X-my-var "$myvar" always; > > if ($limit_req_status = "REJECTED_DRY_RUN") { > add_header X-custom-header "rejected" always; > return 400 'rejected'; > } > > root /usr/share/nginx/html; > index index.html; > } > > } > > But once I replace root and index with a proxy_pass, the whole thing stops > working: > > limit_req_zone $binary_remote_addr zone=one:1m rate=2r/m; > > server { > resolver 8.8.8.8; > listen 80; > server_name localhost; > > location / { > set $myupstream "myurl.com"; > > # set rate limiting for this location > limit_req zone=one burst=10 nodelay; > limit_req_dry_run on; > > add_header X-limit-req-status "$limit_req_status" always; > > if ($limit_req_status = "REJECTED_DRY_RUN") { > add_header X-custom-header "rejected" always; > return 400 'rejected'; > } > > proxy_pass http://$myupstream; > } > > } > > I added $limit_req_status to my log_format and can confirm that the value of > $limit_req_status does get set to "REJECTED_DRY_RUN". I also see the header > "X-limit-req-status" from the request set to "REJECTED_DRY_RUN". > > I'm assuming the issue is the way Nginx evaluates if statements that have > unset variables at the beginning of the request? If so, any pointers on how > to get this working? Thank you! The rewrite module directives, notably "if", "set", and "return" in your configuration, are evaluated while looking for a configuration to process a request[1]. In contrast, limit_req limits are evaluated before processing a request in a given configuration. As such, both the above configurations are not expected to work. First one likely appear to work for you because you are testing it with requests such as "/", involving an internal redirect to the index file[2], so "if" acts on the limit_req results before the internal redirect. Testing with direct link to a file will reveal the it doesn't work too. Proper solution to get things working would be to actually switch off limit_req_dry_run. If you need to redefine response code and/or add custom headers, consider using limit_req_status and/or error_page instead. For example: location / { limit_req zone=one burst=10 nodelay; error_page 503 = /rejected; proxy_pass http://...; } location = /rejected { add_header X-custom-header "rejected" always; return 400 rejected; } Hope this helps. [1] http://nginx.org/en/docs/http/ngx_http_rewrite_module.html [2] http://nginx.org/en/docs/http/request_processing.html#simple_php_site_configuration -- Maxim Dounin http://mdounin.ru/ _______________________________________________ nginx mailing list -- nginx@nginx.org To unsubscribe send an email to nginx-le...@nginx.org