# Limit\_req\_zone: How to apply only to some requests containing some string in the URL?

**URL:** <https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072>\
**Category:** NGINX\
**Created:** [October 23, 2013, 5:43am UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072 "2013-10-23T05:43:11Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![alcina](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a587f6/32.png) [@alcina](https://www.ruby-forum.com/u/alcina)\
**Post date:** [October 23, 2013, 5:43am UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/1 "2013-10-23T05:43:11Z")

</div>

Hi,

I’m using the limit\_req\_zone module. I would like it to act only on some  
requests that have a certain string in one variable in the query string  
of  
the URL.For example, lets say that I’m providing a IP geolocation  
service,  
and that in the URL there is a query string like this:

[http://api.acme.com/ipgeolocation/locate?key=NANDSBFHGWHWN2X&ip=146.105.11.59](http://api.acme.com/ipgeolocation/locate?key=NANDSBFHGWHWN2X&ip=146.105.11.59)

I would like the rule to detect when the “key” parameter ends with “2X”,  
and  
in such case to apply the limitation.  
What I really need is to give NGINX a secret message. The “key”  
parameter  
would end in “01X”, “02X”, “03X” (etc). This would indicate Nginx the  
limitation of queries per minute, and Nginx would apply a different rate  
for  
each request, depending on the “message”.

Is there a way to do that?

Thanks in advance!

Posted at Nginx Forum:

> **[limit\_req\_zone: How to apply only to some requests containing some string in...](https://forum.nginx.org/read.php?2,244015,244015#msg-244015)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 23, 2013, 10:09am UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/2 "2013-10-23T10:09:42Z")

</div>

On Tue, Oct 22, 2013 at 11:42:35PM -0400, Brian08275660 wrote:

Hi there,

> I’m using the limit\_req\_zone module. I would like it to act only on some  
> requests that have a certain string in one variable in the query string of  
> the URL.

> [http://api.acme.com/ipgeolocation/locate?key=NANDSBFHGWHWN2X&ip=146.105.11.59](http://api.acme.com/ipgeolocation/locate?key=NANDSBFHGWHWN2X&ip=146.105.11.59)
> 
> I would like the rule to detect when the “key” parameter ends with “2X”, and  
> in such case to apply the limitation.

> **[Module ngx\_http\_limit\_req\_module](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone)**
>
> The ngx\_http\_limit\_req\_module module (0.7.21) is used to limit the request processing rate per a defined key, in particular, the processing rate of requests coming from a single IP address. The limitation is done using the “leaky bucket” method.

See $variable.

Use, for example, “map” to make your variable have a value when you want  
the limit to apply, and be empty when you don’t.

> What I really need is to give NGINX a secret message. The “key” parameter  
> would end in “01X”, “02X”, “03X” (etc). This would indicate Nginx the  
> limitation of queries per minute, and Nginx would apply a different rate for  
> each request, depending on the “message”.

For that, I think you’d need a different limit\_req zone for each rate.

After you’ve got the first part working, it shouldn’t be too hard to  
set up a test system to see if you can get this part to work too.

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 23, 2013, 6:42pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/3 "2013-10-23T18:42:58Z")

</div>

On Wed, Oct 23, 2013 at 08:56:33AM -0400, Brian08275660 wrote:

Hi there,

> Could you please give me an example? A few lines of code would be great!

Completely untested, but something like:

map $arg\_key $key\_ends\_in\_02X {  
default “”;  
~02X$ “A”;  
}

(where “A” might be, for example, $binary\_remote\_addr, if you want to  
limit the requests per client IP, rather than enforce the limit across  
all clients where “key” ends “02X”)

and then

limit\_req\_zone $key\_ends\_in\_02X zone=two:10m rate=2r/s;

and

limit\_req zone=two;

should probably do what you asked for.

If anything is unclear or broken, and the documentation doesn’t make  
it clear how it should be, then feel free to respond pointing out which  
specific parts need fixing.

Cheers,

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 23, 2013, 2:57pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/4 "2013-10-23T14:57:17Z")

</div>

Could you please give me an example? A few lines of code would be great!

Posted at Nginx Forum:

> **[Re: limit\_req\_zone: How to apply only to some requests containing some string...](https://forum.nginx.org/read.php?2,244015,244035#msg-244035)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 23, 2013, 7:39pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/5 "2013-10-23T19:39:07Z")

</div>

Thanks a lot Francis! Now I just have to learn how to use the custom  
variables and the “map” directive. I haven’t ever used them before,  
never  
needed them.  
By the way, it will be easier than what I thought. I decided to ask my  
users  
to add an extra parameter, something like “&capacity=3X” instead of  
“hiding”  
some characters in the key that would indicate what to do. So at least I  
wont have to make a lot of effort with the regular expressions, the  
parameter will be very clear. My logic will chech its value and apply  
the  
respective limit.

Its interesting how weird is the configuration of Nginx. No XML tags,  
but  
weird directives that are not really straightforward.

Posted at Nginx Forum:

> **[Re: limit\_req\_zone: How to apply only to some requests containing some string...](https://forum.nginx.org/read.php?2,244015,244049#msg-244049)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 25, 2013, 7:32pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/6 "2013-10-25T19:32:08Z")

</div>

Hi Francis,

Now I need to create a limit that acts if the parameter (“capacity”) is  
empty (not provided). How do I do that? I can’t find how to, at least  
not  
using “map”.  
(If provided, the other rules will evaluate it and one of them will act  
according to the value).

Thanks in advanced!

Posted at Nginx Forum:

> **[Re: limit\_req\_zone: How to apply only to some requests containing some string...](https://forum.nginx.org/read.php?2,244015,244123#msg-244123)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 25, 2013, 7:59pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/7 "2013-10-25T19:59:00Z")

</div>

Hi,

you could use a map that matches all cases to empty string and default  
value as non-empty

map $arg\_capacity $my\_default\_key{~\*([2-9]|10)X “”; default  
$http\_x\_forwarded\_for;}

If it matches 2X to 10X, $my\_default\_key will be empty.

Cheers  
Jader H. Silva

2013/10/25 Brian08275660 [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 25, 2013, 11:02pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/8 "2013-10-25T23:02:31Z")

</div>

Maybe ive misunderstood but cant you very simply do this by injecting a  
cookie on the origina req page and then have nginx match, count it and  
apply rates? Or maybe im comicating it… If even possible

–  
Payam C.  
Network Engineer / Security Specialist

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 24, 2013, 3:18pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/9 "2013-10-24T15:18:26Z")

</div>

Hi Francis,

Thanks a lot! You saved me probably a couple of days of research. It is  
working now!

I did this:

The user will send my a “capacity” parameter, with a value of 2X or 3X  
or 4X  
or…(etc)

map $arg\_capacity $2X\_key{~\*2X $http\_x\_forwarded\_for;default “”;}  
map $arg\_capacity $3X\_key{~\*3X $http\_x\_forwarded\_for;default “”;}  
map $arg\_capacity $4X\_key{~\*4X $http\_x\_forwarded\_for;default “”;}  
map $arg\_capacity $5X\_key{~\*5X $http\_x\_forwarded\_for;default “”;}  
map $arg\_capacity $6X\_key{~\*6X $http\_x\_forwarded\_for;default “”;}  
map $arg\_capacity $7X\_key{~\*7X $http\_x\_forwarded\_for;default “”;}  
map $arg\_capacity $8X\_key{~\*8X $http\_x\_forwarded\_for;default “”;}  
map $arg\_capacity $9X\_key{~\*9X $http\_x\_forwarded\_for;default “”;}  
map $arg\_capacity $10X\_key{~\*10X $http\_x\_forwarded\_for;default “”;}

limit\_req\_zone $2X\_key zone=2X:1m rate=600r/m;  
limit\_req\_zone $3X\_key zone=3X:1m rate=900r/m;  
limit\_req\_zone $4X\_key zone=4X:1m rate=1200r/m;  
limit\_req\_zone $5X\_key zone=5X:1m rate=1500r/m;  
limit\_req\_zone $6X\_key zone=6X:1m rate=1800r/m;  
limit\_req\_zone $7X\_key zone=7X:1m rate=2100r/m;  
limit\_req\_zone $8X\_key zone=8X:1m rate=2400r/m;  
limit\_req\_zone $9X\_key zone=9X:1m rate=2700r/m;  
limit\_req\_zone $10X\_key zone=10X:1m rate=3000r/m;

limit\_req zone=2X burst=600;  
limit\_req zone=3X burst=900;  
limit\_req zone=4X burst=1200;  
limit\_req zone=5X burst=1500;  
limit\_req zone=6X burst=1800;  
limit\_req zone=7X burst=2100;  
limit\_req zone=8X burst=2400;  
limit\_req zone=9X burst=2700;  
limit\_req zone=10X burst=3000;

Posted at Nginx Forum:

> **[Re: limit\_req\_zone: How to apply only to some requests containing some string...](https://forum.nginx.org/read.php?2,244015,244064#msg-244064)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 25, 2013, 11:18pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/10 "2013-10-25T23:18:18Z")

</div>

Hi Payam,

I dont have that option. My users are not using real browsers, but  
objects  
that model an HTTP client. Probably these object can’t inject cookies.  
And I  
don’t want to ask them to so so, it would make things more complex to  
them,  
whereas including an extra parameter in the query string is a piece of  
cake.

Thanks anyway for the idea!

Posted at Nginx Forum:

> **[Re: limit\_req\_zone: How to apply only to some requests containing some string...](https://forum.nginx.org/read.php?2,244015,244130#msg-244130)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 25, 2013, 11:14pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/11 "2013-10-25T23:14:47Z")

</div>

Hi Jader,

Thanks a lot, that looks like a nice solution!

I barely know how to build regex expressions, and I’m too lazy to learn  
just  
right now. Just a final question: Actually they will send me any value  
from  
2X to 25X, but that could even increase to more than 25. I would like a  
simpler and more open REGEX, something like:

If it is something that includes an “X”

I will use it as this:

map $arg\_capacity $my\_default\_key{ If it is something that includes an  
“X”  
“”; default $http\_x\_forwarded\_for;}

Simple as that. This would catch any case, from 2X to 1000000000X.  
Actually  
it would catch even illegal values. But that is not a problem for me,  
cause  
in my java code that follows Nginx I’m validating the value they send me  
anyway, so I don’t mind if they send me a value like “-1X” because my  
app  
would return an error status code and force them to send me a valid  
value  
anyway. The important thing is that Nginx should apply the limit if the  
received value is not empty, and asking if it contains an “X” covers  
that  
boolean question.

Posted at Nginx Forum:

> **[Re: limit\_req\_zone: How to apply only to some requests containing some string...](https://forum.nginx.org/read.php?2,244015,244129#msg-244129)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 26, 2013, 1:08am UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/12 "2013-10-26T01:08:08Z")

</div>

I read some information about REGEX and think I found the way to express  
“X  
or x, preceded with something before”:

~_(._)X

I think that the first two characters mean “match anycase”, then the  
“(.\*)”  
would mean “any quantity of characters” and the “X” would mean that  
specific  
letter.

Am I right?

Posted at Nginx Forum:

> **[Re: limit\_req\_zone: How to apply only to some requests containing some string...](https://forum.nginx.org/read.php?2,244015,244136#msg-244136)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 26, 2013, 3:38pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/13 "2013-10-26T15:38:37Z")

</div>

Oh, ok. Then it is similar to REGEX in Java.  
Well, then I think I have a nice and elegant solution, Thanks!

Posted at Nginx Forum:

> **[Re: limit\_req\_zone: How to apply only to some requests containing some string...](https://forum.nginx.org/read.php?2,244015,244149#msg-244149)**
>
> Hi, I'm using the limit\_req\_zone module. I would like it to act only on some requests that have a certain string in one variable in the query string of the URL.For example, lets say that I'm providing a IP geolocation service, and that in the URL...

---

<div class="post-metadata">

**Author:** ![Brian08275660](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/838e76/32.png) [@Brian08275660](https://www.ruby-forum.com/u/Brian08275660)\
**Post date:** [October 26, 2013, 2:53pm UTC](https://www.ruby-forum.com/t/limit-req-zone-how-to-apply-only-to-some-requests-containing-some-string-in-the-url/237072/14 "2013-10-26T14:53:45Z")

</div>

On Fri, Oct 25, 2013 at 07:07:20PM -0400, Brian08275660 wrote:

Hi there,

> ~_(._)X
> 
> I think that the first two characters mean “match anycase”, then the “(.\*)”  
> would mean “any quantity of characters” and the “X” would mean that specific  
> letter.
> 
> Am I right?

Yes.

But unless you’re going to do something with the bit before the X,  
then in the context of a map{}, it is equivalent to ~\*X, since all you  
care about is whether it matches.

It will just as easily match x123 or 123x123.

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
