0

i have nginx file part like this

http {
   limit_req_zone $binary_remote_addr zone=limit:1m rate=10r/s;

   server {
     listen 443 ssl;
     server_name domain.temp;
     root "/var/www";
     index index.php;
     location ~* ^/([0-9]+)$ {
        rewrite ^/([0-9]+)$ /blank.php?id=$1 last;
        limit_req zone=limit burst=3;
      }
      location /apply/ {
            limit_req zone=limit burst=6;
      }
    }
  }
}

the /apply/ does work as it should and is limited by 6 bursts and the rest slow

but ^/([0-9]+)$ does not work and does not have any effect

but if i move limit_req zone=limit burst=3; into server{} block it works on everything inside the block from locations but i want it to work on ^/([0-9]+)$ block only

1 Answers1

0

This is likely related to rewrite ^/([0-9]+)$ /blank.php?id=$1 last; directive. nginx documentation states:

last stops processing the current set of ngx_http_rewrite_module directives and starts a search for a new location matching the changed URI;

It can be that the rewrite is processed before limit_req in nginx, therefore nginx starts to process /blank.php and since there is no location block matching this request, no limit is assigned.

If this is the reason for limit not working, then getting around it is somewhat complex. location blocks only match the URL path without the query arguments. So, you would need to have:

location /blank.php {
    limit_reqzone=limit burst=3;
    # PHP processing directives from "location ~ \.php$" block
}

However, this would match all requests to blank.php. If you want to restrict matching to requests with only id query argument, you need a more complex setup:

http {
    # If there is "id" argument in query arguments and it is a number, use "limit" zone. By default, use "nolimit" zone.
    map $arg_id $limit_zone {
        ~ ^[0-9]+$ limit;
        default nolimit;
    }

    limit_req_zone $binary_remote_addr zone=limit:1m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=nolimit:1m rate=1000r/s;

    server {
        location /blank.php {
            limit_req zone=$limit_zone burst=6;
            # PHP processing directives from "location ~ \.php$" block
        }
        location /apply {
            limit_req zone=limit burst=6;
    }
}

I don't see a direct way to map request from rate limited / not rate limited directly.

Therefore we need to use map to select a limit zone, and the "nolimit" zone just has such high limits that it is essentially a zone without limites.

Tero Kilkanen
  • 36,796
  • 3
  • 41
  • 63