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 }