Mercurial > hg > nginx
comparison src/http/modules/proxy/ngx_http_proxy_handler.c @ 160:e7e094d34162
nginx-0.0.1-2003-10-27-11:53:49 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 27 Oct 2003 08:53:49 +0000 |
parents | 981e4af2a425 |
children | 88abd07d9f62 |
comparison
equal
deleted
inserted
replaced
159:981e4af2a425 | 160:e7e094d34162 |
---|---|
8 #include <ngx_http_proxy_handler.h> | 8 #include <ngx_http_proxy_handler.h> |
9 | 9 |
10 | 10 |
11 | 11 |
12 static int ngx_http_proxy_handler(ngx_http_request_t *r); | 12 static int ngx_http_proxy_handler(ngx_http_request_t *r); |
13 static void ngx_http_proxy_init_request(void *data); | |
13 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); | 14 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); |
14 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev); | 15 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev); |
15 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); | 16 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); |
16 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev); | 17 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev); |
17 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev); | 18 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev); |
18 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *); | 19 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *); |
19 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p); | 20 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p); |
20 static void ngx_http_proxy_process_body(ngx_event_t *ev); | 21 static void ngx_http_proxy_process_body(ngx_event_t *ev); |
21 | 22 |
22 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); | 23 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); |
23 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p); | 24 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type); |
24 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc); | 25 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc); |
25 static void ngx_http_proxy_close_connection(ngx_connection_t *c); | 26 static void ngx_http_proxy_close_connection(ngx_connection_t *c); |
26 | 27 |
27 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len); | 28 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len); |
28 | 29 |
42 {ngx_string("proxy_pass"), | 43 {ngx_string("proxy_pass"), |
43 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 44 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
44 ngx_http_proxy_set_pass, | 45 ngx_http_proxy_set_pass, |
45 NGX_HTTP_LOC_CONF_OFFSET, | 46 NGX_HTTP_LOC_CONF_OFFSET, |
46 0, | 47 0, |
48 NULL}, | |
49 | |
50 {ngx_string("proxy_request_buffer_size"), | |
51 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
52 ngx_conf_set_size_slot, | |
53 NGX_HTTP_LOC_CONF_OFFSET, | |
54 offsetof(ngx_http_proxy_loc_conf_t, request_buffer_size), | |
47 NULL}, | 55 NULL}, |
48 | 56 |
49 {ngx_string("proxy_connect_timeout"), | 57 {ngx_string("proxy_connect_timeout"), |
50 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 58 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
51 ngx_conf_set_msec_slot, | 59 ngx_conf_set_msec_slot, |
133 ngx_string("HEAD "), | 141 ngx_string("HEAD "), |
134 ngx_string("POST ") | 142 ngx_string("POST ") |
135 }; | 143 }; |
136 | 144 |
137 | 145 |
138 #if 0 | 146 static char *upstream_header_errors[] = { |
139 static char *header_errors[] = { | |
140 "upstream sent too long status line", | |
141 "upstream sent invalid header", | 147 "upstream sent invalid header", |
142 "upstream sent too long header line" | 148 "upstream sent too long header line" |
143 }; | 149 }; |
144 #endif | |
145 | 150 |
146 | 151 |
147 static ngx_http_header_t headers_in[] = { | 152 static ngx_http_header_t headers_in[] = { |
148 { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) }, | 153 { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) }, |
149 { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) }, | 154 { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) }, |
168 | 173 |
169 | 174 |
170 | 175 |
171 static int ngx_http_proxy_handler(ngx_http_request_t *r) | 176 static int ngx_http_proxy_handler(ngx_http_request_t *r) |
172 { | 177 { |
178 int rc; | |
173 ngx_http_proxy_ctx_t *p; | 179 ngx_http_proxy_ctx_t *p; |
174 | 180 |
175 ngx_http_create_ctx(r, p, ngx_http_proxy_module, | 181 ngx_http_create_ctx(r, p, ngx_http_proxy_module, |
176 sizeof(ngx_http_proxy_ctx_t), | 182 sizeof(ngx_http_proxy_ctx_t), |
177 NGX_HTTP_INTERNAL_SERVER_ERROR); | 183 NGX_HTTP_INTERNAL_SERVER_ERROR); |
184 p->method = r->method; | 190 p->method = r->method; |
185 | 191 |
186 /* TODO: we currently support reverse proxy only */ | 192 /* TODO: we currently support reverse proxy only */ |
187 p->accel = 1; | 193 p->accel = 1; |
188 | 194 |
189 ngx_test_null(p->request_hunks, ngx_http_proxy_create_request(p), | 195 if (r->headers_in.content_length_n > 0) { |
190 NGX_HTTP_INTERNAL_SERVER_ERROR); | 196 ngx_test_null(r->temp_file, |
191 | 197 ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)), |
192 /* TODO: read request body */ | 198 NGX_HTTP_INTERNAL_SERVER_ERROR); |
199 | |
200 r->temp_file->file.fd = NGX_INVALID_FILE; | |
201 r->temp_file->file.log = r->connection->log; | |
202 r->temp_file->path = *p->lcf->temp_path; | |
203 r->temp_file->pool = r->pool; | |
204 r->temp_file->warn = "a client request body is buffered " | |
205 "to a temporary file"; | |
206 /* STUB */ r->temp_file->persistent = 1; | |
207 | |
208 r->request_body_handler = ngx_http_proxy_init_request; | |
209 r->data = p; | |
210 | |
211 rc = ngx_http_read_client_request_body(r, p->lcf->request_buffer_size); | |
212 | |
213 if (rc != NGX_OK) { | |
214 return rc; | |
215 } | |
216 } | |
217 | |
218 ngx_http_proxy_init_request(p); | |
219 | |
220 return NGX_DONE; | |
221 } | |
222 | |
223 | |
224 static void ngx_http_proxy_init_request(void *data) | |
225 { | |
226 ngx_http_proxy_ctx_t *p = data; | |
227 | |
228 ngx_chain_t *cl; | |
229 ngx_http_request_t *r; | |
230 ngx_output_chain_ctx_t *ctx; | |
231 | |
232 | |
233 r = p->request; | |
234 | |
235 cl = ngx_http_proxy_create_request(p); | |
236 if (cl == NULL) { | |
237 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
238 return; | |
239 } | |
240 | |
241 if (r->request_hunks) { | |
242 cl->next = r->request_hunks; | |
243 } | |
244 | |
245 r->request_hunks = cl; | |
193 | 246 |
194 p->upstream.log = r->connection->log; | 247 p->upstream.log = r->connection->log; |
195 p->saved_ctx = r->connection->log->data; | 248 p->saved_ctx = r->connection->log->data; |
196 r->connection->log->data = p;; | 249 p->saved_handler = r->connection->log->handler; |
250 r->connection->log->data = p; | |
197 r->connection->log->handler = ngx_http_proxy_log_error; | 251 r->connection->log->handler = ngx_http_proxy_log_error; |
198 p->action = "connecting to upstream"; | 252 p->action = "connecting to upstream"; |
199 | 253 |
254 ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)); | |
255 if (ctx == NULL) { | |
256 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
257 } | |
258 | |
259 p->output_chain_ctx = ctx; | |
260 | |
261 if (r->request_body_hunk) { | |
262 ctx->free = ngx_alloc_chain_link(r->pool); | |
263 if (ctx->free == NULL) { | |
264 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
265 } | |
266 ctx->free->hunk = r->request_body_hunk; | |
267 ctx->free->next = NULL; | |
268 } | |
269 | |
270 ctx->sendfile = r->sendfile; | |
271 ctx->copy_chain = 1; | |
272 ctx->pool = r->pool; | |
273 ctx->bufs.num = 1; | |
274 ctx->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; | |
275 ctx->output_filter = (ngx_output_chain_filter_pt) ngx_write_chain; | |
276 | |
200 ngx_http_proxy_send_request(p); | 277 ngx_http_proxy_send_request(p); |
201 | |
202 return NGX_DONE; | |
203 } | 278 } |
204 | 279 |
205 | 280 |
206 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) | 281 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) |
207 { | 282 { |
322 ngx_http_proxy_ctx_t *p; | 397 ngx_http_proxy_ctx_t *p; |
323 | 398 |
324 c = wev->data; | 399 c = wev->data; |
325 p = c->data; | 400 p = c->data; |
326 | 401 |
402 p->action = "sending request to upstream"; | |
403 | |
327 if (wev->timedout) { | 404 if (wev->timedout) { |
328 p->timedout = 1; | 405 p->timedout = 1; |
329 ngx_http_proxy_next_upstream(p); | 406 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); |
330 return; | 407 return; |
331 } | 408 } |
332 | 409 |
333 ngx_http_proxy_send_request(p); | 410 ngx_http_proxy_send_request(p); |
334 | 411 |
336 } | 413 } |
337 | 414 |
338 | 415 |
339 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) | 416 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) |
340 { | 417 { |
341 int rc; | 418 int rc; |
342 ngx_chain_t *chain, *cl, *tl, **ll; | 419 ngx_chain_t *cl; |
343 ngx_connection_t *c; | 420 ngx_connection_t *c; |
344 | 421 |
345 c = p->upstream.connection; | 422 c = p->upstream.connection; |
346 | 423 |
347 for ( ;; ) { | 424 for ( ;; ) { |
348 | 425 |
349 if (c) { | 426 if (c) { |
350 chain = ngx_write_chain(c, p->work_request_hunks); | 427 p->output_chain_ctx->output_ctx = c; |
351 | 428 rc = ngx_output_chain(p->output_chain_ctx, |
352 if (chain != NGX_CHAIN_ERROR) { | 429 p->request->request_hunks); |
353 p->work_request_hunks = chain; | 430 |
431 if (rc != NGX_ERROR) { | |
354 p->request_sent = 1; | 432 p->request_sent = 1; |
355 | 433 |
356 if (c->write->timer_set) { | 434 if (c->write->timer_set) { |
357 ngx_del_timer(c->write); | 435 ngx_del_timer(c->write); |
358 } | 436 } |
359 | 437 |
360 if (chain) { | 438 if (rc == NGX_AGAIN) { |
361 ngx_add_timer(c->write, p->lcf->send_timeout); | 439 ngx_add_timer(c->write, p->lcf->send_timeout); |
362 | 440 |
363 } else { | 441 } else { |
364 /* TODO: del event */ | 442 /* TODO: del event */ |
443 | |
444 if (c->tcp_nopush) { | |
445 if (ngx_tcp_push(c->fd) == NGX_ERROR) { | |
446 ngx_log_error(NGX_LOG_CRIT, c->log, | |
447 ngx_socket_errno, | |
448 ngx_tcp_push_n " failed"); | |
449 ngx_http_proxy_finalize_request(p, | |
450 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
451 return; | |
452 } | |
453 c->tcp_nopush = 0; | |
454 } | |
365 } | 455 } |
366 | 456 |
367 return; | 457 return; |
368 } | 458 } |
369 | 459 |
402 | 492 |
403 if (p->upstream.tries > 1 && p->request_sent) { | 493 if (p->upstream.tries > 1 && p->request_sent) { |
404 | 494 |
405 /* reinit the request chain */ | 495 /* reinit the request chain */ |
406 | 496 |
407 p->work_request_hunks = ngx_alloc_chain_link(p->request->pool); | 497 for (cl = p->request->request_hunks; cl; cl = cl->next) { |
408 if (p->work_request_hunks == NULL) { | 498 cl->hunk->pos = cl->hunk->start; |
409 ngx_http_proxy_finalize_request(p, | |
410 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
411 return; | |
412 } | 499 } |
413 | |
414 tl = p->work_request_hunks; | |
415 ll = &p->work_request_hunks; | |
416 | |
417 for (cl = p->request_hunks; cl; cl = cl->next) { | |
418 tl->hunk = cl->hunk; | |
419 *ll = tl; | |
420 ll = &tl->next; | |
421 cl->hunk->pos = cl->hunk->start; | |
422 | |
423 tl = ngx_alloc_chain_link(p->request->pool); | |
424 if (tl == NULL) { | |
425 ngx_http_proxy_finalize_request(p, | |
426 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
427 return; | |
428 } | |
429 } | |
430 | |
431 *ll = NULL; | |
432 | |
433 } else { | |
434 p->work_request_hunks = p->request_hunks; | |
435 } | 500 } |
436 | 501 |
437 p->request_sent = 0; | 502 p->request_sent = 0; |
438 p->timedout = 0; | 503 p->timedout = 0; |
439 | 504 |
459 ngx_http_proxy_ctx_t *p; | 524 ngx_http_proxy_ctx_t *p; |
460 | 525 |
461 c = rev->data; | 526 c = rev->data; |
462 p = c->data; | 527 p = c->data; |
463 | 528 |
529 p->action = "reading upstream status line"; | |
530 | |
464 ngx_log_debug(rev->log, "http proxy process status line"); | 531 ngx_log_debug(rev->log, "http proxy process status line"); |
465 | 532 |
466 if (rev->timedout) { | 533 if (rev->timedout) { |
467 p->timedout = 1; | 534 p->timedout = 1; |
468 ngx_http_proxy_next_upstream(p); | 535 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); |
469 return; | 536 return; |
470 } | 537 } |
471 | 538 |
472 if (p->header_in == NULL) { | 539 if (p->header_in == NULL) { |
473 p->header_in = ngx_create_temp_hunk(p->request->pool, | 540 p->header_in = ngx_create_temp_hunk(p->request->pool, |
481 } | 548 } |
482 | 549 |
483 n = ngx_http_proxy_read_upstream_header(p); | 550 n = ngx_http_proxy_read_upstream_header(p); |
484 | 551 |
485 if (n == NGX_ERROR) { | 552 if (n == NGX_ERROR) { |
486 ngx_http_proxy_next_upstream(p); | 553 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); |
487 return; | 554 return; |
488 } | 555 } |
489 | 556 |
490 if (n == NGX_AGAIN) { | 557 if (n == NGX_AGAIN) { |
491 return; | 558 return; |
494 rc = ngx_http_proxy_parse_status_line(p); | 561 rc = ngx_http_proxy_parse_status_line(p); |
495 | 562 |
496 if (rc == NGX_AGAIN) { | 563 if (rc == NGX_AGAIN) { |
497 if (p->header_in->pos == p->header_in->last) { | 564 if (p->header_in->pos == p->header_in->last) { |
498 ngx_log_error(NGX_LOG_ERR, rev->log, 0, | 565 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
499 "upstream sent too big header"); | 566 "upstream sent too long status line"); |
500 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY); | 567 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER); |
501 return; | |
502 } | 568 } |
503 | 569 |
504 return; | 570 return; |
505 } | 571 } |
506 | 572 |
507 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { | 573 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { |
508 /* TODO: HTTP/0.9 */ | 574 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
575 "upstream sent no valid HTTP/1.0 header"); | |
576 | |
577 if (p->accel) { | |
578 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER); | |
579 | |
580 } else { | |
581 p->request->http_version = NGX_HTTP_VERSION_9; | |
582 p->status = NGX_HTTP_OK; | |
583 ngx_http_proxy_send_response(p); | |
584 } | |
585 | |
509 return; | 586 return; |
510 } | 587 } |
511 | 588 |
512 /* rc == NGX_OK */ | 589 /* rc == NGX_OK */ |
590 | |
591 if (p->status == NGX_HTTP_INTERNAL_SERVER_ERROR | |
592 && p->upstream.tries > 1 | |
593 && (p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_500)) | |
594 { | |
595 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_500); | |
596 return; | |
597 } | |
513 | 598 |
514 p->status_line.len = p->status_end - p->status_start; | 599 p->status_line.len = p->status_end - p->status_start; |
515 p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1); | 600 p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1); |
516 if (p->status_line.data == NULL) { | 601 if (p->status_line.data == NULL) { |
517 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | 602 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
519 } | 604 } |
520 ngx_cpystrn(p->status_line.data, p->status_start, p->status_line.len + 1); | 605 ngx_cpystrn(p->status_line.data, p->status_start, p->status_line.len + 1); |
521 | 606 |
522 ngx_log_debug(rev->log, "http proxy status %d '%s'" _ | 607 ngx_log_debug(rev->log, "http proxy status %d '%s'" _ |
523 p->status _ p->status_line.data); | 608 p->status _ p->status_line.data); |
524 | |
525 | 609 |
526 if (p->headers_in.headers) { | 610 if (p->headers_in.headers) { |
527 p->headers_in.headers->nelts = 0; | 611 p->headers_in.headers->nelts = 0; |
528 } else { | 612 } else { |
529 p->headers_in.headers = ngx_create_table(p->request->pool, 10); | 613 p->headers_in.headers = ngx_create_table(p->request->pool, 10); |
547 | 631 |
548 c = rev->data; | 632 c = rev->data; |
549 p = c->data; | 633 p = c->data; |
550 r = p->request; | 634 r = p->request; |
551 | 635 |
636 p->action = "reading upstream headers"; | |
637 | |
552 ngx_log_debug(rev->log, "http proxy process header line"); | 638 ngx_log_debug(rev->log, "http proxy process header line"); |
553 | 639 |
554 if (rev->timedout) { | 640 if (rev->timedout) { |
555 p->timedout = 1; | 641 p->timedout = 1; |
556 ngx_http_proxy_next_upstream(p); | 642 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT); |
557 return; | 643 return; |
558 } | 644 } |
559 | 645 |
560 rc = NGX_AGAIN; | 646 rc = NGX_AGAIN; |
561 | 647 |
562 for ( ;; ) { | 648 for ( ;; ) { |
563 if (rc == NGX_AGAIN) { | 649 if (rc == NGX_AGAIN) { |
564 n = ngx_http_proxy_read_upstream_header(p); | 650 n = ngx_http_proxy_read_upstream_header(p); |
565 | 651 |
566 if (n == NGX_ERROR) { | 652 if (n == NGX_ERROR) { |
567 ngx_http_proxy_next_upstream(p); | 653 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); |
568 return; | 654 return; |
569 } | 655 } |
570 | 656 |
571 if (n == NGX_AGAIN) { | 657 if (n == NGX_AGAIN) { |
572 return; | 658 return; |
607 } | 693 } |
608 | 694 |
609 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) { | 695 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) { |
610 *((ngx_table_elt_t **) | 696 *((ngx_table_elt_t **) |
611 ((char *) &p->headers_in + headers_in[i].offset)) = h; | 697 ((char *) &p->headers_in + headers_in[i].offset)) = h; |
698 break; | |
612 } | 699 } |
613 } | 700 } |
614 | 701 |
615 ngx_log_debug(c->log, "HTTP proxy header: '%s: %s'" _ | 702 ngx_log_debug(c->log, "HTTP proxy header: '%s: %s'" _ |
616 h->key.data _ h->value.data); | 703 h->key.data _ h->value.data); |
629 | 716 |
630 } else if (rc != NGX_AGAIN) { | 717 } else if (rc != NGX_AGAIN) { |
631 | 718 |
632 /* there was error while a header line parsing */ | 719 /* there was error while a header line parsing */ |
633 | 720 |
634 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY); | 721 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
722 upstream_header_errors[rc - NGX_HTTP_PARSE_HEADER_ERROR]); | |
723 | |
724 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER); | |
635 return; | 725 return; |
636 } | 726 } |
637 | 727 |
638 /* NGX_AGAIN: a header line parsing is still not complete */ | 728 /* NGX_AGAIN: a header line parsing is still not complete */ |
639 | 729 |
640 if (p->header_in->last == p->header_in->end) { | 730 if (p->header_in->last == p->header_in->end) { |
641 ngx_log_error(NGX_LOG_ERR, rev->log, 0, | 731 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
642 "upstream sent too big header"); | 732 "upstream sent too big header"); |
643 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY); | 733 |
734 ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER); | |
644 return; | 735 return; |
645 } | 736 } |
646 } | 737 } |
647 } | 738 } |
648 | 739 |
677 | 768 |
678 return NGX_AGAIN; | 769 return NGX_AGAIN; |
679 } | 770 } |
680 | 771 |
681 if (n == 0) { | 772 if (n == 0) { |
682 ngx_log_error(NGX_LOG_INFO, rev->log, 0, | 773 ngx_log_error(NGX_LOG_ERR, rev->log, 0, |
683 "upstream closed prematurely connection"); | 774 "upstream closed prematurely connection"); |
684 } | 775 } |
685 | 776 |
686 if (n == 0 || n == NGX_ERROR) { | 777 if (n == 0 || n == NGX_ERROR) { |
687 return NGX_ERROR; | 778 return NGX_ERROR; |
832 r->sendfile = 1; | 923 r->sendfile = 1; |
833 } | 924 } |
834 | 925 |
835 p->event_pipe = ep; | 926 p->event_pipe = ep; |
836 | 927 |
837 #if 0 | |
838 lcx = p->log->data; | |
839 lcx->action = "reading an upstream"; | |
840 #endif | |
841 | |
842 p->upstream.connection->read->event_handler = ngx_http_proxy_process_body; | 928 p->upstream.connection->read->event_handler = ngx_http_proxy_process_body; |
843 r->connection->write->event_handler = ngx_http_proxy_process_body; | 929 r->connection->write->event_handler = ngx_http_proxy_process_body; |
844 | 930 |
845 ngx_http_proxy_process_body(p->upstream.connection->read); | 931 ngx_http_proxy_process_body(p->upstream.connection->read); |
846 | 932 |
859 | 945 |
860 if (ev->write) { | 946 if (ev->write) { |
861 ngx_log_debug(ev->log, "http proxy process downstream"); | 947 ngx_log_debug(ev->log, "http proxy process downstream"); |
862 r = c->data; | 948 r = c->data; |
863 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); | 949 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
950 p->action = "sending to client"; | |
864 | 951 |
865 } else { | 952 } else { |
866 ngx_log_debug(ev->log, "http proxy process upstream"); | 953 ngx_log_debug(ev->log, "http proxy process upstream"); |
867 p = c->data; | 954 p = c->data; |
868 r = p->request; | 955 r = p->request; |
956 p->action = "reading upstream body"; | |
869 } | 957 } |
870 | 958 |
871 ep = p->event_pipe; | 959 ep = p->event_pipe; |
872 | 960 |
873 if (ev->timedout) { | 961 if (ev->timedout) { |
1121 p->state = state; | 1209 p->state = state; |
1122 return NGX_AGAIN; | 1210 return NGX_AGAIN; |
1123 } | 1211 } |
1124 | 1212 |
1125 | 1213 |
1126 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p) | 1214 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type) |
1127 { | 1215 { |
1128 ngx_event_connect_peer_failed(&p->upstream); | 1216 ngx_event_connect_peer_failed(&p->upstream); |
1129 | 1217 |
1130 if (p->timedout) { | 1218 if (p->timedout) { |
1131 ngx_log_error(NGX_LOG_ERR, p->request->connection->log, NGX_ETIMEDOUT, | 1219 ngx_log_error(NGX_LOG_ERR, p->request->connection->log, NGX_ETIMEDOUT, |
1135 if (p->upstream.connection) { | 1223 if (p->upstream.connection) { |
1136 ngx_http_proxy_close_connection(p->upstream.connection); | 1224 ngx_http_proxy_close_connection(p->upstream.connection); |
1137 p->upstream.connection = NULL; | 1225 p->upstream.connection = NULL; |
1138 } | 1226 } |
1139 | 1227 |
1140 if (p->upstream.tries == 0) { | 1228 if (p->upstream.tries == 0 || !(p->lcf->next_upstream & ft_type)) { |
1141 ngx_http_proxy_finalize_request(p, | 1229 ngx_http_proxy_finalize_request(p, |
1142 p->timedout ? NGX_HTTP_GATEWAY_TIME_OUT: | 1230 p->timedout ? NGX_HTTP_GATEWAY_TIME_OUT: |
1143 NGX_HTTP_BAD_GATEWAY); | 1231 NGX_HTTP_BAD_GATEWAY); |
1144 return; | 1232 return; |
1145 } | 1233 } |
1146 | 1234 |
1147 if (!p->fatal_error) { | 1235 if (!p->fatal_error) { |
1148 ngx_http_proxy_send_request(p); | 1236 ngx_http_proxy_send_request(p); |
1149 } | 1237 return; |
1238 } | |
1239 | |
1240 ngx_log_debug(p->request->connection->log, "FATAL ERROR IN NEXT UPSTREAM"); | |
1150 | 1241 |
1151 return; | 1242 return; |
1152 } | 1243 } |
1153 | 1244 |
1154 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc) | 1245 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc) |
1161 if (p->header_sent | 1252 if (p->header_sent |
1162 && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE)) | 1253 && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE)) |
1163 { | 1254 { |
1164 rc = 0; | 1255 rc = 0; |
1165 } | 1256 } |
1257 | |
1258 p->request->connection->log->data = p->saved_ctx; | |
1259 p->request->connection->log->handler = p->saved_handler; | |
1166 | 1260 |
1167 ngx_http_finalize_request(p->request, rc); | 1261 ngx_http_finalize_request(p->request, rc); |
1168 | 1262 |
1169 p->fatal_error = 1; | 1263 p->fatal_error = 1; |
1170 | 1264 |
1221 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len) | 1315 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len) |
1222 { | 1316 { |
1223 ngx_http_proxy_ctx_t *p = data; | 1317 ngx_http_proxy_ctx_t *p = data; |
1224 | 1318 |
1225 return ngx_snprintf(buf, len, | 1319 return ngx_snprintf(buf, len, |
1226 " while %s, upstream: %s, client: %s, URL: %s", | 1320 " while %s, client: %s, URL: %s, upstream: %s%s%s%s%s", |
1227 p->action, | 1321 p->action, |
1322 p->request->connection->addr_text.data, | |
1323 p->request->unparsed_uri.data, | |
1228 p->upstream.peers->peers[p->upstream.cur_peer].addr_port_text.data, | 1324 p->upstream.peers->peers[p->upstream.cur_peer].addr_port_text.data, |
1229 p->request->connection->addr_text.data, | 1325 p->lcf->upstream->uri.data, |
1230 p->request->unparsed_uri.data); | 1326 p->request->uri.data + p->lcf->upstream->location->len, |
1327 p->request->args.len ? "?" : "", | |
1328 p->request->args.len ? p->request->args.data : ""); | |
1231 } | 1329 } |
1232 | 1330 |
1233 | 1331 |
1234 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) | 1332 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) |
1235 { | 1333 { |
1248 conf->upstreams = NULL; | 1346 conf->upstreams = NULL; |
1249 conf->peers = NULL; | 1347 conf->peers = NULL; |
1250 | 1348 |
1251 */ | 1349 */ |
1252 | 1350 |
1351 conf->request_buffer_size = NGX_CONF_UNSET; | |
1253 conf->connect_timeout = NGX_CONF_UNSET; | 1352 conf->connect_timeout = NGX_CONF_UNSET; |
1254 conf->send_timeout = NGX_CONF_UNSET; | 1353 conf->send_timeout = NGX_CONF_UNSET; |
1255 conf->header_buffer_size = NGX_CONF_UNSET; | 1354 conf->header_buffer_size = NGX_CONF_UNSET; |
1256 conf->read_timeout = NGX_CONF_UNSET; | 1355 conf->read_timeout = NGX_CONF_UNSET; |
1257 conf->busy_buffers_size = NGX_CONF_UNSET; | 1356 conf->busy_buffers_size = NGX_CONF_UNSET; |
1265 conf->temp_file_write_size = NGX_CONF_UNSET; | 1364 conf->temp_file_write_size = NGX_CONF_UNSET; |
1266 | 1365 |
1267 /* "proxy_cyclic_temp_file" is disabled */ | 1366 /* "proxy_cyclic_temp_file" is disabled */ |
1268 conf->cyclic_temp_file = 0; | 1367 conf->cyclic_temp_file = 0; |
1269 | 1368 |
1369 conf->next_upstream = NGX_CONF_UNSET; | |
1370 | |
1270 return conf; | 1371 return conf; |
1271 } | 1372 } |
1272 | 1373 |
1273 | 1374 |
1274 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, | 1375 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, |
1275 void *parent, void *child) | 1376 void *parent, void *child) |
1276 { | 1377 { |
1277 ngx_http_proxy_loc_conf_t *prev = parent; | 1378 ngx_http_proxy_loc_conf_t *prev = parent; |
1278 ngx_http_proxy_loc_conf_t *conf = child; | 1379 ngx_http_proxy_loc_conf_t *conf = child; |
1279 | 1380 |
1381 ngx_conf_merge_size_value(conf->request_buffer_size, | |
1382 prev->request_buffer_size, 8192); | |
1280 ngx_conf_merge_msec_value(conf->connect_timeout, | 1383 ngx_conf_merge_msec_value(conf->connect_timeout, |
1281 prev->connect_timeout, 60000); | 1384 prev->connect_timeout, 60000); |
1282 ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 30000); | 1385 ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 30000); |
1283 ngx_conf_merge_size_value(conf->header_buffer_size, | 1386 ngx_conf_merge_size_value(conf->header_buffer_size, |
1284 prev->header_buffer_size, 4096); | 1387 prev->header_buffer_size, 4096); |
1295 #endif | 1398 #endif |
1296 | 1399 |
1297 ngx_conf_merge_size_value(conf->temp_file_write_size, | 1400 ngx_conf_merge_size_value(conf->temp_file_write_size, |
1298 prev->temp_file_write_size, 16384); | 1401 prev->temp_file_write_size, 16384); |
1299 | 1402 |
1403 ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, | |
1404 (NGX_HTTP_PROXY_FT_ERROR|NGX_HTTP_PROXY_FT_TIMEOUT)); | |
1405 | |
1300 ngx_conf_merge_path_value(conf->temp_path, prev->temp_path, | 1406 ngx_conf_merge_path_value(conf->temp_path, prev->temp_path, |
1301 "temp", 1, 2, 0, cf->pool); | 1407 "temp", 1, 2, 0, cf->pool); |
1302 | 1408 |
1303 return NULL; | 1409 return NULL; |
1304 } | 1410 } |