Hello, I would like to see if it's possible to get limit_conn and limit_req working with the rewrite modules if statement. I have seen some discussion about this in the mailing list already saying to use stuff like throwing a 410 code and having that 410 code handled by a @named location that handles requests that should not be limited, such as ... location / { error_page 410 = @nolimit; if ($http_user_agent ~ Googlebot) { return 410; } limit_req zone=one burst=4; ... } location @nolimit { ... } I also know about how if statements are considered evil and should be avoided where possible, but I am working with dynamically generating config files which support multiple upstreams, with different upstream options per location directive with various features involved. I would like to be able to set a variable that I can than use in an if statement to determine if limit_con or limit_req should be used. For example... set $Whitelisted "No"; if ($http_user_agent ~ (googlebot|bingbot)) { set $Whitelisted "Yes"; } if ($Whitelisted ~* "No") { limit_conn conlimit-one 5; limit_req zone=limit-half burst=9; } Is there any possibility of this functionality being unlocked in the nginx code? I really need this functionality, and I hope it's not a big deal to do. Is there are particular reason why this module does not work with the rewrite if statement? Posted at Nginx Forum: http://forum.nginx.org/read.php?2,244781,244781#msg-244781
on 2013-11-18 20:49

on 2013-11-18 21:58

To elaborate a bit more, in a single location I may end up with something like this... set $Whitelisted "No"; if ($GeoList1 = allow) { set $Whitelisted "Yes"; } if ($GeoList5 = allow) { set $Whitelisted "Yes"; } if ($http_user_agent ~ (googlebot|bingbot)) { set $Whitelisted "Yes"; } if ($Whitelisted ~* "No") { limit_conn conlimit-one 5; limit_req zone=limit-half burst=9; } So that I can allow both IPs and user agents to avoid getting limited. Posted at Nginx Forum: http://forum.nginx.org/read.php?2,244781,244783#msg-244783
on 2013-11-18 22:06

On 18 November 2013 20:57, Nam <nginx-forum@nginx.us> wrote: > if ($http_user_agent ~ (googlebot|bingbot)) { > set $Whitelisted "Yes"; > } > if ($Whitelisted ~* "No") { > limit_conn conlimit-one 5; > limit_req zone=limit-half burst=9; > } Have you looked at using map{}s as the limit_* settings' arguments instead? They're much nicer than sequential if()s, which may not even achieve what you want to. J
on 2013-11-19 00:24

Can you give an example of how I would accomplish the desired if statement I posted? I do not see how i could get map to do that myself. Posted at Nginx Forum: http://forum.nginx.org/read.php?2,244781,244789#msg-244789
on 2013-11-19 01:35

On Mon, Nov 18, 2013 at 02:49:27PM -0500, Nam wrote: Hi there, > I would like to see if it's possible to get limit_conn and limit_req > working with the rewrite modules if statement. Not according to the current documentation. I suspect that patches will be welcome, if they fit the usual criteria. > I have seen some discussion > about this in the mailing list already saying to use stuff like throwing a > 410 code and having that 410 code handled by a @named location that handles > requests that should not be limited You don't seem to say why that setup doesn't work for your situation. > I also know about how if statements are considered evil Yes. > and should be avoided where possible No. "if" inside "location" can be a problem. Otherwise, it should be fine. > but I am working with dynamically generating config > files which support multiple upstreams, with different upstream options per > location directive with various features involved. You may want to rethink the design, based on the nginx features available. > I would like to be able > to set a variable that I can than use in an if statement to determine if > limit_con or limit_req should be used. As above, if you're doing that, you're not using current nginx. > For example... > > set $Whitelisted "No"; > if ($http_user_agent ~ (googlebot|bingbot)) { > set $Whitelisted "Yes"; > } > if ($Whitelisted ~* "No") { > limit_conn conlimit-one 5; > limit_req zone=limit-half burst=9; Somewhere, you have defined limit_conn_zone to match that. Can you redefine that to use a new variable that takes the value you want, if $Whitelisted is "No", and is empty if $Whitelisted is "Yes" -- in this case, if $http_user_agent matches those patterns? That should be doable without patching nginx. f -- Francis Daly francis@daoine.org
on 2013-11-19 03:45

Hello! On Tue, Nov 19, 2013 at 12:35:19AM +0000, Francis Daly wrote: > On Mon, Nov 18, 2013 at 02:49:27PM -0500, Nam wrote: > > Hi there, > > > I would like to see if it's possible to get limit_conn and limit_req > > working with the rewrite modules if statement. > > Not according to the current documentation. > > I suspect that patches will be welcome, if they fit the usual criteria. Not really. Pathes to enable directives in if-in-location context are not considered. Instead, directives should be able to work with variables. In case of limit_req / limit_conn, variables support is already here. Whitelisting can be easily done with something like this: map $whitelist $limit { default $binary_remote_addr; 1 ""; } limit_req_zone $limit zone=one:10m rate=1r/s; server { ... set $whitelist ""; if (...) { set $whitelist 1; } limit_req one; ... } [...] -- Maxim Dounin http://nginx.org/en/donation.html