Mercurial > hg > nginx
annotate src/http/modules/ngx_http_memcached_module.c @ 4615:adcd60233817
Added r->state reset on fastcgi/scgi/uwsgi request start.
Failing to do so results in problems if 400 or 414 requests are
redirected to fastcgi/scgi/uwsgi upstream, as well as after invalid
headers got from upstream. This was already fixed for proxy in r3478,
but fastcgi (the only affected protocol at that time) was missed.
Reported by Matthieu Tourne.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 11 May 2012 13:09:24 +0000 |
parents | 778ef9c3fd2d |
children | a4512d7737f6 |
rev | line source |
---|---|
581 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
581 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_http_upstream_conf_t upstream; | |
1076 | 15 ngx_int_t index; |
581 | 16 } ngx_http_memcached_loc_conf_t; |
17 | |
18 | |
19 typedef struct { | |
20 size_t rest; | |
21 ngx_http_request_t *request; | |
597 | 22 ngx_str_t key; |
581 | 23 } ngx_http_memcached_ctx_t; |
24 | |
25 | |
26 static ngx_int_t ngx_http_memcached_create_request(ngx_http_request_t *r); | |
27 static ngx_int_t ngx_http_memcached_reinit_request(ngx_http_request_t *r); | |
28 static ngx_int_t ngx_http_memcached_process_header(ngx_http_request_t *r); | |
29 static ngx_int_t ngx_http_memcached_filter_init(void *data); | |
30 static ngx_int_t ngx_http_memcached_filter(void *data, ssize_t bytes); | |
31 static void ngx_http_memcached_abort_request(ngx_http_request_t *r); | |
32 static void ngx_http_memcached_finalize_request(ngx_http_request_t *r, | |
33 ngx_int_t rc); | |
34 | |
35 static void *ngx_http_memcached_create_loc_conf(ngx_conf_t *cf); | |
36 static char *ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, | |
37 void *parent, void *child); | |
38 | |
39 static char *ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, | |
40 void *conf); | |
41 | |
42 | |
43 static ngx_conf_bitmask_t ngx_http_memcached_next_upstream_masks[] = { | |
44 { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, | |
45 { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, | |
46 { ngx_string("invalid_response"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, | |
47 { ngx_string("not_found"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, | |
665 | 48 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, |
581 | 49 { ngx_null_string, 0 } |
50 }; | |
51 | |
52 | |
53 static ngx_command_t ngx_http_memcached_commands[] = { | |
54 | |
55 { ngx_string("memcached_pass"), | |
1788
f10228d7ea06
allow memached_pass inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1787
diff
changeset
|
56 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, |
581 | 57 ngx_http_memcached_pass, |
58 NGX_HTTP_LOC_CONF_OFFSET, | |
59 0, | |
60 NULL }, | |
61 | |
3271
fcd98af88df3
proxy_bind, fastcgi_bind, and memcached_bind
Igor Sysoev <igor@sysoev.ru>
parents:
3061
diff
changeset
|
62 { ngx_string("memcached_bind"), |
fcd98af88df3
proxy_bind, fastcgi_bind, and memcached_bind
Igor Sysoev <igor@sysoev.ru>
parents:
3061
diff
changeset
|
63 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
3399 | 64 ngx_http_upstream_bind_set_slot, |
3271
fcd98af88df3
proxy_bind, fastcgi_bind, and memcached_bind
Igor Sysoev <igor@sysoev.ru>
parents:
3061
diff
changeset
|
65 NGX_HTTP_LOC_CONF_OFFSET, |
fcd98af88df3
proxy_bind, fastcgi_bind, and memcached_bind
Igor Sysoev <igor@sysoev.ru>
parents:
3061
diff
changeset
|
66 offsetof(ngx_http_memcached_loc_conf_t, upstream.local), |
fcd98af88df3
proxy_bind, fastcgi_bind, and memcached_bind
Igor Sysoev <igor@sysoev.ru>
parents:
3061
diff
changeset
|
67 NULL }, |
fcd98af88df3
proxy_bind, fastcgi_bind, and memcached_bind
Igor Sysoev <igor@sysoev.ru>
parents:
3061
diff
changeset
|
68 |
581 | 69 { ngx_string("memcached_connect_timeout"), |
70 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
71 ngx_conf_set_msec_slot, | |
72 NGX_HTTP_LOC_CONF_OFFSET, | |
73 offsetof(ngx_http_memcached_loc_conf_t, upstream.connect_timeout), | |
74 NULL }, | |
75 | |
76 { ngx_string("memcached_send_timeout"), | |
77 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
78 ngx_conf_set_msec_slot, | |
79 NGX_HTTP_LOC_CONF_OFFSET, | |
80 offsetof(ngx_http_memcached_loc_conf_t, upstream.send_timeout), | |
81 NULL }, | |
82 | |
83 { ngx_string("memcached_buffer_size"), | |
84 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
85 ngx_conf_set_size_slot, | |
86 NGX_HTTP_LOC_CONF_OFFSET, | |
87 offsetof(ngx_http_memcached_loc_conf_t, upstream.buffer_size), | |
88 NULL }, | |
89 | |
90 { ngx_string("memcached_read_timeout"), | |
91 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
92 ngx_conf_set_msec_slot, | |
93 NGX_HTTP_LOC_CONF_OFFSET, | |
94 offsetof(ngx_http_memcached_loc_conf_t, upstream.read_timeout), | |
95 NULL }, | |
96 | |
97 { ngx_string("memcached_next_upstream"), | |
98 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
99 ngx_conf_set_bitmask_slot, | |
100 NGX_HTTP_LOC_CONF_OFFSET, | |
101 offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream), | |
102 &ngx_http_memcached_next_upstream_masks }, | |
103 | |
104 ngx_null_command | |
105 }; | |
106 | |
107 | |
667 | 108 static ngx_http_module_t ngx_http_memcached_module_ctx = { |
581 | 109 NULL, /* preconfiguration */ |
110 NULL, /* postconfiguration */ | |
111 | |
112 NULL, /* create main configuration */ | |
113 NULL, /* init main configuration */ | |
114 | |
115 NULL, /* create server configuration */ | |
116 NULL, /* merge server configuration */ | |
117 | |
4499
778ef9c3fd2d
Fixed spelling in single-line comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
118 ngx_http_memcached_create_loc_conf, /* create location configuration */ |
778ef9c3fd2d
Fixed spelling in single-line comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
119 ngx_http_memcached_merge_loc_conf /* merge location configuration */ |
581 | 120 }; |
121 | |
122 | |
123 ngx_module_t ngx_http_memcached_module = { | |
124 NGX_MODULE_V1, | |
125 &ngx_http_memcached_module_ctx, /* module context */ | |
126 ngx_http_memcached_commands, /* module directives */ | |
127 NGX_HTTP_MODULE, /* module type */ | |
128 NULL, /* init master */ | |
129 NULL, /* init module */ | |
130 NULL, /* init process */ | |
131 NULL, /* init thread */ | |
132 NULL, /* exit thread */ | |
133 NULL, /* exit process */ | |
134 NULL, /* exit master */ | |
135 NGX_MODULE_V1_PADDING | |
136 }; | |
137 | |
138 | |
1076 | 139 static ngx_str_t ngx_http_memcached_key = ngx_string("memcached_key"); |
140 | |
141 | |
581 | 142 #define NGX_HTTP_MEMCACHED_END (sizeof(ngx_http_memcached_end) - 1) |
143 static u_char ngx_http_memcached_end[] = CRLF "END" CRLF; | |
144 | |
145 | |
146 static ngx_int_t | |
147 ngx_http_memcached_handler(ngx_http_request_t *r) | |
148 { | |
149 ngx_int_t rc; | |
150 ngx_http_upstream_t *u; | |
151 ngx_http_memcached_ctx_t *ctx; | |
152 ngx_http_memcached_loc_conf_t *mlcf; | |
153 | |
645 | 154 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { |
581 | 155 return NGX_HTTP_NOT_ALLOWED; |
156 } | |
157 | |
1370
cc114c85be0f
rename ngx_http_discard_body() to ngx_http_discard_request_body()
Igor Sysoev <igor@sysoev.ru>
parents:
1333
diff
changeset
|
158 rc = ngx_http_discard_request_body(r); |
581 | 159 |
1374 | 160 if (rc != NGX_OK) { |
581 | 161 return rc; |
162 } | |
163 | |
164 if (ngx_http_set_content_type(r) != NGX_OK) { | |
165 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
166 } | |
167 | |
3006
95972b9e790b
ngx_http_upstream_create() to cleanup the previous upstream after
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
168 if (ngx_http_upstream_create(r) != NGX_OK) { |
581 | 169 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
170 } | |
171 | |
3006
95972b9e790b
ngx_http_upstream_create() to cleanup the previous upstream after
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
172 u = r->upstream; |
95972b9e790b
ngx_http_upstream_create() to cleanup the previous upstream after
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
173 |
3516
dd1570b6f237
ngx_str_set() and ngx_str_null()
Igor Sysoev <igor@sysoev.ru>
parents:
3487
diff
changeset
|
174 ngx_str_set(&u->schema, "memcached://"); |
3006
95972b9e790b
ngx_http_upstream_create() to cleanup the previous upstream after
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
175 u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module; |
581 | 176 |
3006
95972b9e790b
ngx_http_upstream_create() to cleanup the previous upstream after
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
177 mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); |
581 | 178 |
179 u->conf = &mlcf->upstream; | |
180 | |
181 u->create_request = ngx_http_memcached_create_request; | |
182 u->reinit_request = ngx_http_memcached_reinit_request; | |
183 u->process_header = ngx_http_memcached_process_header; | |
184 u->abort_request = ngx_http_memcached_abort_request; | |
185 u->finalize_request = ngx_http_memcached_finalize_request; | |
186 | |
187 ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)); | |
188 if (ctx == NULL) { | |
189 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
190 } | |
191 | |
192 ctx->rest = NGX_HTTP_MEMCACHED_END; | |
193 ctx->request = r; | |
194 | |
597 | 195 ngx_http_set_ctx(r, ctx, ngx_http_memcached_module); |
196 | |
581 | 197 u->input_filter_init = ngx_http_memcached_filter_init; |
198 u->input_filter = ngx_http_memcached_filter; | |
199 u->input_filter_ctx = ctx; | |
200 | |
3061
f444f291ed38
fix request counter for memcached, introduced in r3050
Igor Sysoev <igor@sysoev.ru>
parents:
3006
diff
changeset
|
201 r->main->count++; |
f444f291ed38
fix request counter for memcached, introduced in r3050
Igor Sysoev <igor@sysoev.ru>
parents:
3006
diff
changeset
|
202 |
581 | 203 ngx_http_upstream_init(r); |
204 | |
205 return NGX_DONE; | |
206 } | |
207 | |
208 | |
209 static ngx_int_t | |
210 ngx_http_memcached_create_request(ngx_http_request_t *r) | |
211 { | |
1076 | 212 size_t len; |
1333
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
213 uintptr_t escape; |
1076 | 214 ngx_buf_t *b; |
215 ngx_chain_t *cl; | |
216 ngx_http_memcached_ctx_t *ctx; | |
217 ngx_http_variable_value_t *vv; | |
218 ngx_http_memcached_loc_conf_t *mlcf; | |
219 | |
220 mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); | |
581 | 221 |
1076 | 222 vv = ngx_http_get_indexed_variable(r, mlcf->index); |
223 | |
224 if (vv == NULL || vv->not_found || vv->len == 0) { | |
225 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
226 "the \"$memcached_key\" variable is not set"); | |
227 return NGX_ERROR; | |
228 } | |
229 | |
1333
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
230 escape = 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_MEMCACHED); |
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
231 |
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
232 len = sizeof("get ") - 1 + vv->len + escape + sizeof(CRLF) - 1; |
581 | 233 |
234 b = ngx_create_temp_buf(r->pool, len); | |
235 if (b == NULL) { | |
236 return NGX_ERROR; | |
237 } | |
238 | |
239 cl = ngx_alloc_chain_link(r->pool); | |
240 if (cl == NULL) { | |
241 return NGX_ERROR; | |
242 } | |
243 | |
244 cl->buf = b; | |
245 cl->next = NULL; | |
246 | |
247 r->upstream->request_bufs = cl; | |
248 | |
249 *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' '; | |
250 | |
597 | 251 ctx = ngx_http_get_module_ctx(r, ngx_http_memcached_module); |
252 | |
253 ctx->key.data = b->last; | |
254 | |
1333
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
255 if (escape == 0) { |
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
256 b->last = ngx_copy(b->last, vv->data, vv->len); |
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
257 |
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
258 } else { |
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
259 b->last = (u_char *) ngx_escape_uri(b->last, vv->data, vv->len, |
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
260 NGX_ESCAPE_MEMCACHED); |
07ebeeb55700
escape space, etc in $memcached_key
Igor Sysoev <igor@sysoev.ru>
parents:
1332
diff
changeset
|
261 } |
581 | 262 |
597 | 263 ctx->key.len = b->last - ctx->key.data; |
581 | 264 |
265 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
597 | 266 "http memcached request: \"%V\"", &ctx->key); |
581 | 267 |
1088
2d8e72584534
eliminate the useless space symbol
Igor Sysoev <igor@sysoev.ru>
parents:
1076
diff
changeset
|
268 *b->last++ = CR; *b->last++ = LF; |
581 | 269 |
270 return NGX_OK; | |
271 } | |
272 | |
273 | |
274 static ngx_int_t | |
275 ngx_http_memcached_reinit_request(ngx_http_request_t *r) | |
276 { | |
277 return NGX_OK; | |
278 } | |
279 | |
280 | |
281 static ngx_int_t | |
282 ngx_http_memcached_process_header(ngx_http_request_t *r) | |
283 { | |
597 | 284 u_char *p, *len; |
285 ngx_str_t line; | |
286 ngx_http_upstream_t *u; | |
287 ngx_http_memcached_ctx_t *ctx; | |
581 | 288 |
289 u = r->upstream; | |
290 | |
291 for (p = u->buffer.pos; p < u->buffer.last; p++) { | |
292 if (*p == LF) { | |
293 goto found; | |
294 } | |
295 } | |
296 | |
297 return NGX_AGAIN; | |
298 | |
299 found: | |
300 | |
301 *p = '\0'; | |
302 | |
303 line.len = p - u->buffer.pos - 1; | |
304 line.data = u->buffer.pos; | |
305 | |
306 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
307 "memcached: \"%V\"", &line); | |
308 | |
309 p = u->buffer.pos; | |
310 | |
597 | 311 ctx = ngx_http_get_module_ctx(r, ngx_http_memcached_module); |
312 | |
581 | 313 if (ngx_strncmp(p, "VALUE ", sizeof("VALUE ") - 1) == 0) { |
314 | |
315 p += sizeof("VALUE ") - 1; | |
316 | |
597 | 317 if (ngx_strncmp(p, ctx->key.data, ctx->key.len) != 0) { |
581 | 318 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
319 "memcached sent invalid key in response \"%V\" " | |
320 "for key \"%V\"", | |
597 | 321 &line, &ctx->key); |
581 | 322 |
323 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
324 } | |
325 | |
597 | 326 p += ctx->key.len; |
581 | 327 |
328 if (*p++ != ' ') { | |
329 goto no_valid; | |
330 } | |
331 | |
332 /* skip flags */ | |
333 | |
334 while (*p) { | |
335 if (*p++ == ' ') { | |
336 goto length; | |
337 } | |
338 } | |
339 | |
340 goto no_valid; | |
341 | |
342 length: | |
343 | |
344 len = p; | |
345 | |
346 while (*p && *p++ != CR) { /* void */ } | |
347 | |
4117
103b0d9afe07
Upstream: content_length_n API change.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3523
diff
changeset
|
348 u->headers_in.content_length_n = ngx_atoof(len, p - len - 1); |
103b0d9afe07
Upstream: content_length_n API change.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3523
diff
changeset
|
349 if (u->headers_in.content_length_n == -1) { |
581 | 350 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
351 "memcached sent invalid length in response \"%V\" " | |
352 "for key \"%V\"", | |
597 | 353 &line, &ctx->key); |
581 | 354 return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
355 } | |
356 | |
357 u->headers_in.status_n = 200; | |
1567
31d4278d51c0
memcached did not set $upstream_response_time
Igor Sysoev <igor@sysoev.ru>
parents:
1554
diff
changeset
|
358 u->state->status = 200; |
581 | 359 u->buffer.pos = p + 1; |
360 | |
361 return NGX_OK; | |
362 } | |
363 | |
364 if (ngx_strcmp(p, "END\x0d") == 0) { | |
365 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
597 | 366 "key: \"%V\" was not found by memcached", &ctx->key); |
581 | 367 |
368 u->headers_in.status_n = 404; | |
1567
31d4278d51c0
memcached did not set $upstream_response_time
Igor Sysoev <igor@sysoev.ru>
parents:
1554
diff
changeset
|
369 u->state->status = 404; |
4121
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
370 u->keepalive = 1; |
581 | 371 |
372 return NGX_OK; | |
373 } | |
374 | |
375 no_valid: | |
376 | |
377 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
378 "memcached sent invalid response: \"%V\"", &line); | |
379 | |
380 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
381 } | |
382 | |
383 | |
384 static ngx_int_t | |
385 ngx_http_memcached_filter_init(void *data) | |
386 { | |
387 ngx_http_memcached_ctx_t *ctx = data; | |
388 | |
389 ngx_http_upstream_t *u; | |
390 | |
391 u = ctx->request->upstream; | |
392 | |
393 u->length += NGX_HTTP_MEMCACHED_END; | |
394 | |
395 return NGX_OK; | |
396 } | |
397 | |
398 | |
399 static ngx_int_t | |
400 ngx_http_memcached_filter(void *data, ssize_t bytes) | |
401 { | |
402 ngx_http_memcached_ctx_t *ctx = data; | |
403 | |
404 u_char *last; | |
405 ngx_buf_t *b; | |
406 ngx_chain_t *cl, **ll; | |
407 ngx_http_upstream_t *u; | |
408 | |
409 u = ctx->request->upstream; | |
410 b = &u->buffer; | |
411 | |
4118
dbddec65fdab
Upstream: r->upstream->length type change to off_t.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4117
diff
changeset
|
412 if (u->length == (ssize_t) ctx->rest) { |
581 | 413 |
414 if (ngx_strncmp(b->last, | |
1548 | 415 ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest, |
3487
5d2acf153153
revert partially r1555 and fix the error "memcached sent invalid trailer"
Igor Sysoev <igor@sysoev.ru>
parents:
3399
diff
changeset
|
416 bytes) |
1548 | 417 != 0) |
581 | 418 { |
419 ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, | |
420 "memcached sent invalid trailer"); | |
3487
5d2acf153153
revert partially r1555 and fix the error "memcached sent invalid trailer"
Igor Sysoev <igor@sysoev.ru>
parents:
3399
diff
changeset
|
421 |
5d2acf153153
revert partially r1555 and fix the error "memcached sent invalid trailer"
Igor Sysoev <igor@sysoev.ru>
parents:
3399
diff
changeset
|
422 u->length = 0; |
5d2acf153153
revert partially r1555 and fix the error "memcached sent invalid trailer"
Igor Sysoev <igor@sysoev.ru>
parents:
3399
diff
changeset
|
423 ctx->rest = 0; |
5d2acf153153
revert partially r1555 and fix the error "memcached sent invalid trailer"
Igor Sysoev <igor@sysoev.ru>
parents:
3399
diff
changeset
|
424 |
5d2acf153153
revert partially r1555 and fix the error "memcached sent invalid trailer"
Igor Sysoev <igor@sysoev.ru>
parents:
3399
diff
changeset
|
425 return NGX_OK; |
581 | 426 } |
427 | |
3487
5d2acf153153
revert partially r1555 and fix the error "memcached sent invalid trailer"
Igor Sysoev <igor@sysoev.ru>
parents:
3399
diff
changeset
|
428 u->length -= bytes; |
5d2acf153153
revert partially r1555 and fix the error "memcached sent invalid trailer"
Igor Sysoev <igor@sysoev.ru>
parents:
3399
diff
changeset
|
429 ctx->rest -= bytes; |
581 | 430 |
4121
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
431 if (u->length == 0) { |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
432 u->keepalive = 1; |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
433 } |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
434 |
581 | 435 return NGX_OK; |
436 } | |
437 | |
438 for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) { | |
439 ll = &cl->next; | |
440 } | |
441 | |
442 cl = ngx_chain_get_free_buf(ctx->request->pool, &u->free_bufs); | |
443 if (cl == NULL) { | |
444 return NGX_ERROR; | |
445 } | |
446 | |
447 cl->buf->flush = 1; | |
448 cl->buf->memory = 1; | |
449 | |
450 *ll = cl; | |
451 | |
1554
30fcc8478d85
two commits those go together by mistake
Igor Sysoev <igor@sysoev.ru>
parents:
1548
diff
changeset
|
452 last = b->last; |
30fcc8478d85
two commits those go together by mistake
Igor Sysoev <igor@sysoev.ru>
parents:
1548
diff
changeset
|
453 cl->buf->pos = last; |
581 | 454 b->last += bytes; |
455 cl->buf->last = b->last; | |
1908
f2953601ed3c
fix memory leak in long-lived non buffered connections
Igor Sysoev <igor@sysoev.ru>
parents:
1788
diff
changeset
|
456 cl->buf->tag = u->output.tag; |
581 | 457 |
458 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0, | |
459 "memcached filter bytes:%z size:%z length:%z rest:%z", | |
460 bytes, b->last - b->pos, u->length, ctx->rest); | |
461 | |
1554
30fcc8478d85
two commits those go together by mistake
Igor Sysoev <igor@sysoev.ru>
parents:
1548
diff
changeset
|
462 if (bytes <= (ssize_t) (u->length - NGX_HTTP_MEMCACHED_END)) { |
581 | 463 u->length -= bytes; |
464 return NGX_OK; | |
465 } | |
466 | |
1554
30fcc8478d85
two commits those go together by mistake
Igor Sysoev <igor@sysoev.ru>
parents:
1548
diff
changeset
|
467 last += u->length - NGX_HTTP_MEMCACHED_END; |
581 | 468 |
469 if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) { | |
470 ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, | |
471 "memcached sent invalid trailer"); | |
4121
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
472 |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
473 b->last = last; |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
474 cl->buf->last = last; |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
475 u->length = 0; |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
476 ctx->rest = 0; |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
477 |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
478 return NGX_OK; |
581 | 479 } |
480 | |
1554
30fcc8478d85
two commits those go together by mistake
Igor Sysoev <igor@sysoev.ru>
parents:
1548
diff
changeset
|
481 ctx->rest -= b->last - last; |
581 | 482 b->last = last; |
483 cl->buf->last = last; | |
484 u->length = ctx->rest; | |
485 | |
4121
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
486 if (u->length == 0) { |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
487 u->keepalive = 1; |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
488 } |
16c60162c35b
Keepalive support in memcached.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4118
diff
changeset
|
489 |
581 | 490 return NGX_OK; |
491 } | |
492 | |
493 | |
494 static void | |
495 ngx_http_memcached_abort_request(ngx_http_request_t *r) | |
496 { | |
497 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
498 "abort http memcached request"); | |
499 return; | |
500 } | |
501 | |
502 | |
503 static void | |
504 ngx_http_memcached_finalize_request(ngx_http_request_t *r, ngx_int_t rc) | |
505 { | |
506 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
507 "finalize http memcached request"); | |
508 return; | |
509 } | |
510 | |
511 | |
512 static void * | |
513 ngx_http_memcached_create_loc_conf(ngx_conf_t *cf) | |
514 { | |
515 ngx_http_memcached_loc_conf_t *conf; | |
516 | |
517 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_memcached_loc_conf_t)); | |
518 if (conf == NULL) { | |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2392
diff
changeset
|
519 return NULL; |
581 | 520 } |
521 | |
522 /* | |
523 * set by ngx_pcalloc(): | |
524 * | |
525 * conf->upstream.bufs.num = 0; | |
526 * conf->upstream.next_upstream = 0; | |
527 * conf->upstream.temp_path = NULL; | |
528 * conf->upstream.uri = { 0, NULL }; | |
529 * conf->upstream.location = NULL; | |
530 */ | |
531 | |
532 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; | |
533 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; | |
534 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; | |
535 | |
536 conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; | |
537 | |
884 | 538 /* the hardcoded values */ |
581 | 539 conf->upstream.cyclic_temp_file = 0; |
629 | 540 conf->upstream.buffering = 0; |
541 conf->upstream.ignore_client_abort = 0; | |
581 | 542 conf->upstream.send_lowat = 0; |
543 conf->upstream.bufs.num = 0; | |
544 conf->upstream.busy_buffers_size = 0; | |
545 conf->upstream.max_temp_file_size = 0; | |
546 conf->upstream.temp_file_write_size = 0; | |
657 | 547 conf->upstream.intercept_errors = 1; |
675 | 548 conf->upstream.intercept_404 = 1; |
581 | 549 conf->upstream.pass_request_headers = 0; |
550 conf->upstream.pass_request_body = 0; | |
551 | |
1787
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
552 conf->index = NGX_CONF_UNSET; |
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
553 |
581 | 554 return conf; |
555 } | |
556 | |
557 | |
558 static char * | |
559 ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
560 { | |
561 ngx_http_memcached_loc_conf_t *prev = parent; | |
562 ngx_http_memcached_loc_conf_t *conf = child; | |
563 | |
564 ngx_conf_merge_msec_value(conf->upstream.connect_timeout, | |
565 prev->upstream.connect_timeout, 60000); | |
566 | |
567 ngx_conf_merge_msec_value(conf->upstream.send_timeout, | |
568 prev->upstream.send_timeout, 60000); | |
569 | |
570 ngx_conf_merge_msec_value(conf->upstream.read_timeout, | |
571 prev->upstream.read_timeout, 60000); | |
572 | |
573 ngx_conf_merge_size_value(conf->upstream.buffer_size, | |
574 prev->upstream.buffer_size, | |
575 (size_t) ngx_pagesize); | |
576 | |
577 ngx_conf_merge_bitmask_value(conf->upstream.next_upstream, | |
578 prev->upstream.next_upstream, | |
579 (NGX_CONF_BITMASK_SET | |
580 |NGX_HTTP_UPSTREAM_FT_ERROR | |
581 |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); | |
582 | |
665 | 583 if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { |
584 conf->upstream.next_upstream = NGX_CONF_BITMASK_SET | |
585 |NGX_HTTP_UPSTREAM_FT_OFF; | |
586 } | |
587 | |
1787
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
588 if (conf->upstream.upstream == NULL) { |
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
589 conf->upstream.upstream = prev->upstream.upstream; |
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
590 } |
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
591 |
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
592 if (conf->index == NGX_CONF_UNSET) { |
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
593 conf->index = prev->index; |
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
594 } |
a37fe5ceacc4
inherit $memached_key index and memcached_pass upstream inside "if" block
Igor Sysoev <igor@sysoev.ru>
parents:
1658
diff
changeset
|
595 |
581 | 596 return NGX_CONF_OK; |
597 } | |
598 | |
599 | |
600 static char * | |
601 ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
602 { | |
2392 | 603 ngx_http_memcached_loc_conf_t *mlcf = conf; |
581 | 604 |
605 ngx_str_t *value; | |
807
3095bf59059b
now the "memcached_pass" directive uses ngx_parse_url()
Igor Sysoev <igor@sysoev.ru>
parents:
675
diff
changeset
|
606 ngx_url_t u; |
581 | 607 ngx_http_core_loc_conf_t *clcf; |
608 | |
2392 | 609 if (mlcf->upstream.upstream) { |
581 | 610 return "is duplicate"; |
611 } | |
612 | |
613 value = cf->args->elts; | |
614 | |
807
3095bf59059b
now the "memcached_pass" directive uses ngx_parse_url()
Igor Sysoev <igor@sysoev.ru>
parents:
675
diff
changeset
|
615 ngx_memzero(&u, sizeof(ngx_url_t)); |
581 | 616 |
807
3095bf59059b
now the "memcached_pass" directive uses ngx_parse_url()
Igor Sysoev <igor@sysoev.ru>
parents:
675
diff
changeset
|
617 u.url = value[1]; |
884 | 618 u.no_resolve = 1; |
815
b630109560b7
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
807
diff
changeset
|
619 |
2392 | 620 mlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); |
621 if (mlcf->upstream.upstream == NULL) { | |
884 | 622 return NGX_CONF_ERROR; |
581 | 623 } |
624 | |
625 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
626 | |
627 clcf->handler = ngx_http_memcached_handler; | |
628 | |
629 if (clcf->name.data[clcf->name.len - 1] == '/') { | |
630 clcf->auto_redirect = 1; | |
631 } | |
632 | |
2392 | 633 mlcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key); |
1076 | 634 |
2392 | 635 if (mlcf->index == NGX_ERROR) { |
1076 | 636 return NGX_CONF_ERROR; |
637 } | |
638 | |
581 | 639 return NGX_CONF_OK; |
640 } |