Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_limit_req_module.c @ 4009:3183165283cc
Fixing proxy_set_body and proxy_pass_request_body with SSL.
Flush flag wasn't set in constructed buffer and this prevented any data
from being actually sent to upstream due to SSL buffering. Make sure
we always set flush in the last buffer we are going to sent.
See here for report:
http://nginx.org/pipermail/nginx-ru/2011-June/041552.html
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 18 Aug 2011 16:34:24 +0000 |
parents | d94d7104f598 |
children | 7697412a0921 97995d63aa36 |
rev | line source |
---|---|
980 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
12 typedef struct { | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
13 u_char color; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
14 u_char dummy; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
15 u_short len; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
16 ngx_queue_t queue; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
17 ngx_msec_t last; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
18 /* integer value, 1 corresponds to 0.001 r/s */ |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
19 ngx_uint_t excess; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
20 u_char data[1]; |
2294 | 21 } ngx_http_limit_req_node_t; |
980 | 22 |
23 | |
24 typedef struct { | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
25 ngx_rbtree_t rbtree; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
26 ngx_rbtree_node_t sentinel; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
27 ngx_queue_t queue; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
28 } ngx_http_limit_req_shctx_t; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
29 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
30 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
31 typedef struct { |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
32 ngx_http_limit_req_shctx_t *sh; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
33 ngx_slab_pool_t *shpool; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
34 /* integer value, 1 corresponds to 0.001 r/s */ |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
35 ngx_uint_t rate; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
36 ngx_int_t index; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
37 ngx_str_t var; |
2294 | 38 } ngx_http_limit_req_ctx_t; |
987 | 39 |
40 | |
41 typedef struct { | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
42 ngx_shm_zone_t *shm_zone; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
43 /* integer value, 1 corresponds to 0.001 r/s */ |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
44 ngx_uint_t burst; |
3185 | 45 ngx_uint_t limit_log_level; |
46 ngx_uint_t delay_log_level; | |
47 | |
48 ngx_uint_t nodelay; /* unsigned nodelay:1 */ | |
2294 | 49 } ngx_http_limit_req_conf_t; |
980 | 50 |
51 | |
2294 | 52 static void ngx_http_limit_req_delay(ngx_http_request_t *r); |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
53 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, |
3779
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
54 ngx_uint_t hash, u_char *data, size_t len, ngx_uint_t *ep); |
2294 | 55 static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, |
56 ngx_uint_t n); | |
980 | 57 |
2294 | 58 static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf); |
59 static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, | |
980 | 60 void *child); |
2294 | 61 static char *ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, |
980 | 62 void *conf); |
2294 | 63 static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, |
980 | 64 void *conf); |
2294 | 65 static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf); |
980 | 66 |
67 | |
3185 | 68 static ngx_conf_enum_t ngx_http_limit_req_log_levels[] = { |
69 { ngx_string("info"), NGX_LOG_INFO }, | |
70 { ngx_string("notice"), NGX_LOG_NOTICE }, | |
71 { ngx_string("warn"), NGX_LOG_WARN }, | |
72 { ngx_string("error"), NGX_LOG_ERR }, | |
73 { ngx_null_string, 0 } | |
74 }; | |
75 | |
76 | |
2294 | 77 static ngx_command_t ngx_http_limit_req_commands[] = { |
980 | 78 |
2294 | 79 { ngx_string("limit_req_zone"), |
987 | 80 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3, |
2294 | 81 ngx_http_limit_req_zone, |
980 | 82 0, |
83 0, | |
84 NULL }, | |
85 | |
2294 | 86 { ngx_string("limit_req"), |
87 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, | |
88 ngx_http_limit_req, | |
980 | 89 NGX_HTTP_LOC_CONF_OFFSET, |
90 0, | |
91 NULL }, | |
92 | |
3185 | 93 { ngx_string("limit_req_log_level"), |
94 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
95 ngx_conf_set_enum_slot, | |
96 NGX_HTTP_LOC_CONF_OFFSET, | |
97 offsetof(ngx_http_limit_req_conf_t, limit_log_level), | |
98 &ngx_http_limit_req_log_levels }, | |
99 | |
980 | 100 ngx_null_command |
101 }; | |
102 | |
103 | |
2294 | 104 static ngx_http_module_t ngx_http_limit_req_module_ctx = { |
980 | 105 NULL, /* preconfiguration */ |
2294 | 106 ngx_http_limit_req_init, /* postconfiguration */ |
980 | 107 |
108 NULL, /* create main configuration */ | |
109 NULL, /* init main configuration */ | |
110 | |
111 NULL, /* create server configuration */ | |
112 NULL, /* merge server configuration */ | |
113 | |
2294 | 114 ngx_http_limit_req_create_conf, /* create location configration */ |
115 ngx_http_limit_req_merge_conf /* merge location configration */ | |
980 | 116 }; |
117 | |
118 | |
2294 | 119 ngx_module_t ngx_http_limit_req_module = { |
980 | 120 NGX_MODULE_V1, |
2294 | 121 &ngx_http_limit_req_module_ctx, /* module context */ |
122 ngx_http_limit_req_commands, /* module directives */ | |
980 | 123 NGX_HTTP_MODULE, /* module type */ |
124 NULL, /* init master */ | |
125 NULL, /* init module */ | |
126 NULL, /* init process */ | |
127 NULL, /* init thread */ | |
128 NULL, /* exit thread */ | |
129 NULL, /* exit process */ | |
130 NULL, /* exit master */ | |
131 NGX_MODULE_V1_PADDING | |
132 }; | |
133 | |
134 | |
135 static ngx_int_t | |
2294 | 136 ngx_http_limit_req_handler(ngx_http_request_t *r) |
980 | 137 { |
2294 | 138 size_t len, n; |
139 uint32_t hash; | |
140 ngx_int_t rc; | |
2313 | 141 ngx_uint_t excess; |
2294 | 142 ngx_time_t *tp; |
143 ngx_rbtree_node_t *node; | |
144 ngx_http_variable_value_t *vv; | |
145 ngx_http_limit_req_ctx_t *ctx; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
146 ngx_http_limit_req_node_t *lr; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
147 ngx_http_limit_req_conf_t *lrcf; |
980 | 148 |
2294 | 149 if (r->main->limit_req_set) { |
984
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
150 return NGX_DECLINED; |
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
151 } |
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
152 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
153 lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module); |
980 | 154 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
155 if (lrcf->shm_zone == NULL) { |
980 | 156 return NGX_DECLINED; |
157 } | |
158 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
159 ctx = lrcf->shm_zone->data; |
987 | 160 |
161 vv = ngx_http_get_indexed_variable(r, ctx->index); | |
980 | 162 |
163 if (vv == NULL || vv->not_found) { | |
164 return NGX_DECLINED; | |
165 } | |
166 | |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
167 len = vv->len; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
168 |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
169 if (len == 0) { |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
170 return NGX_DECLINED; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
171 } |
984
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
172 |
2294 | 173 if (len > 65535) { |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
174 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
175 "the value of the \"%V\" variable " |
2294 | 176 "is more than 65535 bytes: \"%v\"", |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
177 &ctx->var, vv); |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
178 return NGX_DECLINED; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
179 } |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
180 |
2294 | 181 r->main->limit_req_set = 1; |
980 | 182 |
183 hash = ngx_crc32_short(vv->data, len); | |
184 | |
2294 | 185 ngx_shmtx_lock(&ctx->shpool->mutex); |
186 | |
187 ngx_http_limit_req_expire(ctx, 1); | |
188 | |
3779
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
189 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess); |
980 | 190 |
2313 | 191 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
2973 | 192 "limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000); |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
193 |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
194 if (rc == NGX_DECLINED) { |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
195 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
196 n = offsetof(ngx_rbtree_node_t, color) |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
197 + offsetof(ngx_http_limit_req_node_t, data) |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
198 + len; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
199 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
200 node = ngx_slab_alloc_locked(ctx->shpool, n); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
201 if (node == NULL) { |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
202 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
203 ngx_http_limit_req_expire(ctx, 0); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
204 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
205 node = ngx_slab_alloc_locked(ctx->shpool, n); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
206 if (node == NULL) { |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
207 ngx_shmtx_unlock(&ctx->shpool->mutex); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
208 return NGX_HTTP_SERVICE_UNAVAILABLE; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
209 } |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
210 } |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
211 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
212 lr = (ngx_http_limit_req_node_t *) &node->color; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
213 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
214 node->key = hash; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
215 lr->len = (u_char) len; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
216 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
217 tp = ngx_timeofday(); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
218 lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
219 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
220 lr->excess = 0; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
221 ngx_memcpy(lr->data, vv->data, len); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
222 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
223 ngx_rbtree_insert(&ctx->sh->rbtree, node); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
224 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
225 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
226 |
2294 | 227 ngx_shmtx_unlock(&ctx->shpool->mutex); |
1012
11ffb8e4753f
stop rbtree search early if equal hash was found
Igor Sysoev <igor@sysoev.ru>
parents:
1011
diff
changeset
|
228 |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
229 return NGX_DECLINED; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
230 } |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
231 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
232 ngx_shmtx_unlock(&ctx->shpool->mutex); |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
233 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
234 if (rc == NGX_OK) { |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
235 return NGX_DECLINED; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
236 } |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
237 |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
238 if (rc == NGX_BUSY) { |
3185 | 239 ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, |
2376
29d89920a749
*) add zone name while logging 503 error reason
Igor Sysoev <igor@sysoev.ru>
parents:
2375
diff
changeset
|
240 "limiting requests, excess: %ui.%03ui by zone \"%V\"", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
241 excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); |
980 | 242 |
243 return NGX_HTTP_SERVICE_UNAVAILABLE; | |
244 } | |
245 | |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
246 /* rc == NGX_AGAIN */ |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
247 |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
248 if (lrcf->nodelay) { |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
249 return NGX_DECLINED; |
2294 | 250 } |
251 | |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
252 ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
253 "delaying request, excess: %ui.%03ui, by zone \"%V\"", |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
254 excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); |
2294 | 255 |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
256 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
257 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
2294 | 258 } |
259 | |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
260 r->read_event_handler = ngx_http_test_reading; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
261 r->write_event_handler = ngx_http_limit_req_delay; |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
262 ngx_add_timer(r->connection->write, |
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
263 (ngx_msec_t) excess * 1000 / ctx->rate); |
2294 | 264 |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
265 return NGX_AGAIN; |
980 | 266 } |
267 | |
268 | |
269 static void | |
2294 | 270 ngx_http_limit_req_delay(ngx_http_request_t *r) |
271 { | |
2972
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
272 ngx_event_t *wev; |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
273 |
2294 | 274 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
2973 | 275 "limit_req delay"); |
2294 | 276 |
2972
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
277 wev = r->connection->write; |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
278 |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
279 if (!wev->timedout) { |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
280 |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
281 if (ngx_handle_write_event(wev, 0) != NGX_OK) { |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
282 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
283 } |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
284 |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
285 return; |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
286 } |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
287 |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
288 wev->timedout = 0; |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
289 |
2294 | 290 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { |
291 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
292 return; | |
293 } | |
294 | |
295 r->read_event_handler = ngx_http_block_reading; | |
296 r->write_event_handler = ngx_http_core_run_phases; | |
297 | |
298 ngx_http_core_run_phases(r); | |
299 } | |
300 | |
301 | |
302 static void | |
303 ngx_http_limit_req_rbtree_insert_value(ngx_rbtree_node_t *temp, | |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
304 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
305 { |
2294 | 306 ngx_rbtree_node_t **p; |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
307 ngx_http_limit_req_node_t *lrn, *lrnt; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
308 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
309 for ( ;; ) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
310 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
311 if (node->key < temp->key) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
312 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
313 p = &temp->left; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
314 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
315 } else if (node->key > temp->key) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
316 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
317 p = &temp->right; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
318 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
319 } else { /* node->key == temp->key */ |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
320 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
321 lrn = (ngx_http_limit_req_node_t *) &node->color; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
322 lrnt = (ngx_http_limit_req_node_t *) &temp->color; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
323 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
324 p = (ngx_memn2cmp(lrn->data, lrnt->data, lrn->len, lrnt->len) < 0) |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
325 ? &temp->left : &temp->right; |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
326 } |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
327 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
328 if (*p == sentinel) { |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
329 break; |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
330 } |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
331 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
332 temp = *p; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
333 } |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
334 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
335 *p = node; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
336 node->parent = temp; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
337 node->left = sentinel; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
338 node->right = sentinel; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
339 ngx_rbt_red(node); |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
340 } |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
341 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
342 |
2294 | 343 static ngx_int_t |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
344 ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash, |
3779
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
345 u_char *data, size_t len, ngx_uint_t *ep) |
980 | 346 { |
2313 | 347 ngx_int_t rc, excess; |
2294 | 348 ngx_time_t *tp; |
349 ngx_msec_t now; | |
350 ngx_msec_int_t ms; | |
351 ngx_rbtree_node_t *node, *sentinel; | |
352 ngx_http_limit_req_ctx_t *ctx; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
353 ngx_http_limit_req_node_t *lr; |
2294 | 354 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
355 ctx = lrcf->shm_zone->data; |
2294 | 356 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
357 node = ctx->sh->rbtree.root; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
358 sentinel = ctx->sh->rbtree.sentinel; |
980 | 359 |
2294 | 360 while (node != sentinel) { |
361 | |
362 if (hash < node->key) { | |
363 node = node->left; | |
364 continue; | |
365 } | |
366 | |
367 if (hash > node->key) { | |
368 node = node->right; | |
369 continue; | |
370 } | |
371 | |
372 /* hash == node->key */ | |
373 | |
374 do { | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
375 lr = (ngx_http_limit_req_node_t *) &node->color; |
980 | 376 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
377 rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len); |
2294 | 378 |
379 if (rc == 0) { | |
3779
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
380 ngx_queue_remove(&lr->queue); |
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
381 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
2294 | 382 |
383 tp = ngx_timeofday(); | |
980 | 384 |
2294 | 385 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
386 ms = (ngx_msec_int_t) (now - lr->last); |
2294 | 387 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
388 excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; |
2294 | 389 |
3191 | 390 if (excess < 0) { |
391 excess = 0; | |
392 } | |
393 | |
3779
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
394 *ep = excess; |
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
395 |
3183
b87542338ac3
make limit_req to conform to the leaky bucket algorithm
Igor Sysoev <igor@sysoev.ru>
parents:
2973
diff
changeset
|
396 if ((ngx_uint_t) excess > lrcf->burst) { |
b87542338ac3
make limit_req to conform to the leaky bucket algorithm
Igor Sysoev <igor@sysoev.ru>
parents:
2973
diff
changeset
|
397 return NGX_BUSY; |
b87542338ac3
make limit_req to conform to the leaky bucket algorithm
Igor Sysoev <igor@sysoev.ru>
parents:
2973
diff
changeset
|
398 } |
b87542338ac3
make limit_req to conform to the leaky bucket algorithm
Igor Sysoev <igor@sysoev.ru>
parents:
2973
diff
changeset
|
399 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
400 lr->excess = excess; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
401 lr->last = now; |
980 | 402 |
2313 | 403 if (excess) { |
2294 | 404 return NGX_AGAIN; |
405 } | |
980 | 406 |
2294 | 407 return NGX_OK; |
408 } | |
409 | |
410 node = (rc < 0) ? node->left : node->right; | |
411 | |
412 } while (node != sentinel && hash == node->key); | |
413 | |
414 break; | |
980 | 415 } |
416 | |
3779
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
417 *ep = 0; |
2294 | 418 |
419 return NGX_DECLINED; | |
420 } | |
421 | |
422 | |
423 static void | |
424 ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n) | |
425 { | |
2313 | 426 ngx_int_t excess; |
2294 | 427 ngx_time_t *tp; |
428 ngx_msec_t now; | |
429 ngx_queue_t *q; | |
430 ngx_msec_int_t ms; | |
431 ngx_rbtree_node_t *node; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
432 ngx_http_limit_req_node_t *lr; |
2294 | 433 |
434 tp = ngx_timeofday(); | |
435 | |
436 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | |
437 | |
438 /* | |
439 * n == 1 deletes one or two zero rate entries | |
440 * n == 0 deletes oldest entry by force | |
441 * and one or two zero rate entries | |
442 */ | |
443 | |
444 while (n < 3) { | |
445 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
446 if (ngx_queue_empty(&ctx->sh->queue)) { |
2294 | 447 return; |
448 } | |
449 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
450 q = ngx_queue_last(&ctx->sh->queue); |
2294 | 451 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
452 lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue); |
2294 | 453 |
454 if (n++ != 0) { | |
455 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
456 ms = (ngx_msec_int_t) (now - lr->last); |
2294 | 457 ms = ngx_abs(ms); |
458 | |
459 if (ms < 60000) { | |
460 return; | |
461 } | |
462 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
463 excess = lr->excess - ctx->rate * ms / 1000; |
2294 | 464 |
2313 | 465 if (excess > 0) { |
2294 | 466 return; |
467 } | |
468 } | |
469 | |
470 ngx_queue_remove(q); | |
471 | |
472 node = (ngx_rbtree_node_t *) | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
473 ((u_char *) lr - offsetof(ngx_rbtree_node_t, color)); |
2294 | 474 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
475 ngx_rbtree_delete(&ctx->sh->rbtree, node); |
2294 | 476 |
477 ngx_slab_free_locked(ctx->shpool, node); | |
478 } | |
980 | 479 } |
480 | |
481 | |
482 static ngx_int_t | |
2294 | 483 ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data) |
980 | 484 { |
2294 | 485 ngx_http_limit_req_ctx_t *octx = data; |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
486 |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
487 size_t len; |
2294 | 488 ngx_http_limit_req_ctx_t *ctx; |
980 | 489 |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
490 ctx = shm_zone->data; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
491 |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
492 if (octx) { |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
493 if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
494 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, |
2294 | 495 "limit_req \"%V\" uses the \"%V\" variable " |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
496 "while previously it used the \"%V\" variable", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
497 &shm_zone->shm.name, &ctx->var, &octx->var); |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
498 return NGX_ERROR; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
499 } |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
500 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
501 ctx->sh = octx->sh; |
2294 | 502 ctx->shpool = octx->shpool; |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
503 |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
504 return NGX_OK; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
505 } |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
506 |
2294 | 507 ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; |
980 | 508 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
509 if (shm_zone->shm.exists) { |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
510 ctx->sh = ctx->shpool->data; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
511 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
512 return NGX_OK; |
980 | 513 } |
514 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
515 ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_req_shctx_t)); |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
516 if (ctx->sh == NULL) { |
980 | 517 return NGX_ERROR; |
518 } | |
519 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
520 ctx->shpool->data = ctx->sh; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
521 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
522 ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel, |
2294 | 523 ngx_http_limit_req_rbtree_insert_value); |
524 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
525 ngx_queue_init(&ctx->sh->queue); |
980 | 526 |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
527 len = sizeof(" in limit_req zone \"\"") + shm_zone->shm.name.len; |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
528 |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
529 ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len); |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
530 if (ctx->shpool->log_ctx == NULL) { |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
531 return NGX_ERROR; |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
532 } |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
533 |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
534 ngx_sprintf(ctx->shpool->log_ctx, " in limit_req zone \"%V\"%Z", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
535 &shm_zone->shm.name); |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
536 |
980 | 537 return NGX_OK; |
538 } | |
539 | |
540 | |
541 static void * | |
2294 | 542 ngx_http_limit_req_create_conf(ngx_conf_t *cf) |
980 | 543 { |
2294 | 544 ngx_http_limit_req_conf_t *conf; |
980 | 545 |
2294 | 546 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_conf_t)); |
980 | 547 if (conf == NULL) { |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2720
diff
changeset
|
548 return NULL; |
980 | 549 } |
550 | |
551 /* | |
552 * set by ngx_pcalloc(): | |
553 * | |
554 * conf->shm_zone = NULL; | |
2375 | 555 * conf->burst = 0; |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
556 * conf->nodelay = 0; |
980 | 557 */ |
558 | |
3185 | 559 conf->limit_log_level = NGX_CONF_UNSET_UINT; |
560 | |
980 | 561 return conf; |
562 } | |
563 | |
564 | |
565 static char * | |
2294 | 566 ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child) |
980 | 567 { |
2294 | 568 ngx_http_limit_req_conf_t *prev = parent; |
569 ngx_http_limit_req_conf_t *conf = child; | |
980 | 570 |
571 if (conf->shm_zone == NULL) { | |
572 *conf = *prev; | |
573 } | |
574 | |
3185 | 575 ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level, |
576 NGX_LOG_ERR); | |
577 | |
578 conf->delay_log_level = (conf->limit_log_level == NGX_LOG_INFO) ? | |
579 NGX_LOG_INFO : conf->limit_log_level + 1; | |
580 | |
980 | 581 return NGX_CONF_OK; |
582 } | |
583 | |
584 | |
585 static char * | |
2294 | 586 ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
980 | 587 { |
2294 | 588 u_char *p; |
589 size_t size, len; | |
590 ngx_str_t *value, name, s; | |
591 ngx_int_t rate, scale; | |
592 ngx_uint_t i; | |
593 ngx_shm_zone_t *shm_zone; | |
594 ngx_http_limit_req_ctx_t *ctx; | |
980 | 595 |
596 value = cf->args->elts; | |
597 | |
2294 | 598 ctx = NULL; |
599 size = 0; | |
600 rate = 1; | |
601 scale = 1; | |
602 name.len = 0; | |
603 | |
604 for (i = 1; i < cf->args->nelts; i++) { | |
605 | |
606 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
607 | |
608 name.data = value[i].data + 5; | |
609 | |
610 p = (u_char *) ngx_strchr(name.data, ':'); | |
611 | |
612 if (p) { | |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
613 *p = '\0'; |
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
614 |
2294 | 615 name.len = p - name.data; |
616 | |
617 p++; | |
618 | |
619 s.len = value[i].data + value[i].len - p; | |
620 s.data = p; | |
621 | |
622 size = ngx_parse_size(&s); | |
623 if (size > 8191) { | |
624 continue; | |
625 } | |
626 } | |
627 | |
628 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
629 "invalid zone size \"%V\"", &value[i]); | |
630 return NGX_CONF_ERROR; | |
631 } | |
632 | |
633 if (ngx_strncmp(value[i].data, "rate=", 5) == 0) { | |
634 | |
635 len = value[i].len; | |
636 p = value[i].data + len - 3; | |
987 | 637 |
2294 | 638 if (ngx_strncmp(p, "r/s", 3) == 0) { |
639 scale = 1; | |
640 len -= 3; | |
641 | |
642 } else if (ngx_strncmp(p, "r/m", 3) == 0) { | |
643 scale = 60; | |
644 len -= 3; | |
645 } | |
646 | |
647 rate = ngx_atoi(value[i].data + 5, len - 5); | |
648 if (rate <= NGX_ERROR) { | |
649 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
650 "invalid rate \"%V\"", &value[i]); | |
651 return NGX_CONF_ERROR; | |
652 } | |
653 | |
654 continue; | |
655 } | |
656 | |
657 if (value[i].data[0] == '$') { | |
987 | 658 |
2294 | 659 value[i].len--; |
660 value[i].data++; | |
661 | |
662 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t)); | |
663 if (ctx == NULL) { | |
664 return NGX_CONF_ERROR; | |
665 } | |
666 | |
667 ctx->index = ngx_http_get_variable_index(cf, &value[i]); | |
668 if (ctx->index == NGX_ERROR) { | |
669 return NGX_CONF_ERROR; | |
670 } | |
671 | |
672 ctx->var = value[i]; | |
673 | |
674 continue; | |
675 } | |
676 | |
677 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
678 "invalid parameter \"%V\"", &value[i]); | |
987 | 679 return NGX_CONF_ERROR; |
680 } | |
681 | |
2294 | 682 if (name.len == 0 || size == 0) { |
683 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
684 "\"%V\" must have \"zone\" parameter", | |
685 &cmd->name); | |
987 | 686 return NGX_CONF_ERROR; |
687 } | |
688 | |
2294 | 689 if (ctx == NULL) { |
980 | 690 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 691 "no variable is defined for limit_req_zone \"%V\"", |
692 &cmd->name); | |
980 | 693 return NGX_CONF_ERROR; |
694 } | |
695 | |
2313 | 696 ctx->rate = rate * 1000 / scale; |
980 | 697 |
2294 | 698 shm_zone = ngx_shared_memory_add(cf, &name, size, |
699 &ngx_http_limit_req_module); | |
980 | 700 if (shm_zone == NULL) { |
701 return NGX_CONF_ERROR; | |
702 } | |
703 | |
987 | 704 if (shm_zone->data) { |
705 ctx = shm_zone->data; | |
706 | |
707 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
2294 | 708 "limit_req_zone \"%V\" is already bound to variable \"%V\"", |
709 &value[1], &ctx->var); | |
987 | 710 return NGX_CONF_ERROR; |
711 } | |
712 | |
2294 | 713 shm_zone->init = ngx_http_limit_req_init_zone; |
987 | 714 shm_zone->data = ctx; |
980 | 715 |
716 return NGX_CONF_OK; | |
717 } | |
718 | |
719 | |
720 static char * | |
2294 | 721 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
980 | 722 { |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
723 ngx_http_limit_req_conf_t *lrcf = conf; |
980 | 724 |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
725 ngx_int_t burst; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
726 ngx_str_t *value, s; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
727 ngx_uint_t i; |
2294 | 728 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
729 if (lrcf->shm_zone) { |
2294 | 730 return "is duplicate"; |
731 } | |
980 | 732 |
733 value = cf->args->elts; | |
734 | |
2294 | 735 burst = 0; |
736 | |
737 for (i = 1; i < cf->args->nelts; i++) { | |
738 | |
739 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
740 | |
741 s.len = value[i].len - 5; | |
742 s.data = value[i].data + 5; | |
743 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
744 lrcf->shm_zone = ngx_shared_memory_add(cf, &s, 0, |
2294 | 745 &ngx_http_limit_req_module); |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
746 if (lrcf->shm_zone == NULL) { |
2294 | 747 return NGX_CONF_ERROR; |
748 } | |
749 | |
750 continue; | |
751 } | |
752 | |
753 if (ngx_strncmp(value[i].data, "burst=", 6) == 0) { | |
754 | |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
755 burst = ngx_atoi(value[i].data + 6, value[i].len - 6); |
2294 | 756 if (burst <= 0) { |
757 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
758 "invalid burst rate \"%V\"", &value[i]); | |
759 return NGX_CONF_ERROR; | |
760 } | |
761 | |
762 continue; | |
763 } | |
764 | |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
765 if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) { |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
766 lrcf->nodelay = 1; |
2294 | 767 continue; |
768 } | |
769 | |
770 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
771 "invalid parameter \"%V\"", &value[i]); | |
980 | 772 return NGX_CONF_ERROR; |
773 } | |
774 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
775 if (lrcf->shm_zone == NULL) { |
980 | 776 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 777 "\"%V\" must have \"zone\" parameter", |
778 &cmd->name); | |
980 | 779 return NGX_CONF_ERROR; |
780 } | |
781 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
782 if (lrcf->shm_zone->data == NULL) { |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
783 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 784 "unknown limit_req_zone \"%V\"", |
2716
d5896f6608e8
move zone name from ngx_shm_zone_t to ngx_shm_t to use Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2612
diff
changeset
|
785 &lrcf->shm_zone->shm.name); |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
786 return NGX_CONF_ERROR; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
787 } |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
788 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
789 lrcf->burst = burst * 1000; |
980 | 790 |
791 return NGX_CONF_OK; | |
792 } | |
793 | |
794 | |
795 static ngx_int_t | |
2294 | 796 ngx_http_limit_req_init(ngx_conf_t *cf) |
980 | 797 { |
798 ngx_http_handler_pt *h; | |
799 ngx_http_core_main_conf_t *cmcf; | |
800 | |
801 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
802 | |
803 h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); | |
804 if (h == NULL) { | |
805 return NGX_ERROR; | |
806 } | |
807 | |
2294 | 808 *h = ngx_http_limit_req_handler; |
980 | 809 |
810 return NGX_OK; | |
811 } |