Mercurial > hg > nginx
annotate src/http/modules/ngx_http_limit_req_module.c @ 8570:6dac06dfe779 quic
QUIC: inline function instead of macro for hexdump.
This prevents name clashes with local variables.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Mon, 05 Oct 2020 10:03:01 +0300 |
parents | 776d1bebdca2 |
children | 559d19037984 |
rev | line source |
---|---|
980 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
980 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
13 #define NGX_HTTP_LIMIT_REQ_PASSED 1 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
14 #define NGX_HTTP_LIMIT_REQ_DELAYED 2 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
15 #define NGX_HTTP_LIMIT_REQ_REJECTED 3 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
16 #define NGX_HTTP_LIMIT_REQ_DELAYED_DRY_RUN 4 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
17 #define NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN 5 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
18 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
19 |
980 | 20 typedef struct { |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
21 u_char color; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
22 u_char dummy; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
23 u_short len; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
24 ngx_queue_t queue; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
25 ngx_msec_t last; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
26 /* 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
|
27 ngx_uint_t excess; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
28 ngx_uint_t count; |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
29 u_char data[1]; |
2294 | 30 } ngx_http_limit_req_node_t; |
980 | 31 |
32 | |
33 typedef struct { | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
34 ngx_rbtree_t rbtree; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
35 ngx_rbtree_node_t sentinel; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
36 ngx_queue_t queue; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
37 } ngx_http_limit_req_shctx_t; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
38 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
39 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
40 typedef struct { |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
41 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
|
42 ngx_slab_pool_t *shpool; |
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 rate; |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
45 ngx_http_complex_value_t key; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
46 ngx_http_limit_req_node_t *node; |
2294 | 47 } ngx_http_limit_req_ctx_t; |
987 | 48 |
49 | |
50 typedef struct { | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
51 ngx_shm_zone_t *shm_zone; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
52 /* 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
|
53 ngx_uint_t burst; |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
54 ngx_uint_t delay; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
55 } ngx_http_limit_req_limit_t; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
56 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
57 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
58 typedef struct { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
59 ngx_array_t limits; |
3185 | 60 ngx_uint_t limit_log_level; |
61 ngx_uint_t delay_log_level; | |
5117
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
62 ngx_uint_t status_code; |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
63 ngx_flag_t dry_run; |
2294 | 64 } ngx_http_limit_req_conf_t; |
980 | 65 |
66 | |
2294 | 67 static void ngx_http_limit_req_delay(ngx_http_request_t *r); |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
68 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, |
5863
102f85699420
Limit req: reduced number of parameters in the lookup function.
Valentin Bartenev <vbart@nginx.com>
parents:
5862
diff
changeset
|
69 ngx_uint_t hash, ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account); |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
70 static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
71 ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit); |
2294 | 72 static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, |
73 ngx_uint_t n); | |
980 | 74 |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
75 static ngx_int_t ngx_http_limit_req_status_variable(ngx_http_request_t *r, |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
76 ngx_http_variable_value_t *v, uintptr_t data); |
2294 | 77 static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf); |
78 static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, | |
980 | 79 void *child); |
2294 | 80 static char *ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, |
980 | 81 void *conf); |
2294 | 82 static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, |
980 | 83 void *conf); |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
84 static ngx_int_t ngx_http_limit_req_add_variables(ngx_conf_t *cf); |
2294 | 85 static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf); |
980 | 86 |
87 | |
3185 | 88 static ngx_conf_enum_t ngx_http_limit_req_log_levels[] = { |
89 { ngx_string("info"), NGX_LOG_INFO }, | |
90 { ngx_string("notice"), NGX_LOG_NOTICE }, | |
91 { ngx_string("warn"), NGX_LOG_WARN }, | |
92 { ngx_string("error"), NGX_LOG_ERR }, | |
93 { ngx_null_string, 0 } | |
94 }; | |
95 | |
96 | |
5117
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
97 static ngx_conf_num_bounds_t ngx_http_limit_req_status_bounds = { |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
98 ngx_conf_check_num_bounds, 400, 599 |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
99 }; |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
100 |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
101 |
2294 | 102 static ngx_command_t ngx_http_limit_req_commands[] = { |
980 | 103 |
2294 | 104 { ngx_string("limit_req_zone"), |
987 | 105 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3, |
2294 | 106 ngx_http_limit_req_zone, |
980 | 107 0, |
108 0, | |
109 NULL }, | |
110 | |
2294 | 111 { ngx_string("limit_req"), |
112 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, | |
113 ngx_http_limit_req, | |
980 | 114 NGX_HTTP_LOC_CONF_OFFSET, |
115 0, | |
116 NULL }, | |
117 | |
3185 | 118 { ngx_string("limit_req_log_level"), |
119 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
120 ngx_conf_set_enum_slot, | |
121 NGX_HTTP_LOC_CONF_OFFSET, | |
122 offsetof(ngx_http_limit_req_conf_t, limit_log_level), | |
123 &ngx_http_limit_req_log_levels }, | |
124 | |
5117
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
125 { ngx_string("limit_req_status"), |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
126 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
127 ngx_conf_set_num_slot, |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
128 NGX_HTTP_LOC_CONF_OFFSET, |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
129 offsetof(ngx_http_limit_req_conf_t, status_code), |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
130 &ngx_http_limit_req_status_bounds }, |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
131 |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
132 { ngx_string("limit_req_dry_run"), |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
133 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
134 ngx_conf_set_flag_slot, |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
135 NGX_HTTP_LOC_CONF_OFFSET, |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
136 offsetof(ngx_http_limit_req_conf_t, dry_run), |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
137 NULL }, |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
138 |
980 | 139 ngx_null_command |
140 }; | |
141 | |
142 | |
2294 | 143 static ngx_http_module_t ngx_http_limit_req_module_ctx = { |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
144 ngx_http_limit_req_add_variables, /* preconfiguration */ |
2294 | 145 ngx_http_limit_req_init, /* postconfiguration */ |
980 | 146 |
147 NULL, /* create main configuration */ | |
148 NULL, /* init main configuration */ | |
149 | |
150 NULL, /* create server configuration */ | |
151 NULL, /* merge server configuration */ | |
152 | |
4499
778ef9c3fd2d
Fixed spelling in single-line comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4497
diff
changeset
|
153 ngx_http_limit_req_create_conf, /* create location configuration */ |
778ef9c3fd2d
Fixed spelling in single-line comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4497
diff
changeset
|
154 ngx_http_limit_req_merge_conf /* merge location configuration */ |
980 | 155 }; |
156 | |
157 | |
2294 | 158 ngx_module_t ngx_http_limit_req_module = { |
980 | 159 NGX_MODULE_V1, |
2294 | 160 &ngx_http_limit_req_module_ctx, /* module context */ |
161 ngx_http_limit_req_commands, /* module directives */ | |
980 | 162 NGX_HTTP_MODULE, /* module type */ |
163 NULL, /* init master */ | |
164 NULL, /* init module */ | |
165 NULL, /* init process */ | |
166 NULL, /* init thread */ | |
167 NULL, /* exit thread */ | |
168 NULL, /* exit process */ | |
169 NULL, /* exit master */ | |
170 NGX_MODULE_V1_PADDING | |
171 }; | |
172 | |
173 | |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
174 static ngx_http_variable_t ngx_http_limit_req_vars[] = { |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
175 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
176 { ngx_string("limit_req_status"), NULL, |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
177 ngx_http_limit_req_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
178 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
179 ngx_http_null_variable |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
180 }; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
181 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
182 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
183 static ngx_str_t ngx_http_limit_req_status[] = { |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
184 ngx_string("PASSED"), |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
185 ngx_string("DELAYED"), |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
186 ngx_string("REJECTED"), |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
187 ngx_string("DELAYED_DRY_RUN"), |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
188 ngx_string("REJECTED_DRY_RUN") |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
189 }; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
190 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
191 |
980 | 192 static ngx_int_t |
2294 | 193 ngx_http_limit_req_handler(ngx_http_request_t *r) |
980 | 194 { |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
195 uint32_t hash; |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
196 ngx_str_t key; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
197 ngx_int_t rc; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
198 ngx_uint_t n, excess; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
199 ngx_msec_t delay; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
200 ngx_http_limit_req_ctx_t *ctx; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
201 ngx_http_limit_req_conf_t *lrcf; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
202 ngx_http_limit_req_limit_t *limit, *limits; |
980 | 203 |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
204 if (r->main->limit_req_status) { |
984
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
205 return NGX_DECLINED; |
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
206 } |
dd128232e6ba
count connection once per request
Igor Sysoev <igor@sysoev.ru>
parents:
981
diff
changeset
|
207 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
208 lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module); |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
209 limits = lrcf->limits.elts; |
980 | 210 |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
211 excess = 0; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
212 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
213 rc = NGX_DECLINED; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
214 |
4424
aacd7356c197
Limit req: unbreak compilation with MSVC.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4420
diff
changeset
|
215 #if (NGX_SUPPRESS_WARN) |
aacd7356c197
Limit req: unbreak compilation with MSVC.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4420
diff
changeset
|
216 limit = NULL; |
aacd7356c197
Limit req: unbreak compilation with MSVC.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4420
diff
changeset
|
217 #endif |
aacd7356c197
Limit req: unbreak compilation with MSVC.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4420
diff
changeset
|
218 |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
219 for (n = 0; n < lrcf->limits.nelts; n++) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
220 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
221 limit = &limits[n]; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
222 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
223 ctx = limit->shm_zone->data; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
224 |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
225 if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) { |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
226 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
227 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
228 |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
229 if (key.len == 0) { |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
230 continue; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
231 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
232 |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
233 if (key.len > 65535) { |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
234 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
235 "the value of the \"%V\" key " |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
236 "is more than 65535 bytes: \"%V\"", |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
237 &ctx->key.value, &key); |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
238 continue; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
239 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
240 |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
241 hash = ngx_crc32_short(key.data, key.len); |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
242 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
243 ngx_shmtx_lock(&ctx->shpool->mutex); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
244 |
5863
102f85699420
Limit req: reduced number of parameters in the lookup function.
Valentin Bartenev <vbart@nginx.com>
parents:
5862
diff
changeset
|
245 rc = ngx_http_limit_req_lookup(limit, hash, &key, &excess, |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
246 (n == lrcf->limits.nelts - 1)); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
247 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
248 ngx_shmtx_unlock(&ctx->shpool->mutex); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
249 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
250 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
251 "limit_req[%ui]: %i %ui.%03ui", |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
252 n, rc, excess / 1000, excess % 1000); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
253 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
254 if (rc != NGX_AGAIN) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
255 break; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
256 } |
980 | 257 } |
258 | |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
259 if (rc == NGX_DECLINED) { |
1011
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
260 return NGX_DECLINED; |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
261 } |
19118c44303f
test length of variable and number of connections
Igor Sysoev <igor@sysoev.ru>
parents:
1002
diff
changeset
|
262 |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
263 if (rc == NGX_BUSY || rc == NGX_ERROR) { |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
264 |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
265 if (rc == NGX_BUSY) { |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
266 ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
267 "limiting requests%s, excess: %ui.%03ui by zone \"%V\"", |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
268 lrcf->dry_run ? ", dry run" : "", |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
269 excess / 1000, excess % 1000, |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
270 &limit->shm_zone->shm.name); |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
271 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
272 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
273 while (n--) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
274 ctx = limits[n].shm_zone->data; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
275 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
276 if (ctx->node == NULL) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
277 continue; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
278 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
279 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
280 ngx_shmtx_lock(&ctx->shpool->mutex); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
281 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
282 ctx->node->count--; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
283 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
284 ngx_shmtx_unlock(&ctx->shpool->mutex); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
285 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
286 ctx->node = NULL; |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
287 } |
980 | 288 |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
289 if (lrcf->dry_run) { |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
290 r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN; |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
291 return NGX_DECLINED; |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
292 } |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
293 |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
294 r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
295 |
5117
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
296 return lrcf->status_code; |
980 | 297 } |
298 | |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
299 /* rc == NGX_AGAIN || rc == NGX_OK */ |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
300 |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
301 if (rc == NGX_AGAIN) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
302 excess = 0; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
303 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
304 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
305 delay = ngx_http_limit_req_account(limits, n, &excess, &limit); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
306 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
307 if (!delay) { |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
308 r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_PASSED; |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
309 return NGX_DECLINED; |
2294 | 310 } |
311 | |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
312 ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
313 "delaying request%s, excess: %ui.%03ui, by zone \"%V\"", |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
314 lrcf->dry_run ? ", dry run" : "", |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
315 excess / 1000, excess % 1000, &limit->shm_zone->shm.name); |
2294 | 316 |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
317 if (lrcf->dry_run) { |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
318 r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED_DRY_RUN; |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
319 return NGX_DECLINED; |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
320 } |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
321 |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
322 r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
323 |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
324 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
|
325 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
2294 | 326 } |
327 | |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
328 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
|
329 r->write_event_handler = ngx_http_limit_req_delay; |
6959
7fcf209d40c8
Limit req: fixed delaying subrequests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6653
diff
changeset
|
330 |
7fcf209d40c8
Limit req: fixed delaying subrequests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6653
diff
changeset
|
331 r->connection->write->delayed = 1; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
332 ngx_add_timer(r->connection->write, delay); |
2294 | 333 |
3780
d94d7104f598
change order of limit_req lookup result processing
Igor Sysoev <igor@sysoev.ru>
parents:
3779
diff
changeset
|
334 return NGX_AGAIN; |
980 | 335 } |
336 | |
337 | |
338 static void | |
2294 | 339 ngx_http_limit_req_delay(ngx_http_request_t *r) |
340 { | |
2972
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
341 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
|
342 |
2294 | 343 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
2973 | 344 "limit_req delay"); |
2294 | 345 |
2972
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
346 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
|
347 |
6961
903fb1ddc07f
Moved handling of wev->delayed to the connection event handler.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6959
diff
changeset
|
348 if (wev->delayed) { |
2972
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
349 |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
350 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
|
351 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
|
352 } |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
353 |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
354 return; |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
355 } |
c5ad288f851d
fix client write event handling in ngx_http_limit_req_module
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
356 |
2294 | 357 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { |
358 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
359 return; | |
360 } | |
361 | |
362 r->read_event_handler = ngx_http_block_reading; | |
363 r->write_event_handler = ngx_http_core_run_phases; | |
364 | |
365 ngx_http_core_run_phases(r); | |
366 } | |
367 | |
368 | |
369 static void | |
370 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
|
371 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
|
372 { |
2294 | 373 ngx_rbtree_node_t **p; |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
374 ngx_http_limit_req_node_t *lrn, *lrnt; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
375 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
376 for ( ;; ) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
377 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
378 if (node->key < temp->key) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
379 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
380 p = &temp->left; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
381 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
382 } else if (node->key > temp->key) { |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
383 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
384 p = &temp->right; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
385 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
386 } else { /* node->key == temp->key */ |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
387 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
388 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
|
389 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
|
390 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
391 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
|
392 ? &temp->left : &temp->right; |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
393 } |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
394 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
395 if (*p == sentinel) { |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
396 break; |
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
397 } |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
398 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
399 temp = *p; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
400 } |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
401 |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1406
diff
changeset
|
402 *p = node; |
1026
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
403 node->parent = temp; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
404 node->left = sentinel; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
405 node->right = sentinel; |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
406 ngx_rbt_red(node); |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
407 } |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
408 |
38be15c1379a
fix duplicate rbtree keys case
Igor Sysoev <igor@sysoev.ru>
parents:
1012
diff
changeset
|
409 |
2294 | 410 static ngx_int_t |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
411 ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash, |
5863
102f85699420
Limit req: reduced number of parameters in the lookup function.
Valentin Bartenev <vbart@nginx.com>
parents:
5862
diff
changeset
|
412 ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account) |
980 | 413 { |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
414 size_t size; |
2313 | 415 ngx_int_t rc, excess; |
2294 | 416 ngx_msec_t now; |
417 ngx_msec_int_t ms; | |
418 ngx_rbtree_node_t *node, *sentinel; | |
419 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
|
420 ngx_http_limit_req_node_t *lr; |
2294 | 421 |
6653
7a6456398fc3
Simplified extraction of current time.
Ruslan Ermilov <ru@nginx.com>
parents:
6117
diff
changeset
|
422 now = ngx_current_msec; |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
423 |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
424 ctx = limit->shm_zone->data; |
2294 | 425 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
426 node = ctx->sh->rbtree.root; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
427 sentinel = ctx->sh->rbtree.sentinel; |
980 | 428 |
2294 | 429 while (node != sentinel) { |
430 | |
431 if (hash < node->key) { | |
432 node = node->left; | |
433 continue; | |
434 } | |
435 | |
436 if (hash > node->key) { | |
437 node = node->right; | |
438 continue; | |
439 } | |
440 | |
441 /* hash == node->key */ | |
442 | |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
443 lr = (ngx_http_limit_req_node_t *) &node->color; |
2294 | 444 |
5863
102f85699420
Limit req: reduced number of parameters in the lookup function.
Valentin Bartenev <vbart@nginx.com>
parents:
5862
diff
changeset
|
445 rc = ngx_memn2cmp(key->data, lr->data, key->len, (size_t) lr->len); |
3191 | 446 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
447 if (rc == 0) { |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
448 ngx_queue_remove(&lr->queue); |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
449 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
3183
b87542338ac3
make limit_req to conform to the leaky bucket algorithm
Igor Sysoev <igor@sysoev.ru>
parents:
2973
diff
changeset
|
450 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
451 ms = (ngx_msec_int_t) (now - lr->last); |
980 | 452 |
7281
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
453 if (ms < -60000) { |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
454 ms = 1; |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
455 |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
456 } else if (ms < 0) { |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
457 ms = 0; |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
458 } |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
459 |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
460 excess = lr->excess - ctx->rate * ms / 1000 + 1000; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
461 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
462 if (excess < 0) { |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
463 excess = 0; |
2294 | 464 } |
465 | |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
466 *ep = excess; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
467 |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
468 if ((ngx_uint_t) excess > limit->burst) { |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
469 return NGX_BUSY; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
470 } |
2294 | 471 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
472 if (account) { |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
473 lr->excess = excess; |
7281
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
474 |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
475 if (ms) { |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
476 lr->last = now; |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
477 } |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
478 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
479 return NGX_OK; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
480 } |
2294 | 481 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
482 lr->count++; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
483 |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
484 ctx->node = lr; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
485 |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
486 return NGX_AGAIN; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
487 } |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
488 |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4424
diff
changeset
|
489 node = (rc < 0) ? node->left : node->right; |
980 | 490 } |
491 | |
3779
57aecfdcac3d
an excess was logged as 0.000 if requests were limited without delay:
Igor Sysoev <igor@sysoev.ru>
parents:
3525
diff
changeset
|
492 *ep = 0; |
2294 | 493 |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
494 size = offsetof(ngx_rbtree_node_t, color) |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
495 + offsetof(ngx_http_limit_req_node_t, data) |
5863
102f85699420
Limit req: reduced number of parameters in the lookup function.
Valentin Bartenev <vbart@nginx.com>
parents:
5862
diff
changeset
|
496 + key->len; |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
497 |
4419
7084faa7a4b4
Limit req: number of cleanup calls reduced.
Valentin Bartenev <vbart@nginx.com>
parents:
4418
diff
changeset
|
498 ngx_http_limit_req_expire(ctx, 1); |
7084faa7a4b4
Limit req: number of cleanup calls reduced.
Valentin Bartenev <vbart@nginx.com>
parents:
4418
diff
changeset
|
499 |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
500 node = ngx_slab_alloc_locked(ctx->shpool, size); |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
501 |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
502 if (node == NULL) { |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
503 ngx_http_limit_req_expire(ctx, 0); |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
504 |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
505 node = ngx_slab_alloc_locked(ctx->shpool, size); |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
506 if (node == NULL) { |
5634
5024d29354f1
Core: slab log_nomem flag.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5411
diff
changeset
|
507 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, |
5024d29354f1
Core: slab log_nomem flag.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5411
diff
changeset
|
508 "could not allocate node%s", ctx->shpool->log_ctx); |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
509 return NGX_ERROR; |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
510 } |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
511 } |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
512 |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
513 node->key = hash; |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
514 |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
515 lr = (ngx_http_limit_req_node_t *) &node->color; |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
516 |
5863
102f85699420
Limit req: reduced number of parameters in the lookup function.
Valentin Bartenev <vbart@nginx.com>
parents:
5862
diff
changeset
|
517 lr->len = (u_short) key->len; |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
518 lr->excess = 0; |
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
519 |
5863
102f85699420
Limit req: reduced number of parameters in the lookup function.
Valentin Bartenev <vbart@nginx.com>
parents:
5862
diff
changeset
|
520 ngx_memcpy(lr->data, key->data, key->len); |
4418
aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
Valentin Bartenev <vbart@nginx.com>
parents:
4417
diff
changeset
|
521 |
4832
949ea3d3cd1a
Limit req: fix of rbtree node insertion on hash collisions.
Valentin Bartenev <vbart@nginx.com>
parents:
4811
diff
changeset
|
522 ngx_rbtree_insert(&ctx->sh->rbtree, node); |
949ea3d3cd1a
Limit req: fix of rbtree node insertion on hash collisions.
Valentin Bartenev <vbart@nginx.com>
parents:
4811
diff
changeset
|
523 |
949ea3d3cd1a
Limit req: fix of rbtree node insertion on hash collisions.
Valentin Bartenev <vbart@nginx.com>
parents:
4811
diff
changeset
|
524 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
949ea3d3cd1a
Limit req: fix of rbtree node insertion on hash collisions.
Valentin Bartenev <vbart@nginx.com>
parents:
4811
diff
changeset
|
525 |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
526 if (account) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
527 lr->last = now; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
528 lr->count = 0; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
529 return NGX_OK; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
530 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
531 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
532 lr->last = 0; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
533 lr->count = 1; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
534 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
535 ctx->node = lr; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
536 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
537 return NGX_AGAIN; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
538 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
539 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
540 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
541 static ngx_msec_t |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
542 ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n, |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
543 ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit) |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
544 { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
545 ngx_int_t excess; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
546 ngx_msec_t now, delay, max_delay; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
547 ngx_msec_int_t ms; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
548 ngx_http_limit_req_ctx_t *ctx; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
549 ngx_http_limit_req_node_t *lr; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
550 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
551 excess = *ep; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
552 |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
553 if ((ngx_uint_t) excess <= (*limit)->delay) { |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
554 max_delay = 0; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
555 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
556 } else { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
557 ctx = (*limit)->shm_zone->data; |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
558 max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
559 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
560 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
561 while (n--) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
562 ctx = limits[n].shm_zone->data; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
563 lr = ctx->node; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
564 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
565 if (lr == NULL) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
566 continue; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
567 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
568 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
569 ngx_shmtx_lock(&ctx->shpool->mutex); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
570 |
6653
7a6456398fc3
Simplified extraction of current time.
Ruslan Ermilov <ru@nginx.com>
parents:
6117
diff
changeset
|
571 now = ngx_current_msec; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
572 ms = (ngx_msec_int_t) (now - lr->last); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
573 |
7281
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
574 if (ms < -60000) { |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
575 ms = 1; |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
576 |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
577 } else if (ms < 0) { |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
578 ms = 0; |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
579 } |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
580 |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
581 excess = lr->excess - ctx->rate * ms / 1000 + 1000; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
582 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
583 if (excess < 0) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
584 excess = 0; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
585 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
586 |
7281
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
587 if (ms) { |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
588 lr->last = now; |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
589 } |
bd6563e81cea
Limit req: improved handling of negative times.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6961
diff
changeset
|
590 |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
591 lr->excess = excess; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
592 lr->count--; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
593 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
594 ngx_shmtx_unlock(&ctx->shpool->mutex); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
595 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
596 ctx->node = NULL; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
597 |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
598 if ((ngx_uint_t) excess <= limits[n].delay) { |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
599 continue; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
600 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
601 |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
602 delay = (excess - limits[n].delay) * 1000 / ctx->rate; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
603 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
604 if (delay > max_delay) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
605 max_delay = delay; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
606 *ep = excess; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
607 *limit = &limits[n]; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
608 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
609 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
610 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
611 return max_delay; |
2294 | 612 } |
613 | |
614 | |
615 static void | |
616 ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n) | |
617 { | |
2313 | 618 ngx_int_t excess; |
2294 | 619 ngx_msec_t now; |
620 ngx_queue_t *q; | |
621 ngx_msec_int_t ms; | |
622 ngx_rbtree_node_t *node; | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
623 ngx_http_limit_req_node_t *lr; |
2294 | 624 |
6653
7a6456398fc3
Simplified extraction of current time.
Ruslan Ermilov <ru@nginx.com>
parents:
6117
diff
changeset
|
625 now = ngx_current_msec; |
2294 | 626 |
627 /* | |
628 * n == 1 deletes one or two zero rate entries | |
629 * n == 0 deletes oldest entry by force | |
630 * and one or two zero rate entries | |
631 */ | |
632 | |
633 while (n < 3) { | |
634 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
635 if (ngx_queue_empty(&ctx->sh->queue)) { |
2294 | 636 return; |
637 } | |
638 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
639 q = ngx_queue_last(&ctx->sh->queue); |
2294 | 640 |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
641 lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue); |
2294 | 642 |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
643 if (lr->count) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
644 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
645 /* |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
646 * There is not much sense in looking further, |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
647 * because we bump nodes on the lookup stage. |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
648 */ |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
649 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
650 return; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
651 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
652 |
2294 | 653 if (n++ != 0) { |
654 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
655 ms = (ngx_msec_int_t) (now - lr->last); |
2294 | 656 ms = ngx_abs(ms); |
657 | |
658 if (ms < 60000) { | |
659 return; | |
660 } | |
661 | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
662 excess = lr->excess - ctx->rate * ms / 1000; |
2294 | 663 |
2313 | 664 if (excess > 0) { |
2294 | 665 return; |
666 } | |
667 } | |
668 | |
669 ngx_queue_remove(q); | |
670 | |
671 node = (ngx_rbtree_node_t *) | |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
672 ((u_char *) lr - offsetof(ngx_rbtree_node_t, color)); |
2294 | 673 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
674 ngx_rbtree_delete(&ctx->sh->rbtree, node); |
2294 | 675 |
676 ngx_slab_free_locked(ctx->shpool, node); | |
677 } | |
980 | 678 } |
679 | |
680 | |
681 static ngx_int_t | |
2294 | 682 ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data) |
980 | 683 { |
2294 | 684 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
|
685 |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
686 size_t len; |
2294 | 687 ngx_http_limit_req_ctx_t *ctx; |
980 | 688 |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
689 ctx = shm_zone->data; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
690 |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
691 if (octx) { |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
692 if (ctx->key.value.len != octx->key.value.len |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
693 || ngx_strncmp(ctx->key.value.data, octx->key.value.data, |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
694 ctx->key.value.len) |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
695 != 0) |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
696 { |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
697 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
698 "limit_req \"%V\" uses the \"%V\" key " |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
699 "while previously it used the \"%V\" key", |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
700 &shm_zone->shm.name, &ctx->key.value, |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
701 &octx->key.value); |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
702 return NGX_ERROR; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
703 } |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
704 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
705 ctx->sh = octx->sh; |
2294 | 706 ctx->shpool = octx->shpool; |
993
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
707 |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
708 return NGX_OK; |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
709 } |
1b9a4d92173f
pass the inherited shm_zone data
Igor Sysoev <igor@sysoev.ru>
parents:
987
diff
changeset
|
710 |
2294 | 711 ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; |
980 | 712 |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
713 if (shm_zone->shm.exists) { |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
714 ctx->sh = ctx->shpool->data; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
715 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
716 return NGX_OK; |
980 | 717 } |
718 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
719 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
|
720 if (ctx->sh == NULL) { |
980 | 721 return NGX_ERROR; |
722 } | |
723 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
724 ctx->shpool->data = ctx->sh; |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
725 |
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
726 ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel, |
2294 | 727 ngx_http_limit_req_rbtree_insert_value); |
728 | |
2720
b3b8c66bd520
support attaching to an existent Win32 shared memory
Igor Sysoev <igor@sysoev.ru>
parents:
2716
diff
changeset
|
729 ngx_queue_init(&ctx->sh->queue); |
980 | 730 |
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
|
731 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
|
732 |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
733 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
|
734 if (ctx->shpool->log_ctx == NULL) { |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
735 return NGX_ERROR; |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
736 } |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
737 |
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
738 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
|
739 &shm_zone->shm.name); |
2611
2bce3f6416c6
improve ngx_slab_alloc() error logging
Igor Sysoev <igor@sysoev.ru>
parents:
2376
diff
changeset
|
740 |
5634
5024d29354f1
Core: slab log_nomem flag.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5411
diff
changeset
|
741 ctx->shpool->log_nomem = 0; |
5024d29354f1
Core: slab log_nomem flag.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5411
diff
changeset
|
742 |
980 | 743 return NGX_OK; |
744 } | |
745 | |
746 | |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
747 static ngx_int_t |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
748 ngx_http_limit_req_status_variable(ngx_http_request_t *r, |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
749 ngx_http_variable_value_t *v, uintptr_t data) |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
750 { |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
751 if (r->main->limit_req_status == 0) { |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
752 v->not_found = 1; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
753 return NGX_OK; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
754 } |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
755 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
756 v->valid = 1; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
757 v->no_cacheable = 0; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
758 v->not_found = 0; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
759 v->len = ngx_http_limit_req_status[r->main->limit_req_status - 1].len; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
760 v->data = ngx_http_limit_req_status[r->main->limit_req_status - 1].data; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
761 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
762 return NGX_OK; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
763 } |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
764 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
765 |
980 | 766 static void * |
2294 | 767 ngx_http_limit_req_create_conf(ngx_conf_t *cf) |
980 | 768 { |
2294 | 769 ngx_http_limit_req_conf_t *conf; |
980 | 770 |
2294 | 771 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_conf_t)); |
980 | 772 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
|
773 return NULL; |
980 | 774 } |
775 | |
776 /* | |
777 * set by ngx_pcalloc(): | |
778 * | |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
779 * conf->limits.elts = NULL; |
980 | 780 */ |
781 | |
3185 | 782 conf->limit_log_level = NGX_CONF_UNSET_UINT; |
5117
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
783 conf->status_code = NGX_CONF_UNSET_UINT; |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
784 conf->dry_run = NGX_CONF_UNSET; |
3185 | 785 |
980 | 786 return conf; |
787 } | |
788 | |
789 | |
790 static char * | |
2294 | 791 ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child) |
980 | 792 { |
2294 | 793 ngx_http_limit_req_conf_t *prev = parent; |
794 ngx_http_limit_req_conf_t *conf = child; | |
980 | 795 |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
796 if (conf->limits.elts == NULL) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
797 conf->limits = prev->limits; |
980 | 798 } |
799 | |
3185 | 800 ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level, |
801 NGX_LOG_ERR); | |
802 | |
803 conf->delay_log_level = (conf->limit_log_level == NGX_LOG_INFO) ? | |
804 NGX_LOG_INFO : conf->limit_log_level + 1; | |
805 | |
5117
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
806 ngx_conf_merge_uint_value(conf->status_code, prev->status_code, |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
807 NGX_HTTP_SERVICE_UNAVAILABLE); |
00e4459739ed
The limit_req_status and limit_conn_status directives.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4832
diff
changeset
|
808 |
7515
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
809 ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0); |
2db68852d6a0
Limit req: limit_req_dry_run directive.
Roman Arutyunyan <arut@nginx.com>
parents:
7399
diff
changeset
|
810 |
980 | 811 return NGX_CONF_OK; |
812 } | |
813 | |
814 | |
815 static char * | |
2294 | 816 ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
980 | 817 { |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
818 u_char *p; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
819 size_t len; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
820 ssize_t size; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
821 ngx_str_t *value, name, s; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
822 ngx_int_t rate, scale; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
823 ngx_uint_t i; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
824 ngx_shm_zone_t *shm_zone; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
825 ngx_http_limit_req_ctx_t *ctx; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
826 ngx_http_compile_complex_value_t ccv; |
980 | 827 |
828 value = cf->args->elts; | |
829 | |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
830 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t)); |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
831 if (ctx == NULL) { |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
832 return NGX_CONF_ERROR; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
833 } |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
834 |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
835 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
836 |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
837 ccv.cf = cf; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
838 ccv.value = &value[1]; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
839 ccv.complex_value = &ctx->key; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
840 |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
841 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
842 return NGX_CONF_ERROR; |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
843 } |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
844 |
2294 | 845 size = 0; |
846 rate = 1; | |
847 scale = 1; | |
848 name.len = 0; | |
849 | |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
850 for (i = 2; i < cf->args->nelts; i++) { |
2294 | 851 |
852 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
853 | |
854 name.data = value[i].data + 5; | |
855 | |
856 p = (u_char *) ngx_strchr(name.data, ':'); | |
857 | |
4417
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
858 if (p == NULL) { |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
859 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
860 "invalid zone size \"%V\"", &value[i]); |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
861 return NGX_CONF_ERROR; |
2294 | 862 } |
863 | |
4417
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
864 name.len = p - name.data; |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
865 |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
866 s.data = p + 1; |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
867 s.len = value[i].data + value[i].len - s.data; |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
868 |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
869 size = ngx_parse_size(&s); |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
870 |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
871 if (size == NGX_ERROR) { |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
872 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
873 "invalid zone size \"%V\"", &value[i]); |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
874 return NGX_CONF_ERROR; |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
875 } |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
876 |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
877 if (size < (ssize_t) (8 * ngx_pagesize)) { |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
878 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
879 "zone \"%V\" is too small", &value[i]); |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
880 return NGX_CONF_ERROR; |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
881 } |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
882 |
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
883 continue; |
2294 | 884 } |
885 | |
886 if (ngx_strncmp(value[i].data, "rate=", 5) == 0) { | |
887 | |
888 len = value[i].len; | |
889 p = value[i].data + len - 3; | |
987 | 890 |
2294 | 891 if (ngx_strncmp(p, "r/s", 3) == 0) { |
892 scale = 1; | |
893 len -= 3; | |
894 | |
895 } else if (ngx_strncmp(p, "r/m", 3) == 0) { | |
896 scale = 60; | |
897 len -= 3; | |
898 } | |
899 | |
900 rate = ngx_atoi(value[i].data + 5, len - 5); | |
5166
fc595eeb6c54
Limit req: rate should be non-zero.
Valentin Bartenev <vbart@nginx.com>
parents:
5117
diff
changeset
|
901 if (rate <= 0) { |
2294 | 902 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
903 "invalid rate \"%V\"", &value[i]); | |
904 return NGX_CONF_ERROR; | |
905 } | |
906 | |
907 continue; | |
908 } | |
909 | |
910 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
911 "invalid parameter \"%V\"", &value[i]); | |
987 | 912 return NGX_CONF_ERROR; |
913 } | |
914 | |
4417
9e9d2e06f933
Limit req: improved error handling when parsing "zone" parameter of
Valentin Bartenev <vbart@nginx.com>
parents:
4416
diff
changeset
|
915 if (name.len == 0) { |
2294 | 916 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
917 "\"%V\" must have \"zone\" parameter", | |
918 &cmd->name); | |
987 | 919 return NGX_CONF_ERROR; |
920 } | |
921 | |
2313 | 922 ctx->rate = rate * 1000 / scale; |
980 | 923 |
2294 | 924 shm_zone = ngx_shared_memory_add(cf, &name, size, |
925 &ngx_http_limit_req_module); | |
980 | 926 if (shm_zone == NULL) { |
927 return NGX_CONF_ERROR; | |
928 } | |
929 | |
987 | 930 if (shm_zone->data) { |
931 ctx = shm_zone->data; | |
932 | |
933 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
5862
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
934 "%V \"%V\" is already bound to key \"%V\"", |
ecbb99aa0e12
Limit req: use complex value in limit_req_zone.
Valentin Bartenev <vbart@nginx.com>
parents:
5846
diff
changeset
|
935 &cmd->name, &name, &ctx->key.value); |
987 | 936 return NGX_CONF_ERROR; |
937 } | |
938 | |
2294 | 939 shm_zone->init = ngx_http_limit_req_init_zone; |
987 | 940 shm_zone->data = ctx; |
980 | 941 |
942 return NGX_CONF_OK; | |
943 } | |
944 | |
945 | |
946 static char * | |
2294 | 947 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
980 | 948 { |
2374
7b11f9a1bfe1
rename "lz" to "lr" in variable names
Igor Sysoev <igor@sysoev.ru>
parents:
2313
diff
changeset
|
949 ngx_http_limit_req_conf_t *lrcf = conf; |
980 | 950 |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
951 ngx_int_t burst, delay; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
952 ngx_str_t *value, s; |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
953 ngx_uint_t i; |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
954 ngx_shm_zone_t *shm_zone; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
955 ngx_http_limit_req_limit_t *limit, *limits; |
980 | 956 |
957 value = cf->args->elts; | |
958 | |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
959 shm_zone = NULL; |
2294 | 960 burst = 0; |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
961 delay = 0; |
2294 | 962 |
963 for (i = 1; i < cf->args->nelts; i++) { | |
964 | |
965 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
966 | |
967 s.len = value[i].len - 5; | |
968 s.data = value[i].data + 5; | |
969 | |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
970 shm_zone = ngx_shared_memory_add(cf, &s, 0, |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
971 &ngx_http_limit_req_module); |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
972 if (shm_zone == NULL) { |
2294 | 973 return NGX_CONF_ERROR; |
974 } | |
975 | |
976 continue; | |
977 } | |
978 | |
979 if (ngx_strncmp(value[i].data, "burst=", 6) == 0) { | |
980 | |
2300
159136c9808d
*) correct leaky bucket implementation
Igor Sysoev <igor@sysoev.ru>
parents:
2294
diff
changeset
|
981 burst = ngx_atoi(value[i].data + 6, value[i].len - 6); |
2294 | 982 if (burst <= 0) { |
983 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
7398
bca4dad0d3cb
Limit req: fixed error message wording.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7281
diff
changeset
|
984 "invalid burst value \"%V\"", &value[i]); |
2294 | 985 return NGX_CONF_ERROR; |
986 } | |
987 | |
988 continue; | |
989 } | |
990 | |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
991 if (ngx_strncmp(value[i].data, "delay=", 6) == 0) { |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
992 |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
993 delay = ngx_atoi(value[i].data + 6, value[i].len - 6); |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
994 if (delay <= 0) { |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
995 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
996 "invalid delay value \"%V\"", &value[i]); |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
997 return NGX_CONF_ERROR; |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
998 } |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
999 |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
1000 continue; |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
1001 } |
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
1002 |
5411
5483d9e77b32
Limit req: fixed "nodelay" parsing.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5166
diff
changeset
|
1003 if (ngx_strcmp(value[i].data, "nodelay") == 0) { |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
1004 delay = NGX_MAX_INT_T_VALUE / 1000; |
2294 | 1005 continue; |
1006 } | |
1007 | |
1008 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1009 "invalid parameter \"%V\"", &value[i]); | |
980 | 1010 return NGX_CONF_ERROR; |
1011 } | |
1012 | |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1013 if (shm_zone == NULL) { |
980 | 1014 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2294 | 1015 "\"%V\" must have \"zone\" parameter", |
1016 &cmd->name); | |
980 | 1017 return NGX_CONF_ERROR; |
1018 } | |
1019 | |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1020 limits = lrcf->limits.elts; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1021 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1022 if (limits == NULL) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1023 if (ngx_array_init(&lrcf->limits, cf->pool, 1, |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1024 sizeof(ngx_http_limit_req_limit_t)) |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1025 != NGX_OK) |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1026 { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1027 return NGX_CONF_ERROR; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1028 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1029 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1030 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1031 for (i = 0; i < lrcf->limits.nelts; i++) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1032 if (shm_zone == limits[i].shm_zone) { |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1033 return "is duplicate"; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1034 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1035 } |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1036 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1037 limit = ngx_array_push(&lrcf->limits); |
4811
21d1e3bcb356
Added three missing checks for NULL after ngx_array_push() calls.
Valentin Bartenev <vbart@nginx.com>
parents:
4499
diff
changeset
|
1038 if (limit == NULL) { |
21d1e3bcb356
Added three missing checks for NULL after ngx_array_push() calls.
Valentin Bartenev <vbart@nginx.com>
parents:
4499
diff
changeset
|
1039 return NGX_CONF_ERROR; |
21d1e3bcb356
Added three missing checks for NULL after ngx_array_push() calls.
Valentin Bartenev <vbart@nginx.com>
parents:
4499
diff
changeset
|
1040 } |
4420
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1041 |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1042 limit->shm_zone = shm_zone; |
9ce48f9eb85b
Limit req: support for multiple "limit_req" limits.
Valentin Bartenev <vbart@nginx.com>
parents:
4419
diff
changeset
|
1043 limit->burst = burst * 1000; |
7399
d6ca744c727e
Limit req: "delay=" parameter.
Maxim Dounin <mdounin@mdounin.ru>
parents:
7398
diff
changeset
|
1044 limit->delay = delay * 1000; |
980 | 1045 |
1046 return NGX_CONF_OK; | |
1047 } | |
1048 | |
1049 | |
1050 static ngx_int_t | |
7592
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1051 ngx_http_limit_req_add_variables(ngx_conf_t *cf) |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1052 { |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1053 ngx_http_variable_t *var, *v; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1054 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1055 for (v = ngx_http_limit_req_vars; v->name.len; v++) { |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1056 var = ngx_http_add_variable(cf, &v->name, v->flags); |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1057 if (var == NULL) { |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1058 return NGX_ERROR; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1059 } |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1060 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1061 var->get_handler = v->get_handler; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1062 var->data = v->data; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1063 } |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1064 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1065 return NGX_OK; |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1066 } |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1067 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1068 |
776d1bebdca2
Limit req: $limit_req_status variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7515
diff
changeset
|
1069 static ngx_int_t |
2294 | 1070 ngx_http_limit_req_init(ngx_conf_t *cf) |
980 | 1071 { |
1072 ngx_http_handler_pt *h; | |
1073 ngx_http_core_main_conf_t *cmcf; | |
1074 | |
1075 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
1076 | |
1077 h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); | |
1078 if (h == NULL) { | |
1079 return NGX_ERROR; | |
1080 } | |
1081 | |
2294 | 1082 *h = ngx_http_limit_req_handler; |
980 | 1083 |
1084 return NGX_OK; | |
1085 } |