Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_split_clients_module.c @ 4009:3183165283cc
Fixing proxy_set_body and proxy_pass_request_body with SSL.
Flush flag wasn't set in constructed buffer and this prevented any data
from being actually sent to upstream due to SSL buffering. Make sure
we always set flush in the last buffer we are going to sent.
See here for report:
http://nginx.org/pipermail/nginx-ru/2011-June/041552.html
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 18 Aug 2011 16:34:24 +0000 |
parents | eccd0b66a4ab |
children | d620f497c50f |
rev | line source |
---|---|
3513 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
12 typedef struct { | |
13 uint32_t percent; | |
14 ngx_http_variable_value_t value; | |
15 } ngx_http_split_clients_part_t; | |
16 | |
17 | |
18 typedef struct { | |
19 ngx_http_complex_value_t value; | |
20 ngx_array_t parts; | |
21 } ngx_http_split_clients_ctx_t; | |
22 | |
23 | |
24 static char *ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, | |
25 void *conf); | |
26 static char *ngx_http_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, | |
27 void *conf); | |
28 | |
29 static ngx_command_t ngx_http_split_clients_commands[] = { | |
30 | |
31 { ngx_string("split_clients"), | |
32 NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2, | |
33 ngx_conf_split_clients_block, | |
34 NGX_HTTP_MAIN_CONF_OFFSET, | |
35 0, | |
36 NULL }, | |
37 | |
38 ngx_null_command | |
39 }; | |
40 | |
41 | |
42 static ngx_http_module_t ngx_http_split_clients_module_ctx = { | |
43 NULL, /* preconfiguration */ | |
44 NULL, /* postconfiguration */ | |
45 | |
46 NULL, /* create main configuration */ | |
47 NULL, /* init main configuration */ | |
48 | |
49 NULL, /* create server configuration */ | |
50 NULL, /* merge server configuration */ | |
51 | |
52 NULL, /* create location configuration */ | |
53 NULL /* merge location configuration */ | |
54 }; | |
55 | |
56 | |
57 ngx_module_t ngx_http_split_clients_module = { | |
58 NGX_MODULE_V1, | |
59 &ngx_http_split_clients_module_ctx, /* module context */ | |
60 ngx_http_split_clients_commands, /* module directives */ | |
61 NGX_HTTP_MODULE, /* module type */ | |
62 NULL, /* init master */ | |
63 NULL, /* init module */ | |
64 NULL, /* init process */ | |
65 NULL, /* init thread */ | |
66 NULL, /* exit thread */ | |
67 NULL, /* exit process */ | |
68 NULL, /* exit master */ | |
69 NGX_MODULE_V1_PADDING | |
70 }; | |
71 | |
72 | |
73 static ngx_int_t | |
74 ngx_http_split_clients_variable(ngx_http_request_t *r, | |
75 ngx_http_variable_value_t *v, uintptr_t data) | |
76 { | |
77 ngx_http_split_clients_ctx_t *ctx = (ngx_http_split_clients_ctx_t *) data; | |
78 | |
79 uint32_t hash; | |
80 ngx_str_t val; | |
81 ngx_uint_t i; | |
82 ngx_http_split_clients_part_t *part; | |
83 | |
84 *v = ngx_http_variable_null_value; | |
85 | |
86 if (ngx_http_complex_value(r, &ctx->value, &val) != NGX_OK) { | |
87 return NGX_OK; | |
88 } | |
89 | |
3892
12d8d2f30205
use MurmurHash2 for split_clients, because
Igor Sysoev <igor@sysoev.ru>
parents:
3607
diff
changeset
|
90 hash = ngx_murmur_hash2(val.data, val.len); |
3513 | 91 |
92 part = ctx->parts.elts; | |
93 | |
94 for (i = 0; i < ctx->parts.nelts; i++) { | |
95 | |
96 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
3918 | 97 "http split: %uD %uD", hash, part[i].percent); |
3513 | 98 |
99 if (hash < part[i].percent) { | |
100 *v = part[i].value; | |
101 return NGX_OK; | |
102 } | |
103 } | |
104 | |
105 return NGX_OK; | |
106 } | |
107 | |
108 | |
109 static char * | |
110 ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
111 { | |
112 char *rv; | |
113 ngx_str_t *value, name; | |
114 ngx_uint_t i, sum, last; | |
115 ngx_conf_t save; | |
116 ngx_http_variable_t *var; | |
117 ngx_http_split_clients_ctx_t *ctx; | |
118 ngx_http_split_clients_part_t *part; | |
119 ngx_http_compile_complex_value_t ccv; | |
120 | |
121 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_split_clients_ctx_t)); | |
122 if (ctx == NULL) { | |
123 return NGX_CONF_ERROR; | |
124 } | |
125 | |
126 value = cf->args->elts; | |
127 | |
128 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
129 | |
130 ccv.cf = cf; | |
131 ccv.value = &value[1]; | |
132 ccv.complex_value = &ctx->value; | |
133 | |
134 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
135 return NGX_CONF_ERROR; | |
136 } | |
137 | |
138 name = value[2]; | |
139 name.len--; | |
140 name.data++; | |
141 | |
142 var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); | |
143 if (var == NULL) { | |
144 return NGX_CONF_ERROR; | |
145 } | |
146 | |
147 var->get_handler = ngx_http_split_clients_variable; | |
148 var->data = (uintptr_t) ctx; | |
149 | |
150 if (ngx_array_init(&ctx->parts, cf->pool, 2, | |
151 sizeof(ngx_http_split_clients_part_t)) | |
152 != NGX_OK) | |
153 { | |
154 return NGX_CONF_ERROR; | |
155 } | |
156 | |
157 save = *cf; | |
158 cf->ctx = ctx; | |
159 cf->handler = ngx_http_split_clients; | |
160 cf->handler_conf = conf; | |
161 | |
162 rv = ngx_conf_parse(cf, NULL); | |
163 | |
164 *cf = save; | |
165 | |
3607
8bff43217171
do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents:
3513
diff
changeset
|
166 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
|
167 return rv; |
8bff43217171
do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents:
3513
diff
changeset
|
168 } |
8bff43217171
do not try to calculate procent sum if there was an error
Igor Sysoev <igor@sysoev.ru>
parents:
3513
diff
changeset
|
169 |
3513 | 170 sum = 0; |
171 last = 0; | |
172 part = ctx->parts.elts; | |
173 | |
174 for (i = 0; i < ctx->parts.nelts; i++) { | |
175 sum = part[i].percent ? sum + part[i].percent : 10000; | |
176 if (sum > 10000) { | |
177 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
178 "percent sum is more than 100%%"); | |
179 return NGX_CONF_ERROR; | |
180 } | |
181 | |
182 if (part[i].percent) { | |
183 part[i].percent = (uint32_t) | |
184 (last + 0xffffffff / 10000 * part[i].percent); | |
185 } else { | |
186 part[i].percent = 0xffffffff; | |
187 } | |
188 | |
189 last = part[i].percent; | |
190 } | |
191 | |
192 return rv; | |
193 } | |
194 | |
195 | |
196 static char * | |
197 ngx_http_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) | |
198 { | |
199 ngx_int_t n; | |
200 ngx_str_t *value; | |
201 ngx_http_split_clients_ctx_t *ctx; | |
202 ngx_http_split_clients_part_t *part; | |
203 | |
204 ctx = cf->ctx; | |
205 value = cf->args->elts; | |
206 | |
207 part = ngx_array_push(&ctx->parts); | |
208 if (part == NULL) { | |
209 return NGX_CONF_ERROR; | |
210 } | |
211 | |
212 if (value[0].len == 1 && value[0].data[0] == '*') { | |
213 part->percent = 0; | |
214 | |
215 } else { | |
216 if (value[0].data[value[0].len - 1] != '%') { | |
217 goto invalid; | |
218 } | |
219 | |
220 n = ngx_atofp(value[0].data, value[0].len - 1, 2); | |
221 if (n == NGX_ERROR || n == 0) { | |
222 goto invalid; | |
223 } | |
224 | |
225 part->percent = (uint32_t) n; | |
226 } | |
227 | |
228 part->value.len = value[1].len; | |
229 part->value.valid = 1; | |
230 part->value.no_cacheable = 0; | |
231 part->value.not_found = 0; | |
232 part->value.data = value[1].data; | |
233 | |
234 return NGX_CONF_OK; | |
235 | |
236 invalid: | |
237 | |
238 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
239 "invalid percent value \"%V\"", &value[0]); | |
240 return NGX_CONF_ERROR; | |
241 } |