<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>