Mercurial > hg > nginx
annotate src/http/modules/ngx_http_limit_req_module.c @ 3441:b0fbe6ab9ebe stable-0.7
merge r3309, r3314, r3315, r3380:
gzip headers related fixes:
*) remove "Content-Encoding: gzip" in 304 response
sent by ngx_http_gzip_static_module
*) refactor gzip_vary handling
*) test r->header_only last, since it's not actually
frequent here: 304 and HEAD responses are not set it before the filter
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 01 Feb 2010 15:54:02 +0000 |
parents | 39f82eb3d0f2 |
children |
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; |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
45 ngx_uint_t limit_log_level; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
46 ngx_uint_t delay_log_level; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
47 |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
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, |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
54 ngx_uint_t hash, u_char *data, size_t len, ngx_http_limit_req_node_t **lrp); |
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 | |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
68 static ngx_conf_enum_t ngx_http_limit_req_log_levels[] = { |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
69 { ngx_string("info"), NGX_LOG_INFO }, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
70 { ngx_string("notice"), NGX_LOG_NOTICE }, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
71 { ngx_string("warn"), NGX_LOG_WARN }, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
72 { ngx_string("error"), NGX_LOG_ERR }, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
73 { ngx_null_string, 0 } |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
74 }; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
75 |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
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 | |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
93 { ngx_string("limit_req_log_level"), |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
94 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
95 ngx_conf_set_enum_slot, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
96 NGX_HTTP_LOC_CONF_OFFSET, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
97 offsetof(ngx_http_limit_req_conf_t, limit_log_level), |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
98 &ngx_http_limit_req_log_levels }, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
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 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
189 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &lr); |
2294 | 190 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
191 if (lr) { |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
192 ngx_queue_remove(&lr->queue); |
2294 | 193 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
194 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
2294 | 195 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
196 excess = lr->excess; |
2294 | 197 |
198 } else { | |
2313 | 199 excess = 0; |
980 | 200 } |
201 | |
2313 | 202 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
203 "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
|
204 |
2294 | 205 if (rc == NGX_BUSY) { |
206 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
|
207 |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
208 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
|
209 "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
|
210 excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); |
980 | 211 |
212 return NGX_HTTP_SERVICE_UNAVAILABLE; | |
213 } | |
214 | |
2294 | 215 if (rc == NGX_AGAIN) { |
216 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
217 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
218 if (lrcf->nodelay) { |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
219 return NGX_DECLINED; |
2294 | 220 } |
221 | |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
222 ngx_log_error(lrcf->delay_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
|
223 "delaying request, 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
|
224 excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
225 |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
226 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
227 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
228 } |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
229 |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
230 r->read_event_handler = ngx_http_test_reading; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
231 r->write_event_handler = ngx_http_limit_req_delay; |
2313 | 232 ngx_add_timer(r->connection->write, (ngx_msec_t) excess); |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
233 |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
234 return NGX_AGAIN; |
2294 | 235 } |
236 | |
237 if (rc == NGX_OK) { | |
238 goto done; | |
239 } | |
240 | |
241 /* rc == NGX_DECLINED */ | |
242 | |
243 n = offsetof(ngx_rbtree_node_t, color) | |
244 + offsetof(ngx_http_limit_req_node_t, data) | |
245 + len; | |
246 | |
247 node = ngx_slab_alloc_locked(ctx->shpool, n); | |
248 if (node == NULL) { | |
249 | |
250 ngx_http_limit_req_expire(ctx, 0); | |
251 | |
252 node = ngx_slab_alloc_locked(ctx->shpool, n); | |
253 if (node == NULL) { | |
254 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
255 return NGX_HTTP_SERVICE_UNAVAILABLE; | |
256 } | |
257 } | |
258 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
259 lr = (ngx_http_limit_req_node_t *) &node->color; |
980 | 260 |
261 node->key = hash; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
262 lr->len = (u_char) len; |
2294 | 263 |
264 tp = ngx_timeofday(); | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
265 lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); |
2294 | 266 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
267 lr->excess = 0; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
268 ngx_memcpy(lr->data, vv->data, len); |
980 | 269 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
270 ngx_rbtree_insert(&ctx->sh->rbtree, node); |
980 | 271 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
272 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
2294 | 273 |
980 | 274 done: |
275 | |
2294 | 276 ngx_shmtx_unlock(&ctx->shpool->mutex); |
980 | 277 |
278 return NGX_DECLINED; | |
279 } | |
280 | |
281 | |
282 static void | |
2294 | 283 ngx_http_limit_req_delay(ngx_http_request_t *r) |
284 { | |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
285 ngx_event_t *wev; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
286 |
2294 | 287 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
288 "limit_req delay"); |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
289 |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
290 wev = r->connection->write; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
291 |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
292 if (!wev->timedout) { |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
293 |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
294 if (ngx_handle_write_event(wev, 0) != NGX_OK) { |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
295 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
296 } |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
297 |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
298 return; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
299 } |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
300 |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
301 wev->timedout = 0; |
2294 | 302 |
303 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { | |
304 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
305 return; | |
306 } | |
307 | |
308 r->read_event_handler = ngx_http_block_reading; | |
309 r->write_event_handler = ngx_http_core_run_phases; | |
310 | |
311 ngx_http_core_run_phases(r); | |
312 } | |
313 | |
314 | |
315 static void | |
316 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
|
317 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
|
318 { |
2294 | 319 ngx_rbtree_node_t **p; |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
320 ngx_http_limit_req_node_t *lrn, *lrnt; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
321 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
322 for ( ;; ) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
323 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
324 if (node->key < temp->key) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
325 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
326 p = &temp->left; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
327 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
328 } else if (node->key > temp->key) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
329 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
330 p = &temp->right; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
331 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
332 } else { /* node->key == temp->key */ |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
333 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
334 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
|
335 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
|
336 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
337 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
|
338 ? &temp->left : &temp->right; |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
339 } |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
340 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
341 if (*p == sentinel) { |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
342 break; |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
343 } |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
344 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
345 temp = *p; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
346 } |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
347 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
348 *p = node; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
349 node->parent = temp; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
350 node->left = sentinel; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
351 node->right = sentinel; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
352 ngx_rbt_red(node); |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
353 } |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
354 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
355 |
2294 | 356 static ngx_int_t |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
357 ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash, |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
358 u_char *data, size_t len, ngx_http_limit_req_node_t **lrp) |
980 | 359 { |
2313 | 360 ngx_int_t rc, excess; |
2294 | 361 ngx_time_t *tp; |
362 ngx_msec_t now; | |
363 ngx_msec_int_t ms; | |
364 ngx_rbtree_node_t *node, *sentinel; | |
365 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
|
366 ngx_http_limit_req_node_t *lr; |
2294 | 367 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
368 ctx = lrcf->shm_zone->data; |
2294 | 369 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
370 node = ctx->sh->rbtree.root; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
371 sentinel = ctx->sh->rbtree.sentinel; |
980 | 372 |
2294 | 373 while (node != sentinel) { |
374 | |
375 if (hash < node->key) { | |
376 node = node->left; | |
377 continue; | |
378 } | |
379 | |
380 if (hash > node->key) { | |
381 node = node->right; | |
382 continue; | |
383 } | |
384 | |
385 /* hash == node->key */ | |
386 | |
387 do { | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
388 lr = (ngx_http_limit_req_node_t *) &node->color; |
980 | 389 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
390 rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len); |
2294 | 391 |
392 if (rc == 0) { | |
393 | |
394 tp = ngx_timeofday(); | |
980 | 395 |
2294 | 396 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
|
397 ms = (ngx_msec_int_t) (now - lr->last); |
2294 | 398 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
399 excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; |
2294 | 400 |
2313 | 401 if (excess < 0) { |
402 excess = 0; | |
2294 | 403 } |
404 | |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
405 if ((ngx_uint_t) excess > lrcf->burst) { |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
406 *lrp = lr; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
407 return NGX_BUSY; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
408 } |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
409 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
410 lr->excess = excess; |
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
411 lr->last = now; |
980 | 412 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
413 *lrp = lr; |
2294 | 414 |
2313 | 415 if (excess) { |
2294 | 416 return NGX_AGAIN; |
417 } | |
980 | 418 |
2294 | 419 return NGX_OK; |
420 } | |
421 | |
422 node = (rc < 0) ? node->left : node->right; | |
423 | |
424 } while (node != sentinel && hash == node->key); | |
425 | |
426 break; | |
980 | 427 } |
428 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
429 *lrp = NULL; |
2294 | 430 |
431 return NGX_DECLINED; | |
432 } | |
433 | |
434 | |
435 static void | |
436 ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n) | |
437 { | |
2313 | 438 ngx_int_t excess; |
2294 | 439 ngx_time_t *tp; |
440 ngx_msec_t now; | |
441 ngx_queue_t *q; | |
442 ngx_msec_int_t ms; | |
443 ngx_rbtree_node_t *node; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
444 ngx_http_limit_req_node_t *lr; |
2294 | 445 |
446 tp = ngx_timeofday(); | |
447 | |
448 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | |
449 | |
450 /* | |
451 * n == 1 deletes one or two zero rate entries | |
452 * n == 0 deletes oldest entry by force | |
453 * and one or two zero rate entries | |
454 */ | |
455 | |
456 while (n < 3) { | |
457 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
458 if (ngx_queue_empty(&ctx->sh->queue)) { |
2294 | 459 return; |
460 } | |
461 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
462 q = ngx_queue_last(&ctx->sh->queue); |
2294 | 463 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
464 lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue); |
2294 | 465 |
466 if (n++ != 0) { | |
467 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
468 ms = (ngx_msec_int_t) (now - lr->last); |
2294 | 469 ms = ngx_abs(ms); |
470 | |
471 if (ms < 60000) { | |
472 return; | |
473 } | |
474 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
475 excess = lr->excess - ctx->rate * ms / 1000; |
2294 | 476 |
2313 | 477 if (excess > 0) { |
2294 | 478 return; |
479 } | |
480 } | |
481 | |
482 ngx_queue_remove(q); | |
483 | |
484 node = (ngx_rbtree_node_t *) | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
485 ((u_char *) lr - offsetof(ngx_rbtree_node_t, color)); |
2294 | 486 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
487 ngx_rbtree_delete(&ctx->sh->rbtree, node); |
2294 | 488 |
489 ngx_slab_free_locked(ctx->shpool, node); | |
490 } | |
980 | 491 } |
492 | |
493 | |
494 static ngx_int_t | |
2294 | 495 ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data) |
980 | 496 { |
2294 | 497 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
|
498 |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
499 size_t len; |
2294 | 500 ngx_http_limit_req_ctx_t *ctx; |
980 | 501 |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
502 ctx = shm_zone->data; |
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 if (octx) { |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
505 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
|
506 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, |
2294 | 507 "limit_req \"%V\" uses the \"%V\" variable " |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
508 "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
|
509 &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
|
510 return NGX_ERROR; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
511 } |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
512 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
513 ctx->sh = octx->sh; |
2294 | 514 ctx->shpool = octx->shpool; |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
515 |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
516 return NGX_OK; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
517 } |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
518 |
2294 | 519 ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; |
980 | 520 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
521 if (shm_zone->shm.exists) { |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
522 ctx->sh = ctx->shpool->data; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
523 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
524 return NGX_OK; |
980 | 525 } |
526 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
527 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
|
528 if (ctx->sh == NULL) { |
980 | 529 return NGX_ERROR; |
530 } | |
531 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
532 ctx->shpool->data = ctx->sh; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
533 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
534 ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel, |
2294 | 535 ngx_http_limit_req_rbtree_insert_value); |
536 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
537 ngx_queue_init(&ctx->sh->queue); |
980 | 538 |
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
|
539 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
|
540 |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
541 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
|
542 if (ctx->shpool->log_ctx == NULL) { |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
543 return NGX_ERROR; |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
544 } |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
545 |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
546 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
|
547 &shm_zone->shm.name); |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
548 |
980 | 549 return NGX_OK; |
550 } | |
551 | |
552 | |
553 static void * | |
2294 | 554 ngx_http_limit_req_create_conf(ngx_conf_t *cf) |
980 | 555 { |
2294 | 556 ngx_http_limit_req_conf_t *conf; |
980 | 557 |
2294 | 558 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_conf_t)); |
980 | 559 if (conf == NULL) { |
3237
2efa8d2fcde1
merge r2903, r2911, r2912, r3002:
Igor Sysoev <igor@sysoev.ru>
parents:
2720
diff
changeset
|
560 return NULL; |
980 | 561 } |
562 | |
563 /* | |
564 * set by ngx_pcalloc(): | |
565 * | |
566 * conf->shm_zone = NULL; | |
2375 | 567 * conf->burst = 0; |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
568 * conf->nodelay = 0; |
980 | 569 */ |
570 | |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
571 conf->limit_log_level = NGX_CONF_UNSET_UINT; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
572 |
980 | 573 return conf; |
574 } | |
575 | |
576 | |
577 static char * | |
2294 | 578 ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child) |
980 | 579 { |
2294 | 580 ngx_http_limit_req_conf_t *prev = parent; |
581 ngx_http_limit_req_conf_t *conf = child; | |
980 | 582 |
583 if (conf->shm_zone == NULL) { | |
584 *conf = *prev; | |
585 } | |
586 | |
3240
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
587 ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level, |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
588 NGX_LOG_ERR); |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
589 |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
590 conf->delay_log_level = (conf->limit_log_level == NGX_LOG_INFO) ? |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
591 NGX_LOG_INFO : conf->limit_log_level + 1; |
39f82eb3d0f2
merge r2973, r2974, r3184, r3192, r3186, r3187:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
592 |
980 | 593 return NGX_CONF_OK; |
594 } | |
595 | |
596 | |
597 static char * | |
2294 | 598 ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
980 | 599 { |
2294 | 600 u_char *p; |
601 size_t size, len; | |
602 ngx_str_t *value, name, s; | |
603 ngx_int_t rate, scale; | |
604 ngx_uint_t i; | |
605 ngx_shm_zone_t *shm_zone; | |
606 ngx_http_limit_req_ctx_t *ctx; | |
980 | 607 |
608 value = cf->args->elts; | |
609 | |
2294 | 610 ctx = NULL; |
611 size = 0; | |
612 rate = 1; | |
613 scale = 1; | |
614 name.len = 0; | |
615 | |
616 for (i = 1; i < cf->args->nelts; i++) { | |
617 | |
618 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
619 | |
620 name.data = value[i].data + 5; | |
621 | |
622 p = (u_char *) ngx_strchr(name.data, ':'); | |
623 | |
624 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
|
625 *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
|
626 |
2294 | 627 name.len = p - name.data; |
628 | |
629 p++; | |
630 | |
631 s.len = value[i].data + value[i].len - p; | |
632 s.data = p; | |
633 | |
634 size = ngx_parse_size(&s); | |
635 if (size > 8191) { | |
636 continue; | |
637 } | |
638 } | |
639 | |
640 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
641 "invalid zone size \"%V\"", &value[i]); | |
642 return NGX_CONF_ERROR; | |
643 } | |
644 | |
645 if (ngx_strncmp(value[i].data, "rate=", 5) == 0) { | |
646 | |
647 len = value[i].len; | |
648 p = value[i].data + len - 3; | |
987 | 649 |
2294 | 650 if (ngx_strncmp(p, "r/s", 3) == 0) { |
651 scale = 1; | |
652 len -= 3; | |
653 | |
654 } else if (ngx_strncmp(p, "r/m", 3) == 0) { | |
655 scale = 60; | |
656 len -= 3; | |
657 } | |
658 | |
659 rate = ngx_atoi(value[i].data + 5, len - 5); | |
660 if (rate <= NGX_ERROR) { | |
661 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
662 "invalid rate \"%V\"", &value[i]); | |
663 return NGX_CONF_ERROR; | |
664 } | |
665 | |
666 continue; | |
667 } | |
668 | |
669 if (value[i].data[0] == '$') { | |
987 | 670 |
2294 | 671 value[i].len--; |
672 value[i].data++; | |
673 | |
674 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t)); | |
675 if (ctx == NULL) { | |
676 return NGX_CONF_ERROR; | |
677 } | |
678 | |
679 ctx->index = ngx_http_get_variable_index(cf, &value[i]); | |
680 if (ctx->index == NGX_ERROR) { | |
681 return NGX_CONF_ERROR; | |
682 } | |
683 | |
684 ctx->var = value[i]; | |
685 | |
686 continue; | |
687 } | |
688 | |
689 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
690 "invalid parameter \"%V\"", &value[i]); | |
987 | 691 return NGX_CONF_ERROR; |
692 } | |
693 | |
2294 | 694 if (name.len == 0 || size == 0) { |
695 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
696 "\"%V\" must have \"zone\" parameter", | |
697 &cmd->name); | |
987 | 698 return NGX_CONF_ERROR; |
699 } | |
700 | |
2294 | 701 if (ctx == NULL) { |
980 | 702 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 703 "no variable is defined for limit_req_zone \"%V\"", |
704 &cmd->name); | |
980 | 705 return NGX_CONF_ERROR; |
706 } | |
707 | |
2313 | 708 ctx->rate = rate * 1000 / scale; |
980 | 709 |
2294 | 710 shm_zone = ngx_shared_memory_add(cf, &name, size, |
711 &ngx_http_limit_req_module); | |
980 | 712 if (shm_zone == NULL) { |
713 return NGX_CONF_ERROR; | |
714 } | |
715 | |
987 | 716 if (shm_zone->data) { |
717 ctx = shm_zone->data; | |
718 | |
719 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
2294 | 720 "limit_req_zone \"%V\" is already bound to variable \"%V\"", |
721 &value[1], &ctx->var); | |
987 | 722 return NGX_CONF_ERROR; |
723 } | |
724 | |
2294 | 725 shm_zone->init = ngx_http_limit_req_init_zone; |
987 | 726 shm_zone->data = ctx; |
980 | 727 |
728 return NGX_CONF_OK; | |
729 } | |
730 | |
731 | |
732 static char * | |
2294 | 733 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
980 | 734 { |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
735 ngx_http_limit_req_conf_t *lrcf = conf; |
980 | 736 |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
737 ngx_int_t burst; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
738 ngx_str_t *value, s; |
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
739 ngx_uint_t i; |
2294 | 740 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
741 if (lrcf->shm_zone) { |
2294 | 742 return "is duplicate"; |
743 } | |
980 | 744 |
745 value = cf->args->elts; | |
746 | |
2294 | 747 burst = 0; |
748 | |
749 for (i = 1; i < cf->args->nelts; i++) { | |
750 | |
751 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
752 | |
753 s.len = value[i].len - 5; | |
754 s.data = value[i].data + 5; | |
755 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
756 lrcf->shm_zone = ngx_shared_memory_add(cf, &s, 0, |
2294 | 757 &ngx_http_limit_req_module); |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
758 if (lrcf->shm_zone == NULL) { |
2294 | 759 return NGX_CONF_ERROR; |
760 } | |
761 | |
762 continue; | |
763 } | |
764 | |
765 if (ngx_strncmp(value[i].data, "burst=", 6) == 0) { | |
766 | |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
767 burst = ngx_atoi(value[i].data + 6, value[i].len - 6); |
2294 | 768 if (burst <= 0) { |
769 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
770 "invalid burst rate \"%V\"", &value[i]); | |
771 return NGX_CONF_ERROR; | |
772 } | |
773 | |
774 continue; | |
775 } | |
776 | |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
777 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
|
778 lrcf->nodelay = 1; |
2294 | 779 continue; |
780 } | |
781 | |
782 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
783 "invalid parameter \"%V\"", &value[i]); | |
980 | 784 return NGX_CONF_ERROR; |
785 } | |
786 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
787 if (lrcf->shm_zone == NULL) { |
980 | 788 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 789 "\"%V\" must have \"zone\" parameter", |
790 &cmd->name); | |
980 | 791 return NGX_CONF_ERROR; |
792 } | |
793 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
794 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
|
795 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 796 "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
|
797 &lrcf->shm_zone->shm.name); |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
798 return NGX_CONF_ERROR; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
799 } |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
800 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
801 lrcf->burst = burst * 1000; |
980 | 802 |
803 return NGX_CONF_OK; | |
804 } | |
805 | |
806 | |
807 static ngx_int_t | |
2294 | 808 ngx_http_limit_req_init(ngx_conf_t *cf) |
980 | 809 { |
810 ngx_http_handler_pt *h; | |
811 ngx_http_core_main_conf_t *cmcf; | |
812 | |
813 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
814 | |
815 h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); | |
816 if (h == NULL) { | |
817 return NGX_ERROR; | |
818 } | |
819 | |
2294 | 820 *h = ngx_http_limit_req_handler; |
980 | 821 |
822 return NGX_OK; | |
823 } |