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:
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”.
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.
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.
(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”)
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.
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.
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).
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
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.
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.
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.
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.