Mercurial > hg > nginx
comparison src/http/modules/ngx_http_limit_conn_module.c @ 7595:9606d93aa586
Limit conn: $limit_conn_status variable.
The variable takes one of the values: PASSED, REJECTED or REJECTED_DRY_RUN.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 18 Nov 2019 17:48:32 +0300 |
parents | 359b0ea2b067 |
children | b45f052483b8 |
comparison
equal
deleted
inserted
replaced
7594:359b0ea2b067 | 7595:9606d93aa586 |
---|---|
6 | 6 |
7 | 7 |
8 #include <ngx_config.h> | 8 #include <ngx_config.h> |
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_http.h> | 10 #include <ngx_http.h> |
11 | |
12 | |
13 #define NGX_HTTP_LIMIT_CONN_PASSED 1 | |
14 #define NGX_HTTP_LIMIT_CONN_REJECTED 2 | |
15 #define NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN 3 | |
11 | 16 |
12 | 17 |
13 typedef struct { | 18 typedef struct { |
14 u_char color; | 19 u_char color; |
15 u_char len; | 20 u_char len; |
47 static ngx_rbtree_node_t *ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, | 52 static ngx_rbtree_node_t *ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, |
48 ngx_str_t *key, uint32_t hash); | 53 ngx_str_t *key, uint32_t hash); |
49 static void ngx_http_limit_conn_cleanup(void *data); | 54 static void ngx_http_limit_conn_cleanup(void *data); |
50 static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool); | 55 static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool); |
51 | 56 |
57 static ngx_int_t ngx_http_limit_conn_status_variable(ngx_http_request_t *r, | |
58 ngx_http_variable_value_t *v, uintptr_t data); | |
52 static void *ngx_http_limit_conn_create_conf(ngx_conf_t *cf); | 59 static void *ngx_http_limit_conn_create_conf(ngx_conf_t *cf); |
53 static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, | 60 static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, |
54 void *child); | 61 void *child); |
55 static char *ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, | 62 static char *ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, |
56 void *conf); | 63 void *conf); |
57 static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, | 64 static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, |
58 void *conf); | 65 void *conf); |
66 static ngx_int_t ngx_http_limit_conn_add_variables(ngx_conf_t *cf); | |
59 static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf); | 67 static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf); |
60 | 68 |
61 | 69 |
62 static ngx_conf_enum_t ngx_http_limit_conn_log_levels[] = { | 70 static ngx_conf_enum_t ngx_http_limit_conn_log_levels[] = { |
63 { ngx_string("info"), NGX_LOG_INFO }, | 71 { ngx_string("info"), NGX_LOG_INFO }, |
113 ngx_null_command | 121 ngx_null_command |
114 }; | 122 }; |
115 | 123 |
116 | 124 |
117 static ngx_http_module_t ngx_http_limit_conn_module_ctx = { | 125 static ngx_http_module_t ngx_http_limit_conn_module_ctx = { |
118 NULL, /* preconfiguration */ | 126 ngx_http_limit_conn_add_variables, /* preconfiguration */ |
119 ngx_http_limit_conn_init, /* postconfiguration */ | 127 ngx_http_limit_conn_init, /* postconfiguration */ |
120 | 128 |
121 NULL, /* create main configuration */ | 129 NULL, /* create main configuration */ |
122 NULL, /* init main configuration */ | 130 NULL, /* init main configuration */ |
123 | 131 |
143 NULL, /* exit master */ | 151 NULL, /* exit master */ |
144 NGX_MODULE_V1_PADDING | 152 NGX_MODULE_V1_PADDING |
145 }; | 153 }; |
146 | 154 |
147 | 155 |
156 static ngx_http_variable_t ngx_http_limit_conn_vars[] = { | |
157 | |
158 { ngx_string("limit_conn_status"), NULL, | |
159 ngx_http_limit_conn_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, | |
160 | |
161 ngx_http_null_variable | |
162 }; | |
163 | |
164 | |
165 static ngx_str_t ngx_http_limit_conn_status[] = { | |
166 ngx_string("PASSED"), | |
167 ngx_string("REJECTED"), | |
168 ngx_string("REJECTED_DRY_RUN") | |
169 }; | |
170 | |
171 | |
148 static ngx_int_t | 172 static ngx_int_t |
149 ngx_http_limit_conn_handler(ngx_http_request_t *r) | 173 ngx_http_limit_conn_handler(ngx_http_request_t *r) |
150 { | 174 { |
151 size_t n; | 175 size_t n; |
152 uint32_t hash; | 176 uint32_t hash; |
159 ngx_http_limit_conn_node_t *lc; | 183 ngx_http_limit_conn_node_t *lc; |
160 ngx_http_limit_conn_conf_t *lccf; | 184 ngx_http_limit_conn_conf_t *lccf; |
161 ngx_http_limit_conn_limit_t *limits; | 185 ngx_http_limit_conn_limit_t *limits; |
162 ngx_http_limit_conn_cleanup_t *lccln; | 186 ngx_http_limit_conn_cleanup_t *lccln; |
163 | 187 |
164 if (r->main->limit_conn_set) { | 188 if (r->main->limit_conn_status) { |
165 return NGX_DECLINED; | 189 return NGX_DECLINED; |
166 } | 190 } |
167 | 191 |
168 lccf = ngx_http_get_module_loc_conf(r, ngx_http_limit_conn_module); | 192 lccf = ngx_http_get_module_loc_conf(r, ngx_http_limit_conn_module); |
169 limits = lccf->limits.elts; | 193 limits = lccf->limits.elts; |
185 "is more than 255 bytes: \"%V\"", | 209 "is more than 255 bytes: \"%V\"", |
186 &ctx->key.value, &key); | 210 &ctx->key.value, &key); |
187 continue; | 211 continue; |
188 } | 212 } |
189 | 213 |
190 r->main->limit_conn_set = 1; | 214 r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_PASSED; |
191 | 215 |
192 hash = ngx_crc32_short(key.data, key.len); | 216 hash = ngx_crc32_short(key.data, key.len); |
193 | 217 |
194 shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; | 218 shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; |
195 | 219 |
208 if (node == NULL) { | 232 if (node == NULL) { |
209 ngx_shmtx_unlock(&shpool->mutex); | 233 ngx_shmtx_unlock(&shpool->mutex); |
210 ngx_http_limit_conn_cleanup_all(r->pool); | 234 ngx_http_limit_conn_cleanup_all(r->pool); |
211 | 235 |
212 if (lccf->dry_run) { | 236 if (lccf->dry_run) { |
237 r->main->limit_conn_status = | |
238 NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN; | |
213 return NGX_DECLINED; | 239 return NGX_DECLINED; |
214 } | 240 } |
241 | |
242 r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_REJECTED; | |
215 | 243 |
216 return lccf->status_code; | 244 return lccf->status_code; |
217 } | 245 } |
218 | 246 |
219 lc = (ngx_http_limit_conn_node_t *) &node->color; | 247 lc = (ngx_http_limit_conn_node_t *) &node->color; |
239 &limits[i].shm_zone->shm.name); | 267 &limits[i].shm_zone->shm.name); |
240 | 268 |
241 ngx_http_limit_conn_cleanup_all(r->pool); | 269 ngx_http_limit_conn_cleanup_all(r->pool); |
242 | 270 |
243 if (lccf->dry_run) { | 271 if (lccf->dry_run) { |
272 r->main->limit_conn_status = | |
273 NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN; | |
244 return NGX_DECLINED; | 274 return NGX_DECLINED; |
245 } | 275 } |
276 | |
277 r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_REJECTED; | |
246 | 278 |
247 return lccf->status_code; | 279 return lccf->status_code; |
248 } | 280 } |
249 | 281 |
250 lc->conn++; | 282 lc->conn++; |
465 | 497 |
466 return NGX_OK; | 498 return NGX_OK; |
467 } | 499 } |
468 | 500 |
469 | 501 |
502 static ngx_int_t | |
503 ngx_http_limit_conn_status_variable(ngx_http_request_t *r, | |
504 ngx_http_variable_value_t *v, uintptr_t data) | |
505 { | |
506 if (r->main->limit_conn_status == 0) { | |
507 v->not_found = 1; | |
508 return NGX_OK; | |
509 } | |
510 | |
511 v->valid = 1; | |
512 v->no_cacheable = 0; | |
513 v->not_found = 0; | |
514 v->len = ngx_http_limit_conn_status[r->main->limit_conn_status - 1].len; | |
515 v->data = ngx_http_limit_conn_status[r->main->limit_conn_status - 1].data; | |
516 | |
517 return NGX_OK; | |
518 } | |
519 | |
520 | |
470 static void * | 521 static void * |
471 ngx_http_limit_conn_create_conf(ngx_conf_t *cf) | 522 ngx_http_limit_conn_create_conf(ngx_conf_t *cf) |
472 { | 523 { |
473 ngx_http_limit_conn_conf_t *conf; | 524 ngx_http_limit_conn_conf_t *conf; |
474 | 525 |
672 return NGX_CONF_OK; | 723 return NGX_CONF_OK; |
673 } | 724 } |
674 | 725 |
675 | 726 |
676 static ngx_int_t | 727 static ngx_int_t |
728 ngx_http_limit_conn_add_variables(ngx_conf_t *cf) | |
729 { | |
730 ngx_http_variable_t *var, *v; | |
731 | |
732 for (v = ngx_http_limit_conn_vars; v->name.len; v++) { | |
733 var = ngx_http_add_variable(cf, &v->name, v->flags); | |
734 if (var == NULL) { | |
735 return NGX_ERROR; | |
736 } | |
737 | |
738 var->get_handler = v->get_handler; | |
739 var->data = v->data; | |
740 } | |
741 | |
742 return NGX_OK; | |
743 } | |
744 | |
745 | |
746 static ngx_int_t | |
677 ngx_http_limit_conn_init(ngx_conf_t *cf) | 747 ngx_http_limit_conn_init(ngx_conf_t *cf) |
678 { | 748 { |
679 ngx_http_handler_pt *h; | 749 ngx_http_handler_pt *h; |
680 ngx_http_core_main_conf_t *cmcf; | 750 ngx_http_core_main_conf_t *cmcf; |
681 | 751 |