annotate src/http/modules/ngx_http_split_clients_module.c @ 4664:356c91151658 stable-1.2

Merge of r4618: rewrite escaping fix (ticket #162). The following code resulted in incorrect escaping of uri and possible segfault: location / { rewrite ^(.*) $1?c=$1; return 200 "$uri"; } If there were arguments in a rewrite's replacement string, and length was actually calculated (due to duplicate captures as in the example above, or variables present), the is_args flag was set and incorrectly copied after length calculation. This resulted in escaping applied to the uri part of the replacement, resulting in incorrect escaping. Additionally, buffer was allocated without escaping expected, thus this also resulted in buffer overrun and possible segfault.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 04 Jun 2012 11:07:19 +0000
parents 834049edae24
children 9c9fbdbe9383
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
1
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
2 /*
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
3 * Copyright (C) Igor Sysoev
4412
d620f497c50f Copyright updated.
Maxim Konovalov <maxim@nginx.com>
parents: 3918
diff changeset
4 * Copyright (C) Nginx, Inc.
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
5 */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
6
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
7
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
8 #include <ngx_config.h>
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
9 #include <ngx_core.h>
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
10 #include <ngx_http.h>
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
11
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
12
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
13 typedef struct {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
14 uint32_t percent;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
15 ngx_http_variable_value_t value;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
16 } ngx_http_split_clients_part_t;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
17
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
18
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
19 typedef struct {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
20 ngx_http_complex_value_t value;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
21 ngx_array_t parts;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
22 } ngx_http_split_clients_ctx_t;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
23
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
24
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
25 static char *ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
26 void *conf);
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
27 static char *ngx_http_split_clients(ngx_conf_t *cf, ngx_command_t *dummy,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
28 void *conf);
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
29
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
30 static ngx_command_t ngx_http_split_clients_commands[] = {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
31
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
32 { ngx_string("split_clients"),
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
33 NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
34 ngx_conf_split_clients_block,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
35 NGX_HTTP_MAIN_CONF_OFFSET,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
36 0,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
37 NULL },
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
38
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
39 ngx_null_command
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
40 };
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
41
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
42
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
43 static ngx_http_module_t ngx_http_split_clients_module_ctx = {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
44 NULL, /* preconfiguration */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
45 NULL, /* postconfiguration */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
46
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
47 NULL, /* create main configuration */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
48 NULL, /* init main configuration */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
49
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
50 NULL, /* create server configuration */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
51 NULL, /* merge server configuration */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
52
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
53 NULL, /* create location configuration */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
54 NULL /* merge location configuration */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
55 };
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
56
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
57
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
58 ngx_module_t ngx_http_split_clients_module = {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
59 NGX_MODULE_V1,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
60 &ngx_http_split_clients_module_ctx, /* module context */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
61 ngx_http_split_clients_commands, /* module directives */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
62 NGX_HTTP_MODULE, /* module type */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
63 NULL, /* init master */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
64 NULL, /* init module */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
65 NULL, /* init process */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
66 NULL, /* init thread */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
67 NULL, /* exit thread */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
68 NULL, /* exit process */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
69 NULL, /* exit master */
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
70 NGX_MODULE_V1_PADDING
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
71 };
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
72
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
73
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
74 static ngx_int_t
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
75 ngx_http_split_clients_variable(ngx_http_request_t *r,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
76 ngx_http_variable_value_t *v, uintptr_t data)
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
77 {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
78 ngx_http_split_clients_ctx_t *ctx = (ngx_http_split_clients_ctx_t *) data;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
79
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
80 uint32_t hash;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
81 ngx_str_t val;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
82 ngx_uint_t i;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
83 ngx_http_split_clients_part_t *part;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
84
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
85 *v = ngx_http_variable_null_value;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
86
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
87 if (ngx_http_complex_value(r, &ctx->value, &val) != NGX_OK) {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
88 return NGX_OK;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
89 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
90
3892
12d8d2f30205 use MurmurHash2 for split_clients, because
Igor Sysoev <igor@sysoev.ru>
parents: 3607
diff changeset
91 hash = ngx_murmur_hash2(val.data, val.len);
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
92
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
93 part = ctx->parts.elts;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
94
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
95 for (i = 0; i < ctx->parts.nelts; i++) {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
96
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
97 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3918
eccd0b66a4ab fix debug logging
Igor Sysoev <igor@sysoev.ru>
parents: 3892
diff changeset
98 "http split: %uD %uD", hash, part[i].percent);
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
99
4561
ae63013cbffa Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents: 4412
diff changeset
100 if (hash < part[i].percent || part[i].percent == 0) {
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
101 *v = part[i].value;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
102 return NGX_OK;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
103 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
104 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
105
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
106 return NGX_OK;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
107 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
108
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
109
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
110 static char *
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
111 ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
112 {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
113 char *rv;
4561
ae63013cbffa Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents: 4412
diff changeset
114 uint32_t sum, last;
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
115 ngx_str_t *value, name;
4561
ae63013cbffa Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents: 4412
diff changeset
116 ngx_uint_t i;
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
117 ngx_conf_t save;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
118 ngx_http_variable_t *var;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
119 ngx_http_split_clients_ctx_t *ctx;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
120 ngx_http_split_clients_part_t *part;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
121 ngx_http_compile_complex_value_t ccv;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
122
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
123 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_split_clients_ctx_t));
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
124 if (ctx == NULL) {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
125 return NGX_CONF_ERROR;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
126 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
127
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
128 value = cf->args->elts;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
129
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
130 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
131
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
132 ccv.cf = cf;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
133 ccv.value = &value[1];
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
134 ccv.complex_value = &ctx->value;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
135
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
136 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
137 return NGX_CONF_ERROR;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
138 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
139
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
140 name = value[2];
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
141 name.len--;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
142 name.data++;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
143
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
144 var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
145 if (var == NULL) {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
146 return NGX_CONF_ERROR;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
147 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
148
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
149 var->get_handler = ngx_http_split_clients_variable;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
150 var->data = (uintptr_t) ctx;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
151
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
152 if (ngx_array_init(&ctx->parts, cf->pool, 2,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
153 sizeof(ngx_http_split_clients_part_t))
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
154 != NGX_OK)
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
155 {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
156 return NGX_CONF_ERROR;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
157 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
158
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
159 save = *cf;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
160 cf->ctx = ctx;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
161 cf->handler = ngx_http_split_clients;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
162 cf->handler_conf = conf;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
163
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
164 rv = ngx_conf_parse(cf, NULL);
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
165
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
166 *cf = save;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
167
3607
8bff43217171 do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents: 3513
diff changeset
168 if (rv != NGX_CONF_OK) {
8bff43217171 do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents: 3513
diff changeset
169 return rv;
8bff43217171 do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents: 3513
diff changeset
170 }
8bff43217171 do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents: 3513
diff changeset
171
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
172 sum = 0;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
173 last = 0;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
174 part = ctx->parts.elts;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
175
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
176 for (i = 0; i < ctx->parts.nelts; i++) {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
177 sum = part[i].percent ? sum + part[i].percent : 10000;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
178 if (sum > 10000) {
4561
ae63013cbffa Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents: 4412
diff changeset
179 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4593
834049edae24 Fixed grammar in error messages.
Ruslan Ermilov <ru@nginx.com>
parents: 4561
diff changeset
180 "percent total is greater than 100%%");
4561
ae63013cbffa Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents: 4412
diff changeset
181 return NGX_CONF_ERROR;
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
182 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
183
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
184 if (part[i].percent) {
4561
ae63013cbffa Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents: 4412
diff changeset
185 last += part[i].percent * (uint64_t) 0xffffffff / 10000;
ae63013cbffa Fixed calculation of range boundaries.
Ruslan Ermilov <ru@nginx.com>
parents: 4412
diff changeset
186 part[i].percent = last;
3513
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
187 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
188 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
189
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
190 return rv;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
191 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
192
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
193
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
194 static char *
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
195 ngx_http_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
196 {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
197 ngx_int_t n;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
198 ngx_str_t *value;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
199 ngx_http_split_clients_ctx_t *ctx;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
200 ngx_http_split_clients_part_t *part;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
201
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
202 ctx = cf->ctx;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
203 value = cf->args->elts;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
204
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
205 part = ngx_array_push(&ctx->parts);
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
206 if (part == NULL) {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
207 return NGX_CONF_ERROR;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
208 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
209
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
210 if (value[0].len == 1 && value[0].data[0] == '*') {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
211 part->percent = 0;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
212
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
213 } else {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
214 if (value[0].data[value[0].len - 1] != '%') {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
215 goto invalid;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
216 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
217
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
218 n = ngx_atofp(value[0].data, value[0].len - 1, 2);
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
219 if (n == NGX_ERROR || n == 0) {
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
220 goto invalid;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
221 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
222
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
223 part->percent = (uint32_t) n;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
224 }
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
225
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
226 part->value.len = value[1].len;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
227 part->value.valid = 1;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
228 part->value.no_cacheable = 0;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
229 part->value.not_found = 0;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
230 part->value.data = value[1].data;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
231
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
232 return NGX_CONF_OK;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
233
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
234 invalid:
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
235
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
236 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
237 "invalid percent value \"%V\"", &value[0]);
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
238 return NGX_CONF_ERROR;
e60e00b4fe0c ngx_http_split_clients_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
239 }