<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div class="elementToProof"><span style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof ContentPasted0 ContentPasted1">Hello,</span></div>
<div class="elementToProof"><font color="#000000" face="Calibri, Arial, Helvetica, sans-serif"><br>
</font></div>
<div class="elementToProof"><span style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);" class="elementToProof ContentPasted0 ContentPasted1 ContentPasted2 ContentPasted3">
<div class="ContentPasted1">Please find below a patch to enable dynamic rate limiting for limit_req module.</div>
<div class="ContentPasted1"><br>
</div>
<div class="ContentPasted1">
<pre class="ContentPasted4">/* ----------------------------EXAMPLE---------------------------------*/</pre>
</div>
<div class="ContentPasted1"> geo $traffic_tier {</div>
<div class="ContentPasted1">        default        free;</div>
<div class="ContentPasted1">        127.0.1.0/24   basic;</div>
<div class="ContentPasted1">        127.0.2.0/24   premium;</div>
<div class="ContentPasted1">    }</div>
<div><br class="ContentPasted1">
</div>
<div class="ContentPasted1">    map $traffic_tier $rate {</div>
<div class="ContentPasted1">        free           1r/m;</div>
<div class="ContentPasted1">        basic          2r/m;</div>
<div class="ContentPasted1">        premium        1r/s;</div>
<div class="ContentPasted1">    }</div>
<div><br class="ContentPasted1">
</div>
<div class="ContentPasted1">    limit_req_zone $binary_remote_addr zone=one:10m rate=$rate;</div>
<div><br class="ContentPasted1">
</div>
<div class="ContentPasted1">    server {</div>
<div class="ContentPasted1">        limit_req zone=one;</div>
<div class="ContentPasted1">        listen       80;</div>
<div class="ContentPasted1">        server_name  localhost;</div>
<div class="ContentPasted1">        return 200;</div>
<div class="ContentPasted1">    }</div>
<div><br class="ContentPasted1">
</div>
<div class="ContentPasted1">curl --interface 127.0.X.X localhost</div>
<div><br class="ContentPasted1">
</div>
<div class="ContentPasted1">
<pre class="ContentPasted4 ContentPasted5" style="background-color:rgb(255, 255, 255)">/* ----------------------------NGINX-TESTS---------------------------------*/</pre>
</div>
<div><br class="ContentPasted1">
</div>
<div class="ContentPasted1">debian@debian:~/projects/nginx-merc/nginx-tests$ prove limit_req*</div>
<div class="ContentPasted1">limit_req2.t ......... ok</div>
<div class="ContentPasted1">limit_req_delay.t .... ok</div>
<div class="ContentPasted1">limit_req_dry_run.t .. ok</div>
<div class="ContentPasted1">limit_req.t .......... ok</div>
<div class="ContentPasted1">All tests successful.</div>
<div class="ContentPasted1">Files=4, Tests=40,  4 wallclock secs ( 0.04 usr  0.00 sys +  0.28 cusr  0.11 csys =  0.43 CPU)</div>
<div class="ContentPasted1">Result: PASS</div>
<div><br class="ContentPasted1">
</div>
<div class="ContentPasted1">
<pre class="ContentPasted4 ContentPasted5 ContentPasted8" style="background-color:rgb(255, 255, 255)">/* ----------------------------CHANGES OF BEHAVIOUR---------------------------------*/</pre>
</div>
<div class="ContentPasted1">It is backwards compatible with the syntax of existing configurations, either a rate=$variable can be used or the existing syntax of rate=xy/s.</div>
<div><br class="ContentPasted1">
</div>
<div class="ContentPasted1"> - 'rate=' can be assigned empty value, which results in an unlimited(maximum) rate limits value.</div>
<div class="ContentPasted1">- 'rate=' set to an invalid value also results in an unlimited(maximum) rate limit value.</div>
<div class="ContentPasted1">- The value of rate is now limited to prevent integer overflow in certain operations.</div>
<div class="ContentPasted1">- The maximum time between consecutive requests that is determined is now limited to 60s (60000ms) to prevent integer overflow/underflow.</div>
<div class="ContentPasted1">
<pre class="ContentPasted4 ContentPasted5 ContentPasted6" style="background-color:rgb(255, 255, 255)">/* ----------------------------USE-CASES---------------------------------*/</pre>
</div>
<div class="ContentPasted1">Allow rate limits for a given user to be determined by mapping trusted request values to a rate, such as:</div>
<div class="ContentPasted1">- Source IP CIDR.</div>
<div class="ContentPasted1">- Client Certificate identifiers.</div>
<div class="ContentPasted1">- JWT claims. </div>
<div><br>
</div>
<div class="ContentPasted1">This could also be performed dynamically at runtime with key_val zone to alter rate limits on the fly without a reload.</div>
<pre class="ContentPasted4 ContentPasted5 ContentPasted7" style="background-color:rgb(255, 255, 255)">/* ----------------------------PATCHBOMB---------------------------------*/</pre>
# HG changeset patch
<div class="ContentPasted3"># User jordanc.carter@outlook.com</div>
<div class="ContentPasted3"># Date 1672437935 0</div>
<div class="ContentPasted3">#      Fri Dec 30 22:05:35 2022 +0000</div>
<div class="ContentPasted3"># Branch dynamic-rate-limiting</div>
<div class="ContentPasted3"># Node ID b2bd50efa81e5aeeb9b8f84ee0af34463add07fa</div>
<div class="ContentPasted3"># Parent  07b0bee87f32be91a33210bc06973e07c4c1dac9</div>
<div class="ContentPasted3">Changed 'rate=' to complex value and added limits to the rate value to prevent integer overflow/underflow</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">diff -r 07b0bee87f32 -r b2bd50efa81e src/http/modules/ngx_http_limit_req_module.c</div>
<div class="ContentPasted3">--- a/src/http/modules/ngx_http_limit_req_module.c      Wed Dec 21 14:53:27 2022 +0300</div>
<div class="ContentPasted3">+++ b/src/http/modules/ngx_http_limit_req_module.c      Fri Dec 30 22:05:35 2022 +0000</div>
<div class="ContentPasted3">@@ -26,6 +26,7 @@</div>
<div class="ContentPasted3">     /* integer value, 1 corresponds to 0.001 r/s */</div>
<div class="ContentPasted3">     ngx_uint_t                   excess;</div>
<div class="ContentPasted3">     ngx_uint_t                   count;</div>
<div class="ContentPasted3">+    ngx_uint_t                   rate;</div>
<div class="ContentPasted3">     u_char                       data[1];</div>
<div class="ContentPasted3"> } ngx_http_limit_req_node_t;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">@@ -41,7 +42,7 @@</div>
<div class="ContentPasted3">     ngx_http_limit_req_shctx_t  *sh;</div>
<div class="ContentPasted3">     ngx_slab_pool_t             *shpool;</div>
<div class="ContentPasted3">     /* integer value, 1 corresponds to 0.001 r/s */</div>
<div class="ContentPasted3">-    ngx_uint_t                   rate;</div>
<div class="ContentPasted3">+    ngx_http_complex_value_t     rate;</div>
<div class="ContentPasted3">     ngx_http_complex_value_t     key;</div>
<div class="ContentPasted3">     ngx_http_limit_req_node_t   *node;</div>
<div class="ContentPasted3"> } ngx_http_limit_req_ctx_t;</div>
<div class="ContentPasted3">@@ -66,9 +67,9 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3"> static void ngx_http_limit_req_delay(ngx_http_request_t *r);</div>
<div class="ContentPasted3"> static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit,</div>
<div class="ContentPasted3">-    ngx_uint_t hash, ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account);</div>
<div class="ContentPasted3">+    ngx_uint_t hash, ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account, ngx_uint_t rate);</div>
<div class="ContentPasted3"> static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits,</div>
<div class="ContentPasted3">-    ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit);</div>
<div class="ContentPasted3">+    ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit, ngx_uint_t rate);</div>
<div class="ContentPasted3"> static void ngx_http_limit_req_unlock(ngx_http_limit_req_limit_t *limits,</div>
<div class="ContentPasted3">     ngx_uint_t n);</div>
<div class="ContentPasted3"> static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,</div>
<div class="ContentPasted3">@@ -195,10 +196,13 @@</div>
<div class="ContentPasted3"> ngx_http_limit_req_handler(ngx_http_request_t *r)</div>
<div class="ContentPasted3"> {</div>
<div class="ContentPasted3">     uint32_t                     hash;</div>
<div class="ContentPasted3">-    ngx_str_t                    key;</div>
<div class="ContentPasted3">+    ngx_str_t                    key, rate_s;</div>
<div class="ContentPasted3">     ngx_int_t                    rc;</div>
<div class="ContentPasted3">     ngx_uint_t                   n, excess;</div>
<div class="ContentPasted3">+    ngx_uint_t                   scale;</div>
<div class="ContentPasted3">+    ngx_uint_t                   rate;</div>
<div class="ContentPasted3">     ngx_msec_t                   delay;</div>
<div class="ContentPasted3">+    u_char                      *p;</div>
<div class="ContentPasted3">     ngx_http_limit_req_ctx_t    *ctx;</div>
<div class="ContentPasted3">     ngx_http_limit_req_conf_t   *lrcf;</div>
<div class="ContentPasted3">     ngx_http_limit_req_limit_t  *limit, *limits;</div>
<div class="ContentPasted3">@@ -243,10 +247,34 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">         hash = ngx_crc32_short(key.data, key.len);</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">+        if (ngx_http_complex_value(r, &ctx->rate, &rate_s) != NGX_OK) {</div>
<div class="ContentPasted3">+            ngx_http_limit_req_unlock(limits, n);</div>
<div class="ContentPasted3">+            return NGX_HTTP_INTERNAL_SERVER_ERROR;</div>
<div class="ContentPasted3">+        }</div>
<div class="ContentPasted3">+</div>
<div class="ContentPasted3">+        scale = 1;</div>
<div class="ContentPasted3">+        rate = NGX_ERROR;</div>
<div class="ContentPasted3">+</div>
<div class="ContentPasted3">+        if (rate_s.len > 8) {</div>
<div class="ContentPasted3">+</div>
<div class="ContentPasted3">+            rate = (ngx_uint_t) ngx_atoi(rate_s.data + 5, rate_s.len - 8);</div>
<div class="ContentPasted3">+</div>
<div class="ContentPasted3">+            p = rate_s.data + rate_s.len - 3;</div>
<div class="ContentPasted3">+            if (ngx_strncmp(p, "r/m", 3) == 0) {</div>
<div class="ContentPasted3">+                scale = 60;</div>
<div class="ContentPasted3">+            } else if (ngx_strncmp(p, "r/s", 3) != 0){</div>
<div class="ContentPasted3">+                rate = NGX_ERROR;</div>
<div class="ContentPasted3">+            }</div>
<div class="ContentPasted3">+        }</div>
<div class="ContentPasted3">+</div>
<div class="ContentPasted3">+        rate = (rate != 0 && rate < NGX_MAX_INT_T_VALUE / 60000000 - 1001) ?</div>
<div class="ContentPasted3">+                rate * 1000 / scale :</div>
<div class="ContentPasted3">+                NGX_MAX_INT_T_VALUE / 60000000 - 1001;</div>
<div class="ContentPasted3">+</div>
<div class="ContentPasted3">         ngx_shmtx_lock(&ctx->shpool->mutex);</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">         rc = ngx_http_limit_req_lookup(limit, hash, &key, &excess,</div>
<div class="ContentPasted3">-                                       (n == lrcf->limits.nelts - 1));</div>
<div class="ContentPasted3">+                                       (n == lrcf->limits.nelts - 1), rate);</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">         ngx_shmtx_unlock(&ctx->shpool->mutex);</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">@@ -291,7 +319,7 @@</div>
<div class="ContentPasted3">         excess = 0;</div>
<div class="ContentPasted3">     }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-    delay = ngx_http_limit_req_account(limits, n, &excess, &limit);</div>
<div class="ContentPasted3">+    delay = ngx_http_limit_req_account(limits, n, &excess, &limit, rate);</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     if (!delay) {</div>
<div class="ContentPasted3">         r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_PASSED;</div>
<div class="ContentPasted3">@@ -403,7 +431,7 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3"> static ngx_int_t</div>
<div class="ContentPasted3"> ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,</div>
<div class="ContentPasted3">-    ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account)</div>
<div class="ContentPasted3">+    ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account, ngx_uint_t rate)</div>
<div class="ContentPasted3"> {</div>
<div class="ContentPasted3">     size_t                      size;</div>
<div class="ContentPasted3">     ngx_int_t                   rc, excess;</div>
<div class="ContentPasted3">@@ -412,7 +440,6 @@</div>
<div class="ContentPasted3">     ngx_rbtree_node_t          *node, *sentinel;</div>
<div class="ContentPasted3">     ngx_http_limit_req_ctx_t   *ctx;</div>
<div class="ContentPasted3">     ngx_http_limit_req_node_t  *lr;</div>
<div class="ContentPasted3">-</div>
<div class="ContentPasted3">     now = ngx_current_msec;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     ctx = limit->shm_zone->data;</div>
<div class="ContentPasted3">@@ -446,12 +473,14 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">             if (ms < -60000) {</div>
<div class="ContentPasted3">                 ms = 1;</div>
<div class="ContentPasted3">-</div>
<div class="ContentPasted3">             } else if (ms < 0) {</div>
<div class="ContentPasted3">                 ms = 0;</div>
<div class="ContentPasted3">+            } else if (ms > 60000) {</div>
<div class="ContentPasted3">+                ms = 60000;</div>
<div class="ContentPasted3">             }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-            excess = lr->excess - ctx->rate * ms / 1000 + 1000;</div>
<div class="ContentPasted3">+            lr->rate = rate;</div>
<div class="ContentPasted3">+            excess = lr->excess - lr->rate * ms / 1000 + 1000;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">             if (excess < 0) {</div>
<div class="ContentPasted3">                 excess = 0;</div>
<div class="ContentPasted3">@@ -510,6 +539,7 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     lr->len = (u_short) key->len;</div>
<div class="ContentPasted3">     lr->excess = 0;</div>
<div class="ContentPasted3">+    lr->rate = rate;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     ngx_memcpy(lr->data, key->data, key->len);</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">@@ -534,7 +564,7 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3"> static ngx_msec_t</div>
<div class="ContentPasted3"> ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n,</div>
<div class="ContentPasted3">-    ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit)</div>
<div class="ContentPasted3">+    ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit, ngx_uint_t rate)</div>
<div class="ContentPasted3"> {</div>
<div class="ContentPasted3">     ngx_int_t                   excess;</div>
<div class="ContentPasted3">     ngx_msec_t                  now, delay, max_delay;</div>
<div class="ContentPasted3">@@ -543,13 +573,13 @@</div>
<div class="ContentPasted3">     ngx_http_limit_req_node_t  *lr;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     excess = *ep;</div>
<div class="ContentPasted3">+    max_delay = 0;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     if ((ngx_uint_t) excess <= (*limit)->delay) {</div>
<div class="ContentPasted3">         max_delay = 0;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     } else {</div>
<div class="ContentPasted3">-        ctx = (*limit)->shm_zone->data;</div>
<div class="ContentPasted3">-        max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate;</div>
<div class="ContentPasted3">+        max_delay = (excess - (*limit)->delay) * 1000 / rate;</div>
<div class="ContentPasted3">     }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     while (n--) {</div>
<div class="ContentPasted3">@@ -570,9 +600,11 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">         } else if (ms < 0) {</div>
<div class="ContentPasted3">             ms = 0;</div>
<div class="ContentPasted3">+        } else if (ms > 60000) {</div>
<div class="ContentPasted3">+            ms = 60000;</div>
<div class="ContentPasted3">         }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-        excess = lr->excess - ctx->rate * ms / 1000 + 1000;</div>
<div class="ContentPasted3">+        excess = lr->excess - lr->rate * ms / 1000 + 1000;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">         if (excess < 0) {</div>
<div class="ContentPasted3">             excess = 0;</div>
<div class="ContentPasted3">@@ -593,7 +625,7 @@</div>
<div class="ContentPasted3">             continue;</div>
<div class="ContentPasted3">         }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-        delay = (excess - limits[n].delay) * 1000 / ctx->rate;</div>
<div class="ContentPasted3">+        delay = (excess - limits[n].delay) * 1000 / lr->rate;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">         if (delay > max_delay) {</div>
<div class="ContentPasted3">             max_delay = delay;</div>
<div class="ContentPasted3">@@ -674,9 +706,11 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">             if (ms < 60000) {</div>
<div class="ContentPasted3">                 return;</div>
<div class="ContentPasted3">+            } else {</div>
<div class="ContentPasted3">+                ms = 60000;</div>
<div class="ContentPasted3">             }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-            excess = lr->excess - ctx->rate * ms / 1000;</div>
<div class="ContentPasted3">+            excess = lr->excess - lr->rate * ms / 1000;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">             if (excess > 0) {</div>
<div class="ContentPasted3">                 return;</div>
<div class="ContentPasted3">@@ -833,14 +867,12 @@</div>
<div class="ContentPasted3"> ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)</div>
<div class="ContentPasted3"> {</div>
<div class="ContentPasted3">     u_char                            *p;</div>
<div class="ContentPasted3">-    size_t                             len;</div>
<div class="ContentPasted3">     ssize_t                            size;</div>
<div class="ContentPasted3">     ngx_str_t                         *value, name, s;</div>
<div class="ContentPasted3">-    ngx_int_t                          rate, scale;</div>
<div class="ContentPasted3">     ngx_uint_t                         i;</div>
<div class="ContentPasted3">     ngx_shm_zone_t                    *shm_zone;</div>
<div class="ContentPasted3">     ngx_http_limit_req_ctx_t          *ctx;</div>
<div class="ContentPasted3">-    ngx_http_compile_complex_value_t   ccv;</div>
<div class="ContentPasted3">+    ngx_http_compile_complex_value_t   key, rate;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     value = cf->args->elts;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">@@ -849,19 +881,17 @@</div>
<div class="ContentPasted3">         return NGX_CONF_ERROR;</div>
<div class="ContentPasted3">     }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));</div>
<div class="ContentPasted3">+    ngx_memzero(&key, sizeof(ngx_http_compile_complex_value_t));</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-    ccv.cf = cf;</div>
<div class="ContentPasted3">-    ccv.value = &value[1];</div>
<div class="ContentPasted3">-    ccv.complex_value = &ctx->key;</div>
<div class="ContentPasted3">+    key.cf = cf;</div>
<div class="ContentPasted3">+    key.value = &value[1];</div>
<div class="ContentPasted3">+    key.complex_value = &ctx->key;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {</div>
<div class="ContentPasted3">+    if (ngx_http_compile_complex_value(&key) != NGX_OK) {</div>
<div class="ContentPasted3">         return NGX_CONF_ERROR;</div>
<div class="ContentPasted3">     }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     size = 0;</div>
<div class="ContentPasted3">-    rate = 1;</div>
<div class="ContentPasted3">-    scale = 1;</div>
<div class="ContentPasted3">     name.len = 0;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">     for (i = 2; i < cf->args->nelts; i++) {</div>
<div class="ContentPasted3">@@ -902,25 +932,14 @@</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">         if (ngx_strncmp(value[i].data, "rate=", 5) == 0) {</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-            len = value[i].len;</div>
<div class="ContentPasted3">-            p = value[i].data + len - 3;</div>
<div class="ContentPasted3">-</div>
<div class="ContentPasted3">-            if (ngx_strncmp(p, "r/s", 3) == 0) {</div>
<div class="ContentPasted3">-                scale = 1;</div>
<div class="ContentPasted3">-                len -= 3;</div>
<div class="ContentPasted3">+            ngx_memzero(&rate, sizeof(ngx_http_compile_complex_value_t));</div>
<div class="ContentPasted3">+            rate.cf = cf;</div>
<div class="ContentPasted3">+            rate.value = &value[i];</div>
<div class="ContentPasted3">+            rate.complex_value = &ctx->rate;</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-            } else if (ngx_strncmp(p, "r/m", 3) == 0) {</div>
<div class="ContentPasted3">-                scale = 60;</div>
<div class="ContentPasted3">-                len -= 3;</div>
<div class="ContentPasted3">-            }</div>
<div class="ContentPasted3">-</div>
<div class="ContentPasted3">-            rate = ngx_atoi(value[i].data + 5, len - 5);</div>
<div class="ContentPasted3">-            if (rate <= 0) {</div>
<div class="ContentPasted3">-                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,</div>
<div class="ContentPasted3">-                                   "invalid rate \"%V\"", &value[i]);</div>
<div class="ContentPasted3">+            if (ngx_http_compile_complex_value(&rate) != NGX_OK) {</div>
<div class="ContentPasted3">                 return NGX_CONF_ERROR;</div>
<div class="ContentPasted3">             }</div>
<div class="ContentPasted3">-</div>
<div class="ContentPasted3">             continue;</div>
<div class="ContentPasted3">         }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">@@ -936,8 +955,6 @@</div>
<div class="ContentPasted3">         return NGX_CONF_ERROR;</div>
<div class="ContentPasted3">     }</div>
<div><br class="ContentPasted3">
</div>
<div class="ContentPasted3">-    ctx->rate = rate * 1000 / scale;</div>
<div class="ContentPasted3">-</div>
<div class="ContentPasted3">     shm_zone = ngx_shared_memory_add(cf, &name, size,</div>
<div class="ContentPasted3">                                      &ngx_http_limit_req_module);</div>
<div class="ContentPasted3">     if (shm_zone == NULL) {</div>
<div><br>
</div>
</span></div>
</body>
</html>