Mercurial > hg > nginx
comparison src/http/modules/proxy/ngx_http_proxy_handler.c @ 170:c42be4185301
nginx-0.0.1-2003-11-03-01:56:18 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 02 Nov 2003 22:56:18 +0000 |
parents | edf29bb717da |
children | aff0e5d32af8 |
comparison
equal
deleted
inserted
replaced
169:edf29bb717da | 170:c42be4185301 |
---|---|
1 | 1 |
2 #include <ngx_config.h> | 2 #include <ngx_config.h> |
3 #include <ngx_core.h> | 3 #include <ngx_core.h> |
4 #include <ngx_event.h> | |
5 #include <ngx_event_connect.h> | |
6 #include <ngx_event_pipe.h> | |
7 #include <ngx_http.h> | 4 #include <ngx_http.h> |
8 #include <ngx_http_proxy_handler.h> | 5 #include <ngx_http_proxy_handler.h> |
9 | 6 |
10 | 7 |
11 | |
12 static int ngx_http_proxy_handler(ngx_http_request_t *r); | 8 static int ngx_http_proxy_handler(ngx_http_request_t *r); |
9 static int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p); | |
13 static void ngx_http_proxy_init_request(void *data); | 10 static void ngx_http_proxy_init_request(void *data); |
14 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); | 11 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); |
15 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev); | 12 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev); |
13 static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p); | |
16 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); | 14 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); |
17 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev); | 15 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev); |
18 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev); | 16 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev); |
19 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *); | 17 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *); |
20 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p); | 18 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p); |
21 static void ngx_http_proxy_process_body(ngx_event_t *ev); | 19 static void ngx_http_proxy_process_body(ngx_event_t *ev); |
22 | 20 static int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p); |
23 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); | 21 |
24 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type); | 22 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type); |
25 static int ngx_http_proxy_log_state(ngx_http_proxy_ctx_t *p, int status); | 23 static int ngx_http_proxy_log_state(ngx_http_proxy_ctx_t *p, int status); |
26 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc); | 24 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc); |
27 static void ngx_http_proxy_close_connection(ngx_connection_t *c); | 25 static void ngx_http_proxy_close_connection(ngx_connection_t *c); |
28 | 26 |
40 | 38 |
41 | 39 |
42 static ngx_conf_bitmask_t next_upstream_masks[] = { | 40 static ngx_conf_bitmask_t next_upstream_masks[] = { |
43 { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR }, | 41 { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR }, |
44 { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT }, | 42 { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT }, |
45 { ngx_string("http_header"), NGX_HTTP_PROXY_FT_HTTP_HEADER }, | 43 { ngx_string("invalid_header"), NGX_HTTP_PROXY_FT_INVALID_HEADER }, |
46 { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 }, | 44 { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 }, |
45 { ngx_string("http_404"), NGX_HTTP_PROXY_FT_HTTP_404 }, | |
46 { ngx_null_string, 0 } | |
47 }; | |
48 | |
49 | |
50 static ngx_conf_bitmask_t use_stale_masks[] = { | |
51 { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR }, | |
52 { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT }, | |
53 { ngx_string("invalid_header"), NGX_HTTP_PROXY_FT_INVALID_HEADER }, | |
54 { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 }, | |
55 { ngx_string("busy_lock"), NGX_HTTP_PROXY_FT_BUSY_LOCK }, | |
56 { ngx_string("max_waiting"), NGX_HTTP_PROXY_FT_MAX_WAITING }, | |
47 { ngx_null_string, 0 } | 57 { ngx_null_string, 0 } |
48 }; | 58 }; |
49 | 59 |
50 static ngx_command_t ngx_http_proxy_commands[] = { | 60 static ngx_command_t ngx_http_proxy_commands[] = { |
51 | 61 |
103 ngx_conf_set_size_slot, | 113 ngx_conf_set_size_slot, |
104 NGX_HTTP_LOC_CONF_OFFSET, | 114 NGX_HTTP_LOC_CONF_OFFSET, |
105 offsetof(ngx_http_proxy_loc_conf_t, busy_buffers_size), | 115 offsetof(ngx_http_proxy_loc_conf_t, busy_buffers_size), |
106 NULL }, | 116 NULL }, |
107 | 117 |
118 { ngx_string("proxy_cache_path"), | |
119 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, | |
120 ngx_conf_set_path_slot, | |
121 NGX_HTTP_LOC_CONF_OFFSET, | |
122 offsetof(ngx_http_proxy_loc_conf_t, cache_path), | |
123 NULL }, | |
124 | |
108 { ngx_string("proxy_temp_path"), | 125 { ngx_string("proxy_temp_path"), |
109 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, | 126 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, |
110 ngx_conf_set_path_slot, | 127 ngx_conf_set_path_slot, |
111 NGX_HTTP_LOC_CONF_OFFSET, | 128 NGX_HTTP_LOC_CONF_OFFSET, |
112 offsetof(ngx_http_proxy_loc_conf_t, temp_path), | 129 offsetof(ngx_http_proxy_loc_conf_t, temp_path), |
117 ngx_conf_set_size_slot, | 134 ngx_conf_set_size_slot, |
118 NGX_HTTP_LOC_CONF_OFFSET, | 135 NGX_HTTP_LOC_CONF_OFFSET, |
119 offsetof(ngx_http_proxy_loc_conf_t, temp_file_write_size), | 136 offsetof(ngx_http_proxy_loc_conf_t, temp_file_write_size), |
120 NULL }, | 137 NULL }, |
121 | 138 |
139 { ngx_string("proxy_cache"), | |
140 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
141 ngx_conf_set_flag_slot, | |
142 NGX_HTTP_LOC_CONF_OFFSET, | |
143 offsetof(ngx_http_proxy_loc_conf_t, cache), | |
144 NULL }, | |
145 | |
122 { ngx_string("proxy_pass_server"), | 146 { ngx_string("proxy_pass_server"), |
123 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | 147 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
124 ngx_conf_set_flag_slot, | 148 ngx_conf_set_flag_slot, |
125 NGX_HTTP_LOC_CONF_OFFSET, | 149 NGX_HTTP_LOC_CONF_OFFSET, |
126 offsetof(ngx_http_proxy_loc_conf_t, pass_server), | 150 offsetof(ngx_http_proxy_loc_conf_t, pass_server), |
130 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, | 154 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, |
131 ngx_conf_set_bitmask_slot, | 155 ngx_conf_set_bitmask_slot, |
132 NGX_HTTP_LOC_CONF_OFFSET, | 156 NGX_HTTP_LOC_CONF_OFFSET, |
133 offsetof(ngx_http_proxy_loc_conf_t, next_upstream), | 157 offsetof(ngx_http_proxy_loc_conf_t, next_upstream), |
134 &next_upstream_masks }, | 158 &next_upstream_masks }, |
159 | |
160 { ngx_string("proxy_use_stale"), | |
161 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, | |
162 ngx_conf_set_bitmask_slot, | |
163 NGX_HTTP_LOC_CONF_OFFSET, | |
164 offsetof(ngx_http_proxy_loc_conf_t, use_stale), | |
165 &use_stale_masks }, | |
135 | 166 |
136 ngx_null_command | 167 ngx_null_command |
137 }; | 168 }; |
138 | 169 |
139 | 170 |
170 "upstream sent invalid header", | 201 "upstream sent invalid header", |
171 "upstream sent too long header line" | 202 "upstream sent too long header line" |
172 }; | 203 }; |
173 | 204 |
174 | 205 |
175 static ngx_http_header_t headers_in[] = { | 206 ngx_http_header_t ngx_http_proxy_headers_in[] = { |
176 { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) }, | 207 { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) }, |
177 { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) }, | 208 { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) }, |
178 { ngx_string("Connection"), | 209 { ngx_string("Connection"), |
179 offsetof(ngx_http_proxy_headers_in_t, connection) }, | 210 offsetof(ngx_http_proxy_headers_in_t, connection) }, |
180 { ngx_string("Content-Type"), | 211 { ngx_string("Content-Type"), |
196 | 227 |
197 | 228 |
198 | 229 |
199 static int ngx_http_proxy_handler(ngx_http_request_t *r) | 230 static int ngx_http_proxy_handler(ngx_http_request_t *r) |
200 { | 231 { |
201 ngx_http_proxy_ctx_t *p; | 232 int rc; |
233 char *last; | |
234 ngx_http_cache_ctx_t *cctx; | |
235 ngx_http_proxy_ctx_t *p; | |
236 ngx_http_proxy_upstream_t *u; | |
202 | 237 |
203 ngx_http_create_ctx(r, p, ngx_http_proxy_module, | 238 ngx_http_create_ctx(r, p, ngx_http_proxy_module, |
204 sizeof(ngx_http_proxy_ctx_t), | 239 sizeof(ngx_http_proxy_ctx_t), |
205 NGX_HTTP_INTERNAL_SERVER_ERROR); | 240 NGX_HTTP_INTERNAL_SERVER_ERROR); |
206 | 241 |
207 p->lcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | 242 p->lcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
243 p->request = r; | |
244 | |
245 /* TODO: we currently support reverse proxy only */ | |
246 p->accel = 1; | |
247 | |
248 if (!p->lcf->cache || r->bypass_cache) { | |
249 return ngx_http_proxy_request_upstream(p); | |
250 } | |
251 | |
252 rc = ngx_http_proxy_get_cached_response(p); | |
253 | |
254 if (rc == NGX_OK) { | |
255 return ngx_http_proxy_process_cached_response(p); | |
256 } | |
257 | |
258 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { | |
259 return rc; | |
260 } | |
261 | |
262 if (rc == NGX_DECLINED || rc == NGX_STALE) { | |
263 return ngx_http_proxy_request_upstream(p); | |
264 } | |
265 | |
266 return NGX_DONE; | |
267 } | |
268 | |
269 | |
270 static int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p) | |
271 { | |
272 ngx_http_request_t *r; | |
273 | |
274 r = p->request; | |
275 | |
208 p->upstream.peers = p->lcf->peers; | 276 p->upstream.peers = p->lcf->peers; |
209 p->upstream.tries = p->lcf->peers->number; | 277 p->upstream.tries = p->lcf->peers->number; |
210 | 278 |
211 ngx_init_array(p->states, r->pool, p->upstream.tries, | 279 ngx_init_array(p->states, r->pool, p->upstream.tries, |
212 sizeof(ngx_http_proxy_state_t), | 280 sizeof(ngx_http_proxy_state_t), |
213 NGX_HTTP_INTERNAL_SERVER_ERROR); | 281 NGX_HTTP_INTERNAL_SERVER_ERROR); |
214 | 282 |
215 p->request = r; | |
216 p->method = r->method; | 283 p->method = r->method; |
217 | 284 |
218 /* TODO: we currently support reverse proxy only */ | 285 /* STUB */ p->cachable = p->lcf->cache; |
219 p->accel = 1; | |
220 | 286 |
221 if (r->headers_in.content_length_n > 0) { | 287 if (r->headers_in.content_length_n > 0) { |
222 ngx_test_null(r->temp_file, | 288 if (!(r->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)))) { |
223 ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)), | 289 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
224 NGX_HTTP_INTERNAL_SERVER_ERROR); | 290 } |
225 | 291 |
226 r->temp_file->file.fd = NGX_INVALID_FILE; | 292 r->temp_file->file.fd = NGX_INVALID_FILE; |
227 r->temp_file->file.log = r->connection->log; | 293 r->temp_file->file.log = r->connection->log; |
228 r->temp_file->path = *p->lcf->temp_path; | 294 r->temp_file->path = p->lcf->temp_path; |
229 r->temp_file->pool = r->pool; | 295 r->temp_file->pool = r->pool; |
230 r->temp_file->warn = "a client request body is buffered " | 296 r->temp_file->warn = "a client request body is buffered " |
231 "to a temporary file"; | 297 "to a temporary file"; |
232 /* STUB */ r->temp_file->persistent = 1; | 298 /* r->temp_file->persistent = 0; */ |
233 | 299 |
234 r->request_body_handler = ngx_http_proxy_init_request; | 300 r->request_body_handler = ngx_http_proxy_init_request; |
235 r->data = p; | 301 r->data = p; |
236 | 302 |
237 /* TODO: we ignore return value of ngx_http_read_client_request_body */ | 303 /* TODO: we ignore return value of ngx_http_read_client_request_body, |
304 probably we should not return anything */ | |
238 ngx_http_read_client_request_body(r, p->lcf->request_buffer_size); | 305 ngx_http_read_client_request_body(r, p->lcf->request_buffer_size); |
239 | 306 |
240 return NGX_DONE; | 307 return NGX_DONE; |
241 } | 308 } |
242 | 309 |
252 | 319 |
253 ngx_chain_t *cl; | 320 ngx_chain_t *cl; |
254 ngx_http_request_t *r; | 321 ngx_http_request_t *r; |
255 ngx_output_chain_ctx_t *octx; | 322 ngx_output_chain_ctx_t *octx; |
256 ngx_chain_writer_ctx_t *wctx; | 323 ngx_chain_writer_ctx_t *wctx; |
257 | |
258 | 324 |
259 r = p->request; | 325 r = p->request; |
260 | 326 |
261 ngx_log_debug(r->connection->log, "timer_set: %d" _ | 327 ngx_log_debug(r->connection->log, "timer_set: %d" _ |
262 r->connection->read->timer_set); | 328 r->connection->read->timer_set); |
281 p->saved_handler = r->connection->log->handler; | 347 p->saved_handler = r->connection->log->handler; |
282 r->connection->log->data = p; | 348 r->connection->log->data = p; |
283 r->connection->log->handler = ngx_http_proxy_log_error; | 349 r->connection->log->handler = ngx_http_proxy_log_error; |
284 p->action = "connecting to upstream"; | 350 p->action = "connecting to upstream"; |
285 | 351 |
286 octx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)); | 352 if (!(octx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)))) { |
287 if (octx == NULL) { | |
288 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | 353 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
289 return; | 354 return; |
290 } | 355 } |
291 | 356 |
292 p->output_chain_ctx = octx; | 357 p->output_chain_ctx = octx; |
293 | |
294 if (r->request_body_hunk) { | |
295 octx->free = ngx_alloc_chain_link(r->pool); | |
296 if (octx->free == NULL) { | |
297 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
298 } | |
299 octx->free->hunk = r->request_body_hunk; | |
300 octx->free->next = NULL; | |
301 } | |
302 | |
303 octx->sendfile = r->sendfile; | 358 octx->sendfile = r->sendfile; |
304 octx->pool = r->pool; | 359 octx->pool = r->pool; |
305 octx->bufs.num = 1; | 360 octx->bufs.num = 1; |
306 octx->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; | 361 octx->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; |
307 octx->output_filter = (ngx_output_chain_filter_pt) ngx_chain_writer; | 362 octx->output_filter = (ngx_output_chain_filter_pt) ngx_chain_writer; |
308 | 363 |
309 wctx = ngx_pcalloc(r->pool, sizeof(ngx_chain_writer_ctx_t)); | 364 if (!(wctx = ngx_palloc(r->pool, sizeof(ngx_chain_writer_ctx_t)))) { |
310 if (wctx == NULL) { | |
311 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | 365 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
312 return; | 366 return; |
313 } | 367 } |
314 | 368 |
315 octx->output_ctx = wctx; | 369 octx->output_ctx = wctx; |
316 wctx->pool = r->pool; | 370 wctx->pool = r->pool; |
317 wctx->last = &wctx->out; | 371 |
318 | 372 ngx_http_proxy_connect(p); |
319 ngx_http_proxy_send_request(p); | |
320 } | 373 } |
321 | 374 |
322 | 375 |
323 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) | 376 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) |
324 { | 377 { |
439 ngx_http_proxy_ctx_t *p; | 492 ngx_http_proxy_ctx_t *p; |
440 | 493 |
441 c = wev->data; | 494 c = wev->data; |
442 p = c->data; | 495 p = c->data; |
443 | 496 |
444 p->action = "sending request to upstream"; | |
445 | |
446 if (wev->timedout) { | 497 if (wev->timedout) { |
447 p->timedout = 1; | 498 p->action = "sending request to upstream"; |
448 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); | 499 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); |
449 return; | 500 return; |
450 } | 501 } |
451 | 502 |
452 ngx_http_proxy_send_request(p); | 503 ngx_http_proxy_send_request(p); |
453 | 504 } |
454 return; | 505 |
455 } | 506 |
456 | 507 static void ngx_http_proxy_dummy_handler(ngx_event_t *wev) |
457 | 508 { |
458 #if 0 | 509 ngx_log_debug(wev->log, "dummy handler"); |
459 | 510 } |
460 static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p) | 511 |
461 { | 512 |
462 int rc; | 513 static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p) |
463 ngx_chain_t *cl; | 514 { |
464 ngx_connection_t *c; | 515 int rc; |
465 | 516 ngx_chain_t *cl; |
466 for ( ;; ) { | 517 ngx_connection_t *c; |
467 p->action = "connecting to upstream"; | 518 ngx_http_request_t *r; |
468 | 519 ngx_output_chain_ctx_t *octx; |
469 rc = ngx_event_connect_peer(&p->upstream); | 520 |
470 | 521 p->action = "connecting to upstream"; |
471 if (rc == NGX_ERROR) { | 522 |
523 rc = ngx_event_connect_peer(&p->upstream); | |
524 | |
525 if (rc == NGX_ERROR) { | |
526 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
527 return; | |
528 } | |
529 | |
530 if (rc == NGX_CONNECT_ERROR) { | |
531 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); | |
532 return; | |
533 } | |
534 | |
535 p->upstream.connection->data = p; | |
536 p->upstream.connection->write->event_handler = | |
537 ngx_http_proxy_send_request_handler; | |
538 p->upstream.connection->read->event_handler = | |
539 ngx_http_proxy_process_upstream_status_line; | |
540 | |
541 r = p->request; | |
542 c = p->upstream.connection; | |
543 c->pool = r->pool; | |
544 c->read->log = c->write->log = c->log = r->connection->log; | |
545 | |
546 octx = p->output_chain_ctx; | |
547 | |
548 if (p->upstream.tries > 1 && p->request_sent) { | |
549 ngx_http_proxy_reinit_upstream(p); | |
550 } | |
551 | |
552 /* init or reinit ngx_output_chain() context */ | |
553 | |
554 if (r->request_body_hunk) { | |
555 if (!(octx->free = ngx_alloc_chain_link(r->pool))) { | |
472 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | 556 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
473 return NGX_DONE; | 557 return; |
474 } | 558 } |
475 | 559 |
476 if (rc == NGX_CONNECT_ERROR) { | 560 octx->free->hunk = r->request_body_hunk; |
477 ngx_event_connect_peer_failed(&p->upstream); | 561 octx->free->next = NULL; |
478 | 562 octx->hunks = 1; |
479 if (ngx_http_proxy_log_state(p, NGX_HTTP_BAD_GATEWAY) == NGX_ERROR) | 563 |
480 { | 564 r->request_body_hunk->pos = r->request_body_hunk->start; |
481 ngx_http_proxy_finalize_request(p, | 565 r->request_body_hunk->last = r->request_body_hunk->start; |
482 NGX_HTTP_INTERNAL_SERVER_ERROR); | 566 } |
483 return NGX_DONE; | 567 |
484 } | 568 p->request_sent = 0; |
485 | 569 |
486 if (p->upstream.tries == 0) { | 570 if (rc == NGX_AGAIN) { |
487 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY); | |
488 return NGX_DONE; | |
489 } | |
490 | |
491 continue; | |
492 } | |
493 | |
494 p->upstream.connection->data = p; | |
495 p->upstream.connection->write->event_handler = | |
496 ngx_http_proxy_send_request_handler; | |
497 p->upstream.connection->read->event_handler = | |
498 ngx_http_proxy_process_upstream_status_line; | |
499 | |
500 c = p->upstream.connection; | |
501 c->pool = p->request->pool; | |
502 c->read->log = c->write->log = c->log = p->request->connection->log; | |
503 | |
504 if (p->upstream.tries > 1 && p->request_sent) { | |
505 | |
506 /* reinit the request chain */ | |
507 | |
508 for (cl = p->request->request_hunks; cl; cl = cl->next) { | |
509 cl->hunk->pos = cl->hunk->start; | |
510 } | |
511 } | |
512 | |
513 p->request_sent = 0; | |
514 p->timedout = 0; | |
515 | |
516 if (rc == NGX_OK) { | |
517 return ngx_http_proxy_send_request0(p); | |
518 } | |
519 | |
520 /* rc == NGX_AGAIN */ | |
521 | |
522 ngx_add_timer(c->write, p->lcf->connect_timeout); | 571 ngx_add_timer(c->write, p->lcf->connect_timeout); |
523 | 572 return; |
524 return NGX_AGAIN; | 573 } |
525 } | 574 |
526 } | 575 /* rc == NGX_OK */ |
527 | 576 |
528 | 577 #if 1 /* test only */ |
529 static int ngx_http_proxy_send_request0(ngx_http_proxy_ctx_t *p) | 578 |
530 { | 579 if (c->read->ready) { |
580 /* post aio operation */ | |
581 ngx_http_proxy_process_upstream_status_line(c->read); | |
582 return; | |
583 } | |
584 #endif | |
585 | |
586 ngx_http_proxy_send_request(p); | |
587 } | |
588 | |
589 | |
590 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) | |
591 { | |
592 int rc; | |
531 ngx_connection_t *c; | 593 ngx_connection_t *c; |
532 ngx_chain_writer_ctx_t *wctx; | 594 ngx_chain_writer_ctx_t *wctx; |
533 | 595 |
534 c = p->upstream.connection; | 596 c = p->upstream.connection; |
535 | 597 |
598 #if (HAVE_KQUEUE) | |
599 | |
600 if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) | |
601 && !p->request_sent | |
602 && c->write->kq_eof) | |
603 { | |
604 ngx_log_error(NGX_LOG_ERR, c->log, c->write->kq_errno, | |
605 "connect() failed"); | |
606 | |
607 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); | |
608 return; | |
609 } | |
610 | |
611 #endif | |
612 | |
536 p->action = "sending request to upstream"; | 613 p->action = "sending request to upstream"; |
614 | |
537 wctx = p->output_chain_ctx->output_ctx; | 615 wctx = p->output_chain_ctx->output_ctx; |
616 wctx->out = NULL; | |
617 wctx->last = &wctx->out; | |
538 wctx->connection = c; | 618 wctx->connection = c; |
619 | |
539 rc = ngx_output_chain(p->output_chain_ctx, | 620 rc = ngx_output_chain(p->output_chain_ctx, |
540 !p->request_sent ? p->request->request_hunks: | 621 p->request_sent ? NULL : p->request->request_hunks); |
541 NULL); | 622 |
542 if (rc == NGX_ERROR) { | 623 if (rc == NGX_ERROR) { |
543 return ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); | 624 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); |
625 return; | |
544 } | 626 } |
545 | 627 |
546 p->request_sent = 1; | 628 p->request_sent = 1; |
547 | 629 |
548 if (c->write->timer_set) { | 630 if (c->write->timer_set) { |
556 { | 638 { |
557 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | 639 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
558 return; | 640 return; |
559 } | 641 } |
560 | 642 |
561 return NGX_AGAIN; | 643 return; |
562 } | 644 } |
563 | 645 |
564 /* rc == NGX_OK */ | 646 /* rc == NGX_OK */ |
565 | 647 |
648 if (c->tcp_nopush) { | |
649 if (ngx_tcp_push(c->fd) == NGX_ERROR) { | |
650 ngx_log_error(NGX_LOG_CRIT, c->log, | |
651 ngx_socket_errno, | |
652 ngx_tcp_push_n " failed"); | |
653 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
654 return; | |
655 } | |
656 | |
657 c->tcp_nopush = 0; | |
658 return; | |
659 } | |
660 | |
661 #if 0 | |
566 if (c->read->ready) { | 662 if (c->read->ready) { |
663 | |
567 /* post aio operation */ | 664 /* post aio operation */ |
665 | |
666 /* | |
667 * although we can post aio operation just in the end | |
668 * of ngx_http_proxy_connect() CHECK IT !!! | |
669 * it's better to do here because we postpone header buffer allocation | |
670 */ | |
671 | |
568 ngx_http_proxy_process_upstream_status_line(c->read); | 672 ngx_http_proxy_process_upstream_status_line(c->read); |
569 } | 673 return; |
570 | 674 } |
571 if (ngx_handle_level_write_event(c->write) == NGX_ERROR) { | |
572 ngx_http_proxy_finalize_request(p, | |
573 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
574 return; | |
575 } | |
576 | |
577 if (c->tcp_nopush) { | |
578 if (ngx_tcp_push(c->fd) == NGX_ERROR) { | |
579 ngx_log_error(NGX_LOG_CRIT, c->log, | |
580 ngx_socket_errno, | |
581 ngx_tcp_push_n " failed"); | |
582 ngx_http_proxy_finalize_request(p, | |
583 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
584 return; | |
585 } | |
586 | |
587 c->tcp_nopush = 0; | |
588 } | |
589 } | |
590 | |
591 return; | |
592 } | |
593 | |
594 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); | |
595 | |
596 return NGX_OK; | |
597 } | |
598 | |
599 | |
600 #endif | 675 #endif |
601 | 676 |
602 | 677 p->upstream.connection->write->event_handler = ngx_http_proxy_dummy_handler; |
603 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) | 678 |
604 { | 679 if (ngx_handle_level_write_event(c->write) == NGX_ERROR) { |
605 int rc; | 680 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
606 ngx_chain_t *cl; | 681 return; |
607 ngx_connection_t *c; | |
608 ngx_chain_writer_ctx_t *wctx; | |
609 | |
610 c = p->upstream.connection; | |
611 | |
612 for ( ;; ) { | |
613 | |
614 if (c) { | |
615 p->action = "sending request to upstream"; | |
616 wctx = p->output_chain_ctx->output_ctx; | |
617 wctx->connection = c; | |
618 rc = ngx_output_chain(p->output_chain_ctx, | |
619 !p->request_sent ? p->request->request_hunks: | |
620 NULL); | |
621 | |
622 if (rc != NGX_ERROR) { | |
623 p->request_sent = 1; | |
624 | |
625 if (c->write->timer_set) { | |
626 ngx_del_timer(c->write); | |
627 } | |
628 | |
629 if (rc == NGX_AGAIN) { | |
630 ngx_add_timer(c->write, p->lcf->send_timeout); | |
631 | |
632 if (ngx_handle_write_event(c->write, /* STUB: lowat */ 0) | |
633 == NGX_ERROR) | |
634 { | |
635 ngx_http_proxy_finalize_request(p, | |
636 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
637 return; | |
638 } | |
639 | |
640 } else { | |
641 | |
642 /* rc == NGX_OK */ | |
643 | |
644 if (c->read->ready) { | |
645 /* post aio operation */ | |
646 ngx_http_proxy_process_upstream_status_line(c->read); | |
647 } | |
648 | |
649 if (ngx_handle_level_write_event(c->write) == NGX_ERROR) { | |
650 ngx_http_proxy_finalize_request(p, | |
651 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
652 return; | |
653 } | |
654 | |
655 if (c->tcp_nopush) { | |
656 if (ngx_tcp_push(c->fd) == NGX_ERROR) { | |
657 ngx_log_error(NGX_LOG_CRIT, c->log, | |
658 ngx_socket_errno, | |
659 ngx_tcp_push_n " failed"); | |
660 ngx_http_proxy_finalize_request(p, | |
661 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
662 return; | |
663 } | |
664 c->tcp_nopush = 0; | |
665 } | |
666 } | |
667 | |
668 return; | |
669 } | |
670 | |
671 ngx_event_connect_peer_failed(&p->upstream); | |
672 ngx_http_proxy_close_connection(c); | |
673 | |
674 if (p->upstream.tries == 0 | |
675 || !(p->lcf->next_upstream & NGX_HTTP_PROXY_FT_ERROR)) | |
676 { | |
677 ngx_http_proxy_finalize_request(p, | |
678 p->timedout ? NGX_HTTP_GATEWAY_TIME_OUT: | |
679 NGX_HTTP_BAD_GATEWAY); | |
680 return; | |
681 } | |
682 | |
683 if (!p->fatal_error) { | |
684 ngx_http_proxy_send_request(p); | |
685 return; | |
686 } | |
687 } | |
688 | |
689 for ( ;; ) { | |
690 p->action = "connecting to upstream"; | |
691 | |
692 rc = ngx_event_connect_peer(&p->upstream); | |
693 | |
694 if (rc == NGX_ERROR) { | |
695 ngx_http_proxy_finalize_request(p, | |
696 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
697 return; | |
698 } | |
699 | |
700 if (rc == NGX_CONNECT_ERROR) { | |
701 ngx_event_connect_peer_failed(&p->upstream); | |
702 | |
703 if (p->upstream.tries == 0) { | |
704 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY); | |
705 return; | |
706 } | |
707 | |
708 continue; | |
709 } | |
710 | |
711 p->upstream.connection->data = p; | |
712 p->upstream.connection->write->event_handler = | |
713 ngx_http_proxy_send_request_handler; | |
714 p->upstream.connection->read->event_handler = | |
715 ngx_http_proxy_process_upstream_status_line; | |
716 | |
717 c = p->upstream.connection; | |
718 c->pool = p->request->pool; | |
719 c->read->log = c->write->log = c->log = p->request->connection->log; | |
720 | |
721 if (p->upstream.tries > 1 && p->request_sent) { | |
722 | |
723 /* reinit the request chain */ | |
724 | |
725 for (cl = p->request->request_hunks; cl; cl = cl->next) { | |
726 cl->hunk->pos = cl->hunk->start; | |
727 } | |
728 } | |
729 | |
730 p->request_sent = 0; | |
731 p->timedout = 0; | |
732 | |
733 if (rc == NGX_OK) { | |
734 break; | |
735 } | |
736 | |
737 /* rc == NGX_AGAIN */ | |
738 | |
739 ngx_add_timer(c->write, p->lcf->connect_timeout); | |
740 | |
741 return; | |
742 } | |
743 } | 682 } |
744 } | 683 } |
745 | 684 |
746 | 685 |
747 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev) | 686 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev) |
751 ngx_connection_t *c; | 690 ngx_connection_t *c; |
752 ngx_http_proxy_ctx_t *p; | 691 ngx_http_proxy_ctx_t *p; |
753 | 692 |
754 c = rev->data; | 693 c = rev->data; |
755 p = c->data; | 694 p = c->data; |
756 | |
757 p->action = "reading upstream status line"; | 695 p->action = "reading upstream status line"; |
758 | 696 |
759 ngx_log_debug(rev->log, "http proxy process status line"); | 697 ngx_log_debug(rev->log, "http proxy process status line"); |
760 | 698 |
761 if (rev->timedout) { | 699 if (rev->timedout) { |
762 p->timedout = 1; | |
763 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); | 700 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); |
764 return; | 701 return; |
765 } | 702 } |
766 | 703 |
767 if (p->header_in == NULL) { | 704 if (p->header_in == NULL) { |
770 if (p->header_in == NULL) { | 707 if (p->header_in == NULL) { |
771 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | 708 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
772 return; | 709 return; |
773 } | 710 } |
774 p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; | 711 p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; |
712 | |
713 if (p->cache) { | |
714 p->header_in->pos += p->cache->ctx.header.size; | |
715 p->header_in->last = p->header_in->pos; | |
716 } | |
775 } | 717 } |
776 | 718 |
777 n = ngx_http_proxy_read_upstream_header(p); | 719 n = ngx_http_proxy_read_upstream_header(p); |
778 | 720 |
779 if (n == NGX_ERROR) { | 721 if (n == NGX_AGAIN) { |
722 return; | |
723 } | |
724 | |
725 if (n == 0) { | |
726 ngx_log_error(NGX_LOG_ERR, rev->log, 0, | |
727 "upstream prematurely closed connection"); | |
728 } | |
729 | |
730 if (n == NGX_ERROR || n == 0) { | |
780 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); | 731 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); |
781 return; | 732 return; |
782 } | 733 } |
783 | 734 |
784 if (n == NGX_AGAIN) { | 735 p->upstream.cached = 0; |
785 return; | |
786 } | |
787 | 736 |
788 rc = ngx_http_proxy_parse_status_line(p); | 737 rc = ngx_http_proxy_parse_status_line(p); |
789 | 738 |
790 if (rc == NGX_AGAIN) { | 739 if (rc == NGX_AGAIN) { |
791 if (p->header_in->pos == p->header_in->last) { | 740 if (p->header_in->pos == p->header_in->last) { |
792 ngx_log_error(NGX_LOG_ERR, rev->log, 0, | 741 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
793 "upstream sent too long status line"); | 742 "upstream sent too long status line"); |
794 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER); | 743 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER); |
795 } | 744 } |
796 | |
797 return; | 745 return; |
798 } | 746 } |
799 | 747 |
800 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { | 748 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { |
801 ngx_log_error(NGX_LOG_ERR, rev->log, 0, | 749 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
802 "upstream sent no valid HTTP/1.0 header"); | 750 "upstream sent no valid HTTP/1.0 header"); |
803 | 751 |
804 if (p->accel) { | 752 if (p->accel) { |
805 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER); | 753 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER); |
806 | 754 |
807 } else { | 755 } else { |
808 p->request->http_version = NGX_HTTP_VERSION_9; | 756 p->request->http_version = NGX_HTTP_VERSION_9; |
809 p->status = NGX_HTTP_OK; | 757 p->status = NGX_HTTP_OK; |
810 ngx_http_proxy_send_response(p); | 758 ngx_http_proxy_send_response(p); |
813 return; | 761 return; |
814 } | 762 } |
815 | 763 |
816 /* rc == NGX_OK */ | 764 /* rc == NGX_OK */ |
817 | 765 |
818 if (p->status == NGX_HTTP_INTERNAL_SERVER_ERROR | 766 if (p->status == NGX_HTTP_INTERNAL_SERVER_ERROR) { |
819 && p->upstream.tries > 1 | 767 |
820 && (p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_500)) | 768 if (p->upstream.tries > 1 |
821 { | 769 && (p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_500)) |
822 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_500); | 770 { |
823 return; | 771 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_500); |
772 return; | |
773 } | |
774 | |
775 if (p->upstream.tries == 0 | |
776 && p->stale | |
777 && (p->lcf->use_stale & NGX_HTTP_PROXY_FT_HTTP_500)) | |
778 { | |
779 /* | |
780 * TODO: use stale cached response if it exists and enabled | |
781 */ | |
782 | |
783 return; | |
784 } | |
824 } | 785 } |
825 | 786 |
826 p->status_line.len = p->status_end - p->status_start; | 787 p->status_line.len = p->status_end - p->status_start; |
827 p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1); | 788 p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1); |
828 if (p->status_line.data == NULL) { | 789 if (p->status_line.data == NULL) { |
840 p->headers_in.headers = ngx_create_table(p->request->pool, 20); | 801 p->headers_in.headers = ngx_create_table(p->request->pool, 20); |
841 } | 802 } |
842 | 803 |
843 c->read->event_handler = ngx_http_proxy_process_upstream_headers; | 804 c->read->event_handler = ngx_http_proxy_process_upstream_headers; |
844 ngx_http_proxy_process_upstream_headers(rev); | 805 ngx_http_proxy_process_upstream_headers(rev); |
845 | |
846 return; | |
847 } | 806 } |
848 | 807 |
849 | 808 |
850 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev) | 809 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev) |
851 { | 810 { |
857 ngx_http_proxy_ctx_t *p; | 816 ngx_http_proxy_ctx_t *p; |
858 | 817 |
859 c = rev->data; | 818 c = rev->data; |
860 p = c->data; | 819 p = c->data; |
861 r = p->request; | 820 r = p->request; |
862 | |
863 p->action = "reading upstream headers"; | 821 p->action = "reading upstream headers"; |
864 | 822 |
865 ngx_log_debug(rev->log, "http proxy process header line"); | 823 ngx_log_debug(rev->log, "http proxy process header line"); |
866 | 824 |
867 if (rev->timedout) { | 825 if (rev->timedout) { |
868 p->timedout = 1; | |
869 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); | 826 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); |
870 return; | 827 return; |
871 } | 828 } |
872 | 829 |
873 rc = NGX_AGAIN; | 830 rc = NGX_AGAIN; |
874 | 831 |
875 for ( ;; ) { | 832 for ( ;; ) { |
876 if (rc == NGX_AGAIN) { | 833 if (rc == NGX_AGAIN) { |
877 n = ngx_http_proxy_read_upstream_header(p); | 834 n = ngx_http_proxy_read_upstream_header(p); |
878 | 835 |
879 if (n == NGX_ERROR) { | 836 if (n == 0) { |
837 ngx_log_error(NGX_LOG_ERR, rev->log, 0, | |
838 "upstream prematurely closed connection"); | |
839 } | |
840 | |
841 if (n == NGX_ERROR || n == 0) { | |
880 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); | 842 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); |
881 return; | 843 return; |
882 } | 844 } |
883 | 845 |
884 if (n == NGX_AGAIN) { | 846 if (n == NGX_AGAIN) { |
890 | 852 |
891 if (rc == NGX_OK) { | 853 if (rc == NGX_OK) { |
892 | 854 |
893 /* a header line has been parsed successfully */ | 855 /* a header line has been parsed successfully */ |
894 | 856 |
895 if (!(h = ngx_http_add_header(&p->headers_in, headers_in))) { | 857 h = ngx_http_add_header(&p->headers_in, ngx_http_proxy_headers_in); |
858 if (h == NULL) { | |
896 ngx_http_proxy_finalize_request(p, | 859 ngx_http_proxy_finalize_request(p, |
897 NGX_HTTP_INTERNAL_SERVER_ERROR); | 860 NGX_HTTP_INTERNAL_SERVER_ERROR); |
898 return; | 861 return; |
899 } | 862 } |
900 | 863 |
911 | 874 |
912 h->value.data = h->key.data + h->key.len + 1; | 875 h->value.data = h->key.data + h->key.len + 1; |
913 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | 876 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); |
914 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | 877 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); |
915 | 878 |
916 for (i = 0; headers_in[i].name.len != 0; i++) { | 879 for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) { |
917 if (headers_in[i].name.len != h->key.len) { | 880 if (ngx_http_proxy_headers_in[i].name.len != h->key.len) { |
918 continue; | 881 continue; |
919 } | 882 } |
920 | 883 |
921 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) { | 884 if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data, |
922 *((ngx_table_elt_t **) | 885 h->key.data) == 0) |
923 ((char *) &p->headers_in + headers_in[i].offset)) = h; | 886 { |
887 *((ngx_table_elt_t **) ((char *) &p->headers_in | |
888 + ngx_http_proxy_headers_in[i].offset)) = h; | |
924 break; | 889 break; |
925 } | 890 } |
926 } | 891 } |
927 | 892 |
928 ngx_log_debug(c->log, "HTTP proxy header: '%s: %s'" _ | 893 ngx_log_debug(c->log, "HTTP proxy header: '%s: %s'" _ |
935 /* a whole header has been parsed successfully */ | 900 /* a whole header has been parsed successfully */ |
936 | 901 |
937 ngx_log_debug(c->log, "HTTP header done"); | 902 ngx_log_debug(c->log, "HTTP header done"); |
938 | 903 |
939 ngx_http_proxy_send_response(p); | 904 ngx_http_proxy_send_response(p); |
940 | |
941 return; | 905 return; |
942 | 906 |
943 } else if (rc != NGX_AGAIN) { | 907 } else if (rc != NGX_AGAIN) { |
944 | 908 |
945 /* there was error while a header line parsing */ | 909 /* there was error while a header line parsing */ |
946 | 910 |
947 ngx_log_error(NGX_LOG_ERR, rev->log, 0, | 911 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
948 upstream_header_errors[rc - NGX_HTTP_PARSE_HEADER_ERROR]); | 912 upstream_header_errors[rc - NGX_HTTP_PARSE_HEADER_ERROR]); |
949 | 913 |
950 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER); | 914 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER); |
951 return; | 915 return; |
952 } | 916 } |
953 | 917 |
954 /* rc == NGX_AGAIN: a header line parsing is still not complete */ | 918 /* rc == NGX_AGAIN: a header line parsing is still not complete */ |
955 | 919 |
956 if (p->header_in->last == p->header_in->end) { | 920 if (p->header_in->last == p->header_in->end) { |
957 ngx_log_error(NGX_LOG_ERR, rev->log, 0, | 921 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
958 "upstream sent too big header"); | 922 "upstream sent too big header"); |
959 | 923 |
960 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER); | 924 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER); |
961 return; | 925 return; |
962 } | 926 } |
963 } | 927 } |
964 } | 928 } |
965 | 929 |
1006 } | 970 } |
1007 | 971 |
1008 | 972 |
1009 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p) | 973 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p) |
1010 { | 974 { |
1011 int rc, i; | 975 int rc, i; |
1012 ngx_table_elt_t *ho, *h; | 976 ngx_table_elt_t *ho, *h; |
1013 ngx_event_pipe_t *ep; | 977 ngx_event_pipe_t *ep; |
1014 ngx_http_request_t *r; | 978 ngx_http_request_t *r; |
1015 ngx_http_core_loc_conf_t *clcf; | 979 ngx_http_bin_cache_t *header; |
980 ngx_http_core_loc_conf_t *clcf; | |
1016 | 981 |
1017 r = p->request; | 982 r = p->request; |
1018 | 983 |
1019 r->headers_out.status = p->status; | 984 r->headers_out.status = p->status; |
1020 | 985 |
986 #if 0 | |
1021 r->headers_out.content_length_n = -1; | 987 r->headers_out.content_length_n = -1; |
1022 r->headers_out.content_length = NULL; | 988 r->headers_out.content_length = NULL; |
989 #endif | |
1023 | 990 |
1024 /* copy an upstream header to r->headers_out */ | 991 /* copy an upstream header to r->headers_out */ |
1025 | 992 |
1026 h = p->headers_in.headers->elts; | 993 if (ngx_http_proxy_copy_header(p, &p->headers_in) == NGX_ERROR) { |
1027 for (i = 0; i < p->headers_in.headers->nelts; i++) { | 994 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
1028 | 995 return; |
1029 if (&h[i] == p->headers_in.connection) { | 996 } |
1030 continue; | |
1031 } | |
1032 | |
1033 if (p->accel) { | |
1034 if (&h[i] == p->headers_in.date | |
1035 || &h[i] == p->headers_in.accept_ranges) { | |
1036 continue; | |
1037 } | |
1038 | |
1039 if (&h[i] == p->headers_in.server && !p->lcf->pass_server) { | |
1040 continue; | |
1041 } | |
1042 } | |
1043 | |
1044 if (&h[i] == p->headers_in.content_type) { | |
1045 r->headers_out.content_type = &h[i]; | |
1046 r->headers_out.content_type->key.len = 0; | |
1047 continue; | |
1048 } | |
1049 | |
1050 if (!(ho = ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) | |
1051 { | |
1052 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1053 return; | |
1054 } | |
1055 | |
1056 *ho = h[i]; | |
1057 | |
1058 /* | |
1059 * ngx_http_header_filter() output the following headers | |
1060 * from r->headers_out.headers if they are set: | |
1061 * r->headers_out.server, | |
1062 * r->headers_out.date, | |
1063 * r->headers_out.content_length | |
1064 */ | |
1065 | |
1066 if (&h[i] == p->headers_in.server) { | |
1067 r->headers_out.server = ho; | |
1068 continue; | |
1069 } | |
1070 | |
1071 if (&h[i] == p->headers_in.date) { | |
1072 r->headers_out.date = ho; | |
1073 continue; | |
1074 } | |
1075 | |
1076 if (&h[i] == p->headers_in.content_length) { | |
1077 r->headers_out.content_length = ho; | |
1078 r->headers_out.content_length_n = ngx_atoi(ho->value.data, | |
1079 ho->value.len); | |
1080 continue; | |
1081 } | |
1082 } | |
1083 | |
1084 | 997 |
1085 /* TODO: preallocate event_pipe hunks, look "Content-Length" */ | 998 /* TODO: preallocate event_pipe hunks, look "Content-Length" */ |
1086 | 999 |
1087 rc = ngx_http_send_header(r); | 1000 rc = ngx_http_send_header(r); |
1088 | 1001 |
1089 p->header_sent = 1; | 1002 p->header_sent = 1; |
1003 | |
1004 if (p->cache) { | |
1005 header = (ngx_http_bin_cache_t *) p->header_in->start; | |
1006 header->type = 0x42424242; /* "BBBB" */ | |
1007 header->header.length = r->headers_out.content_length_n; | |
1008 header->key_len = p->cache->ctx.key.len; | |
1009 ngx_memcpy(&header->key, p->cache->ctx.key.data, header->key_len); | |
1010 header->key[header->key_len] = LF; | |
1011 } | |
1090 | 1012 |
1091 ep = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); | 1013 ep = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); |
1092 if (ep == NULL) { | 1014 if (ep == NULL) { |
1093 ngx_http_proxy_finalize_request(p, 0); | 1015 ngx_http_proxy_finalize_request(p, 0); |
1094 return; | 1016 return; |
1103 ep->busy_size = p->lcf->busy_buffers_size; | 1025 ep->busy_size = p->lcf->busy_buffers_size; |
1104 ep->upstream = p->upstream.connection; | 1026 ep->upstream = p->upstream.connection; |
1105 ep->downstream = r->connection; | 1027 ep->downstream = r->connection; |
1106 ep->pool = r->pool; | 1028 ep->pool = r->pool; |
1107 ep->log = r->connection->log; | 1029 ep->log = r->connection->log; |
1108 ep->temp_path = p->lcf->temp_path; | 1030 |
1109 | 1031 if (!(ep->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)))) { |
1110 ep->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); | |
1111 if (ep->temp_file == NULL) { | |
1112 ngx_http_proxy_finalize_request(p, 0); | 1032 ngx_http_proxy_finalize_request(p, 0); |
1113 return; | 1033 return; |
1114 } | 1034 } |
1115 | 1035 |
1116 ep->temp_file->fd = NGX_INVALID_FILE; | 1036 ep->temp_file->file.fd = NGX_INVALID_FILE; |
1117 ep->temp_file->log = r->connection->log; | 1037 ep->temp_file->file.log = r->connection->log; |
1038 ep->temp_file->path = p->lcf->temp_path; | |
1039 ep->temp_file->pool = r->pool; | |
1040 ep->temp_file->warn = "an upstream response is buffered " | |
1041 "to a temporary file"; | |
1118 | 1042 |
1119 ep->max_temp_file_size = p->lcf->max_temp_file_size; | 1043 ep->max_temp_file_size = p->lcf->max_temp_file_size; |
1120 ep->temp_file_write_size = p->lcf->temp_file_write_size; | 1044 ep->temp_file_write_size = p->lcf->temp_file_write_size; |
1121 ep->temp_file_warn = "an upstream response is buffered " | |
1122 "to a temporary file"; | |
1123 | 1045 |
1124 ep->preread_hunks = ngx_alloc_chain_link(r->pool); | 1046 ep->preread_hunks = ngx_alloc_chain_link(r->pool); |
1125 if (ep->preread_hunks == NULL) { | 1047 if (ep->preread_hunks == NULL) { |
1126 ngx_http_proxy_finalize_request(p, 0); | 1048 ngx_http_proxy_finalize_request(p, 0); |
1127 return; | 1049 return; |
1128 } | 1050 } |
1129 ep->preread_hunks->hunk = p->header_in; | 1051 ep->preread_hunks->hunk = p->header_in; |
1130 ep->preread_hunks->next = NULL; | 1052 ep->preread_hunks->next = NULL; |
1053 p->header_in->type |= NGX_HUNK_PREREAD; | |
1131 | 1054 |
1132 ep->preread_size = p->header_in->last - p->header_in->pos; | 1055 ep->preread_size = p->header_in->last - p->header_in->pos; |
1133 | 1056 |
1134 if (ngx_event_flags & NGX_USE_AIO_EVENT) { | 1057 if (ngx_event_flags & NGX_USE_AIO_EVENT) { |
1135 | 1058 |
1144 * event_pipe would do p->header_in->last += ep->preread_size | 1067 * event_pipe would do p->header_in->last += ep->preread_size |
1145 * as though these bytes were read. | 1068 * as though these bytes were read. |
1146 */ | 1069 */ |
1147 p->header_in->last = p->header_in->pos; | 1070 p->header_in->last = p->header_in->pos; |
1148 | 1071 |
1149 /* STUB */ ep->cachable = 0; | 1072 ep->cachable = p->cachable; |
1150 | 1073 |
1151 if (p->lcf->cyclic_temp_file) { | 1074 if (p->lcf->cyclic_temp_file) { |
1152 | 1075 |
1153 /* | 1076 /* |
1154 * we need to disable the use of sendfile() if we use cyclic temp file | 1077 * we need to disable the use of sendfile() if we use cyclic temp file |
1224 } | 1147 } |
1225 } | 1148 } |
1226 | 1149 |
1227 if (p->upstream.connection) { | 1150 if (p->upstream.connection) { |
1228 if (ep->upstream_done) { | 1151 if (ep->upstream_done) { |
1229 /* TODO: update cache */ | 1152 if (ngx_http_proxy_update_cache(p) == NGX_ERROR) { |
1153 ngx_http_proxy_finalize_request(p, 0); | |
1154 return; | |
1155 } | |
1230 | 1156 |
1231 } else if (ep->upstream_eof) { | 1157 } else if (ep->upstream_eof) { |
1158 | |
1232 /* TODO: check length & update cache */ | 1159 /* TODO: check length & update cache */ |
1160 | |
1161 if (ngx_http_proxy_update_cache(p) == NGX_ERROR) { | |
1162 ngx_http_proxy_finalize_request(p, 0); | |
1163 return; | |
1164 } | |
1233 } | 1165 } |
1234 | 1166 |
1235 if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) { | 1167 if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) { |
1236 ngx_http_proxy_close_connection(p->upstream.connection); | 1168 ngx_http_proxy_close_connection(p->upstream.connection); |
1237 p->upstream.connection = NULL; | 1169 p->upstream.connection = NULL; |
1257 | 1189 |
1258 return; | 1190 return; |
1259 } | 1191 } |
1260 | 1192 |
1261 | 1193 |
1262 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p) | 1194 static int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p) |
1263 { | 1195 { |
1264 char ch; | 1196 if (p->cache == NULL) { |
1265 char *pos; | |
1266 enum { | |
1267 sw_start = 0, | |
1268 sw_H, | |
1269 sw_HT, | |
1270 sw_HTT, | |
1271 sw_HTTP, | |
1272 sw_first_major_digit, | |
1273 sw_major_digit, | |
1274 sw_first_minor_digit, | |
1275 sw_minor_digit, | |
1276 sw_status, | |
1277 sw_space_after_status, | |
1278 sw_status_text, | |
1279 sw_almost_done, | |
1280 sw_done | |
1281 } state; | |
1282 | |
1283 state = p->state; | |
1284 pos = p->header_in->pos; | |
1285 | |
1286 while (pos < p->header_in->last && state < sw_done) { | |
1287 ch = *pos++; | |
1288 | |
1289 switch (state) { | |
1290 | |
1291 /* "HTTP/" */ | |
1292 case sw_start: | |
1293 switch (ch) { | |
1294 case 'H': | |
1295 state = sw_H; | |
1296 break; | |
1297 default: | |
1298 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1299 } | |
1300 break; | |
1301 | |
1302 case sw_H: | |
1303 switch (ch) { | |
1304 case 'T': | |
1305 state = sw_HT; | |
1306 break; | |
1307 default: | |
1308 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1309 } | |
1310 break; | |
1311 | |
1312 case sw_HT: | |
1313 switch (ch) { | |
1314 case 'T': | |
1315 state = sw_HTT; | |
1316 break; | |
1317 default: | |
1318 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1319 } | |
1320 break; | |
1321 | |
1322 case sw_HTT: | |
1323 switch (ch) { | |
1324 case 'P': | |
1325 state = sw_HTTP; | |
1326 break; | |
1327 default: | |
1328 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1329 } | |
1330 break; | |
1331 | |
1332 case sw_HTTP: | |
1333 switch (ch) { | |
1334 case '/': | |
1335 state = sw_first_major_digit; | |
1336 break; | |
1337 default: | |
1338 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1339 } | |
1340 break; | |
1341 | |
1342 /* the first digit of major HTTP version */ | |
1343 case sw_first_major_digit: | |
1344 if (ch < '1' || ch > '9') { | |
1345 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1346 } | |
1347 | |
1348 state = sw_major_digit; | |
1349 break; | |
1350 | |
1351 /* the major HTTP version or dot */ | |
1352 case sw_major_digit: | |
1353 if (ch == '.') { | |
1354 state = sw_first_minor_digit; | |
1355 break; | |
1356 } | |
1357 | |
1358 if (ch < '0' || ch > '9') { | |
1359 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1360 } | |
1361 | |
1362 break; | |
1363 | |
1364 /* the first digit of minor HTTP version */ | |
1365 case sw_first_minor_digit: | |
1366 if (ch < '0' || ch > '9') { | |
1367 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1368 } | |
1369 | |
1370 state = sw_minor_digit; | |
1371 break; | |
1372 | |
1373 /* the minor HTTP version or the end of the request line */ | |
1374 case sw_minor_digit: | |
1375 if (ch == ' ') { | |
1376 state = sw_status; | |
1377 break; | |
1378 } | |
1379 | |
1380 if (ch < '0' || ch > '9') { | |
1381 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1382 } | |
1383 | |
1384 break; | |
1385 | |
1386 /* HTTP status code */ | |
1387 case sw_status: | |
1388 if (ch < '0' || ch > '9') { | |
1389 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1390 } | |
1391 | |
1392 p->status = p->status * 10 + ch - '0'; | |
1393 | |
1394 if (++p->status_count == 3) { | |
1395 state = sw_space_after_status; | |
1396 p->status_start = pos - 3; | |
1397 } | |
1398 | |
1399 break; | |
1400 | |
1401 /* space or end of line */ | |
1402 case sw_space_after_status: | |
1403 switch (ch) { | |
1404 case ' ': | |
1405 state = sw_status_text; | |
1406 break; | |
1407 case CR: | |
1408 state = sw_almost_done; | |
1409 break; | |
1410 case LF: | |
1411 state = sw_done; | |
1412 break; | |
1413 default: | |
1414 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1415 } | |
1416 break; | |
1417 | |
1418 /* any text until end of line */ | |
1419 case sw_status_text: | |
1420 switch (ch) { | |
1421 case CR: | |
1422 state = sw_almost_done; | |
1423 | |
1424 break; | |
1425 case LF: | |
1426 state = sw_done; | |
1427 break; | |
1428 } | |
1429 break; | |
1430 | |
1431 /* end of request line */ | |
1432 case sw_almost_done: | |
1433 p->status_end = pos - 2; | |
1434 switch (ch) { | |
1435 case LF: | |
1436 state = sw_done; | |
1437 break; | |
1438 default: | |
1439 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | |
1440 } | |
1441 break; | |
1442 } | |
1443 } | |
1444 | |
1445 p->header_in->pos = pos; | |
1446 | |
1447 if (state == sw_done) { | |
1448 if (p->status_end == NULL) { | |
1449 p->status_end = pos - 1; | |
1450 } | |
1451 | |
1452 p->state = sw_start; | |
1453 return NGX_OK; | 1197 return NGX_OK; |
1454 } | 1198 } |
1455 | 1199 |
1456 p->state = state; | 1200 return ngx_http_cache_update_file(p->request, &p->cache->ctx, |
1457 return NGX_AGAIN; | 1201 &p->event_pipe->temp_file->file.name); |
1458 } | 1202 } |
1459 | 1203 |
1460 | 1204 |
1461 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type) | 1205 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type) |
1462 { | 1206 { |
1463 int status; | 1207 int status; |
1464 | 1208 |
1465 ngx_event_connect_peer_failed(&p->upstream); | 1209 ngx_log_debug(p->request->connection->log, "next upstream: %d" _ ft_type); |
1466 | 1210 |
1467 if (p->timedout) { | 1211 if (ft_type != NGX_HTTP_PROXY_FT_HTTP_404) { |
1212 ngx_event_connect_peer_failed(&p->upstream); | |
1213 } | |
1214 | |
1215 if (ft_type == NGX_HTTP_PROXY_FT_TIMEOUT) { | |
1468 ngx_log_error(NGX_LOG_ERR, p->request->connection->log, NGX_ETIMEDOUT, | 1216 ngx_log_error(NGX_LOG_ERR, p->request->connection->log, NGX_ETIMEDOUT, |
1469 "upstream timed out"); | 1217 "upstream timed out"); |
1218 } | |
1219 | |
1220 if (p->upstream.cached && ft_type == NGX_HTTP_PROXY_FT_ERROR) { | |
1221 status = 0; | |
1222 | |
1223 } else { | |
1224 switch(ft_type) { | |
1225 case NGX_HTTP_PROXY_FT_TIMEOUT: | |
1226 status = NGX_HTTP_GATEWAY_TIME_OUT; | |
1227 break; | |
1228 | |
1229 case NGX_HTTP_PROXY_FT_HTTP_500: | |
1230 status = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1231 break; | |
1232 | |
1233 case NGX_HTTP_PROXY_FT_HTTP_404: | |
1234 status = NGX_HTTP_NOT_FOUND; | |
1235 break; | |
1236 | |
1237 /* | |
1238 * NGX_HTTP_PROXY_FT_BUSY_LOCK and NGX_HTTP_PROXY_FT_MAX_WAITING | |
1239 * never reach here | |
1240 */ | |
1241 | |
1242 default: | |
1243 status = NGX_HTTP_BAD_GATEWAY; | |
1244 } | |
1470 } | 1245 } |
1471 | 1246 |
1472 if (p->upstream.connection) { | 1247 if (p->upstream.connection) { |
1473 ngx_http_proxy_close_connection(p->upstream.connection); | 1248 ngx_http_proxy_close_connection(p->upstream.connection); |
1474 p->upstream.connection = NULL; | 1249 p->upstream.connection = NULL; |
1475 } | 1250 } |
1476 | 1251 |
1477 if (ft_type == NGX_HTTP_PROXY_FT_TIMEOUT) { | 1252 if (status) { |
1478 status = NGX_HTTP_GATEWAY_TIME_OUT; | 1253 if (ngx_http_proxy_log_state(p, status) == NGX_ERROR) { |
1479 | 1254 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
1480 } else { | 1255 return; |
1481 status = NGX_HTTP_BAD_GATEWAY; | 1256 } |
1482 } | 1257 |
1483 | 1258 if (p->upstream.tries == 0 || !(p->lcf->next_upstream & ft_type)) { |
1484 if (ngx_http_proxy_log_state(p, status) == NGX_ERROR) { | 1259 |
1485 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | 1260 if (p->stale && (p->lcf->use_stale & ft_type)) { |
1486 return; | 1261 /* |
1487 } | 1262 * TODO: use stale cached response if it exists and enabled |
1488 | 1263 */ |
1489 if (p->upstream.tries == 0 || !(p->lcf->next_upstream & ft_type)) { | 1264 } |
1490 ngx_http_proxy_finalize_request(p, status); | 1265 |
1491 return; | 1266 ngx_http_proxy_finalize_request(p, status); |
1492 } | 1267 return; |
1493 | 1268 } |
1494 if (!p->fatal_error) { | 1269 } |
1495 ngx_http_proxy_send_request(p); | 1270 |
1496 return; | 1271 ngx_http_proxy_connect(p); |
1497 } | |
1498 | |
1499 ngx_log_debug(p->request->connection->log, "FATAL ERROR IN NEXT UPSTREAM"); | |
1500 | |
1501 return; | |
1502 } | 1272 } |
1503 | 1273 |
1504 | 1274 |
1505 static int ngx_http_proxy_log_state(ngx_http_proxy_ctx_t *p, int status) | 1275 static int ngx_http_proxy_log_state(ngx_http_proxy_ctx_t *p, int status) |
1506 { | 1276 { |
1536 | 1306 |
1537 p->request->connection->log->data = p->saved_ctx; | 1307 p->request->connection->log->data = p->saved_ctx; |
1538 p->request->connection->log->handler = p->saved_handler; | 1308 p->request->connection->log->handler = p->saved_handler; |
1539 | 1309 |
1540 ngx_http_finalize_request(p->request, rc); | 1310 ngx_http_finalize_request(p->request, rc); |
1541 | |
1542 p->fatal_error = 1; | |
1543 | |
1544 return; | |
1545 } | 1311 } |
1546 | 1312 |
1547 | 1313 |
1548 static void ngx_http_proxy_close_connection(ngx_connection_t *c) | 1314 static void ngx_http_proxy_close_connection(ngx_connection_t *c) |
1549 { | 1315 { |
1550 ngx_log_debug(c->log, "close connection: %d" _ c->fd); | 1316 ngx_log_debug(c->log, "proxy close connection: %d" _ c->fd); |
1551 | 1317 |
1552 if (c->fd == -1) { | 1318 if (c->fd == -1) { |
1553 #if 0 | 1319 #if 0 |
1554 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); | 1320 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); |
1555 #endif | 1321 #endif |
1583 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, | 1349 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, |
1584 ngx_close_socket_n " failed"); | 1350 ngx_close_socket_n " failed"); |
1585 } | 1351 } |
1586 | 1352 |
1587 c->fd = -1; | 1353 c->fd = -1; |
1588 | |
1589 return; | |
1590 } | 1354 } |
1591 | 1355 |
1592 | 1356 |
1593 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len) | 1357 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len) |
1594 { | 1358 { |
1620 conf->bufs.num = 0; | 1384 conf->bufs.num = 0; |
1621 | 1385 |
1622 conf->path = NULL; | 1386 conf->path = NULL; |
1623 | 1387 |
1624 conf->next_upstream = 0; | 1388 conf->next_upstream = 0; |
1389 conf->use_stale = 0; | |
1625 | 1390 |
1626 conf->upstreams = NULL; | 1391 conf->upstreams = NULL; |
1627 conf->peers = NULL; | 1392 conf->peers = NULL; |
1393 | |
1394 conf->cache_path = NULL; | |
1395 conf->temp_path = NULL; | |
1628 | 1396 |
1629 */ | 1397 */ |
1630 | 1398 |
1631 conf->request_buffer_size = NGX_CONF_UNSET; | 1399 conf->request_buffer_size = NGX_CONF_UNSET; |
1632 conf->connect_timeout = NGX_CONF_UNSET; | 1400 conf->connect_timeout = NGX_CONF_UNSET; |
1643 | 1411 |
1644 conf->temp_file_write_size = NGX_CONF_UNSET; | 1412 conf->temp_file_write_size = NGX_CONF_UNSET; |
1645 | 1413 |
1646 /* "proxy_cyclic_temp_file" is disabled */ | 1414 /* "proxy_cyclic_temp_file" is disabled */ |
1647 conf->cyclic_temp_file = 0; | 1415 conf->cyclic_temp_file = 0; |
1416 | |
1417 conf->cache = NGX_CONF_UNSET; | |
1648 | 1418 |
1649 conf->pass_server = NGX_CONF_UNSET; | 1419 conf->pass_server = NGX_CONF_UNSET; |
1650 | 1420 |
1651 return conf; | 1421 return conf; |
1652 } | 1422 } |
1679 | 1449 |
1680 ngx_conf_merge_size_value(conf->temp_file_write_size, | 1450 ngx_conf_merge_size_value(conf->temp_file_write_size, |
1681 prev->temp_file_write_size, 16384); | 1451 prev->temp_file_write_size, 16384); |
1682 | 1452 |
1683 ngx_conf_merge_bitmask_value(conf->next_upstream, prev->next_upstream, | 1453 ngx_conf_merge_bitmask_value(conf->next_upstream, prev->next_upstream, |
1684 (NGX_HTTP_PROXY_FT_ERROR|NGX_HTTP_PROXY_FT_TIMEOUT)); | 1454 (NGX_CONF_BITMASK_SET |
1455 |NGX_HTTP_PROXY_FT_ERROR | |
1456 |NGX_HTTP_PROXY_FT_TIMEOUT)); | |
1457 | |
1458 ngx_conf_merge_bitmask_value(conf->use_stale, prev->use_stale, | |
1459 NGX_CONF_BITMASK_SET); | |
1460 | |
1461 ngx_conf_merge_path_value(conf->cache_path, prev->cache_path, | |
1462 "cache", 1, 2, 0, cf->pool); | |
1685 | 1463 |
1686 ngx_conf_merge_path_value(conf->temp_path, prev->temp_path, | 1464 ngx_conf_merge_path_value(conf->temp_path, prev->temp_path, |
1687 "temp", 1, 2, 0, cf->pool); | 1465 "temp", 1, 2, 0, cf->pool); |
1466 | |
1467 ngx_conf_merge_value(conf->cache, prev->cache, 0); | |
1688 | 1468 |
1689 ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0); | 1469 ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0); |
1690 | 1470 |
1691 return NULL; | 1471 return NULL; |
1692 } | 1472 } |
1715 | 1495 |
1716 ngx_test_null(lcf->upstream, | 1496 ngx_test_null(lcf->upstream, |
1717 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_upstream_t)), | 1497 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_upstream_t)), |
1718 NGX_CONF_ERROR); | 1498 NGX_CONF_ERROR); |
1719 | 1499 |
1500 lcf->upstream->url.len = value[1].len; | |
1501 if (!(lcf->upstream->url.data = ngx_palloc(cf->pool, value[1].len + 1))) { | |
1502 return NGX_CONF_ERROR; | |
1503 } | |
1504 ngx_cpystrn(lcf->upstream->url.data, value[1].data, value[1].len + 1); | |
1505 | |
1720 value[1].data += 7; | 1506 value[1].data += 7; |
1721 value[1].len -= 7; | 1507 value[1].len -= 7; |
1722 | 1508 |
1723 err = ngx_http_proxy_parse_upstream(&value[1], lcf->upstream); | 1509 err = ngx_http_proxy_parse_upstream(&value[1], lcf->upstream); |
1724 | 1510 |