[PATCH] Conditional application of limit_conn directive

turchanov at farpost.com turchanov at farpost.com
Tue Sep 22 06:53:25 UTC 2020


Patch with tests will follow

# HG changeset patch
# User Sergei Turchanov <turchanov at farpost.com>
# Date 1600756248 -36000
#      Tue Sep 22 16:30:48 2020 +1000
# Node ID 2cf4e00bb96b17142a82e5f1868197465cf5c194
# Parent  052ecc68d35038b1b4adde12efe6249a92055f09
Conditional application of limit_conn directive

Implemented conditional application of limit_conn directive.
Since limit_conn directive cannot be used inside 'if' block, an optional
parameter 'if=condition' was introduced to control whether the limit is
applied or not. The limit will not be applied if the condition evaluates
to "0" or an empty string.

diff -r 052ecc68d350 -r 2cf4e00bb96b 
src/http/modules/ngx_http_limit_conn_module.c
--- a/src/http/modules/ngx_http_limit_conn_module.c	Wed Sep 16 18:26:25 
2020 +0300
+++ b/src/http/modules/ngx_http_limit_conn_module.c	Tue Sep 22 16:30:48 
2020 +1000
@@ -45,6 +45,7 @@
  typedef struct {
      ngx_shm_zone_t               *shm_zone;
      ngx_uint_t                    conn;
+    ngx_http_complex_value_t     *filter;
  } ngx_http_limit_conn_limit_t;


@@ -98,7 +99,7 @@
        NULL },

      { ngx_string("limit_conn"),
-      
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+      
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
        ngx_http_limit_conn,
        NGX_HTTP_LOC_CONF_OFFSET,
        0,
@@ -181,7 +182,7 @@
  {
      size_t                          n;
      uint32_t                        hash;
-    ngx_str_t                       key;
+    ngx_str_t                       key, val;
      ngx_uint_t                      i;
      ngx_rbtree_node_t              *node;
      ngx_pool_cleanup_t             *cln;
@@ -199,6 +200,16 @@
      limits = lccf->limits.elts;

      for (i = 0; i < lccf->limits.nelts; i++) {
+        if (limits[i].filter) {
+            if (ngx_http_complex_value(r, limits[i].filter, &val) != 
NGX_OK) {
+                return NGX_ERROR;
+            }
+
+            if (val.len == 0 || (val.len == 1 && val.data[0] == '0')) {
+                continue;
+            }
+        }
+
          ctx = limits[i].shm_zone->data;

          if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) {
@@ -662,11 +673,12 @@
  static char *
  ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  {
-    ngx_shm_zone_t               *shm_zone;
-    ngx_http_limit_conn_conf_t   *lccf = conf;
-    ngx_http_limit_conn_limit_t  *limit, *limits;
+    ngx_shm_zone_t                     *shm_zone;
+    ngx_http_limit_conn_conf_t         *lccf = conf;
+    ngx_http_limit_conn_limit_t        *limit, *limits;
+    ngx_http_compile_complex_value_t    ccv;

-    ngx_str_t  *value;
+    ngx_str_t  *value, s;
      ngx_int_t   n;
      ngx_uint_t  i;

@@ -712,10 +724,38 @@
      if (limit == NULL) {
          return NGX_CONF_ERROR;
      }
+    ngx_memzero(limit, sizeof(ngx_http_limit_conn_limit_t));

      limit->conn = n;
      limit->shm_zone = shm_zone;

+    if (cf->args->nelts == 4) {
+        if (ngx_strncmp(value[3].data, "if=", 3) == 0) {
+            s.len = value[3].len - 3;
+            s.data = value[3].data + 3;
+
+            ngx_memzero(&ccv, 
sizeof(ngx_http_compile_complex_value_t));
+
+            ccv.cf = cf;
+            ccv.value = &s;
+            ccv.complex_value = ngx_palloc(cf->pool,
+                                           
sizeof(ngx_http_complex_value_t));
+            if (ccv.complex_value == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+                return NGX_CONF_ERROR;
+            }
+
+            limit->filter = ccv.complex_value;
+        } else {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid parameter \"%V\"", &value[3]);
+            return NGX_CONF_ERROR;
+        }
+    }
+
      return NGX_CONF_OK;
  }



More information about the nginx-devel mailing list