comparison src/http/modules/proxy/ngx_http_proxy_handler.c @ 139:54307053f185

nginx-0.0.1-2003-10-07-19:30:05 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 07 Oct 2003 15:30:05 +0000
parents 3b168e12bd2d
children e32405df0e77
comparison
equal deleted inserted replaced
138:3b168e12bd2d 139:54307053f185
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> 4 #include <ngx_event.h>
5 /* STUB */ #include <ngx_event_connect.h> 5 /* STUB */ #include <ngx_event_connect.h>
6 /* STUB */ #include <ngx_event_proxy.h>
6 #include <ngx_http.h> 7 #include <ngx_http.h>
7 #include <ngx_http_proxy_handler.h> 8 #include <ngx_http_proxy_handler.h>
8 9
9 10
10 11
13 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev); 14 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev);
14 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); 15 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p);
15 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev); 16 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev);
16 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev); 17 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev);
17 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *); 18 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_process_upstream_body(ngx_event_t *rev);
21
18 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); 22 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p);
19 static void ngx_http_proxy_next_upstream(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_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
20 static void ngx_http_proxy_close_connection(ngx_connection_t *c); 25 static void ngx_http_proxy_close_connection(ngx_connection_t *c);
21 26
22 static int ngx_http_proxy_init(ngx_cycle_t *cycle); 27 static int ngx_http_proxy_init(ngx_cycle_t *cycle);
23 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); 28 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
24 29
79 offsetof(ngx_http_proxy_headers_in_t, content_type) }, 84 offsetof(ngx_http_proxy_headers_in_t, content_type) },
80 { ngx_string("Content-Length"), 85 { ngx_string("Content-Length"),
81 offsetof(ngx_http_proxy_headers_in_t, content_length) }, 86 offsetof(ngx_http_proxy_headers_in_t, content_length) },
82 { ngx_string("Last-Modified"), 87 { ngx_string("Last-Modified"),
83 offsetof(ngx_http_proxy_headers_in_t, last_modified) }, 88 offsetof(ngx_http_proxy_headers_in_t, last_modified) },
89 { ngx_string("Accept-Ranges"),
90 offsetof(ngx_http_proxy_headers_in_t, accept_ranges) },
84 91
85 { ngx_null_string, 0 } 92 { ngx_null_string, 0 }
86 }; 93 };
87 94
88 95
116 p->request = r; 123 p->request = r;
117 p->method = r->method; 124 p->method = r->method;
118 p->uri.data = "/"; 125 p->uri.data = "/";
119 p->uri.len = 1; 126 p->uri.len = 1;
120 p->location_len = 1; 127 p->location_len = 1;
128
129 /* STUB */ p->accel = 1;
121 130
122 p->host_header = p->upstream.peers->peers[0].host; 131 p->host_header = p->upstream.peers->peers[0].host;
123 132
124 ngx_test_null(p->request_hunks, ngx_http_proxy_create_request(p), 133 ngx_test_null(p->request_hunks, ngx_http_proxy_create_request(p),
125 NGX_HTTP_INTERNAL_SERVER_ERROR); 134 NGX_HTTP_INTERNAL_SERVER_ERROR);
294 303
295 for ( ;; ) { 304 for ( ;; ) {
296 rc = ngx_event_connect_peer(&p->upstream); 305 rc = ngx_event_connect_peer(&p->upstream);
297 306
298 if (rc == NGX_ERROR) { 307 if (rc == NGX_ERROR) {
299 ngx_http_finalize_request(p->request, 308 ngx_http_proxy_finalize_request(p,
300 NGX_HTTP_INTERNAL_SERVER_ERROR); 309 NGX_HTTP_INTERNAL_SERVER_ERROR);
301 return; 310 return;
302 } 311 }
303 312
304 if (rc == NGX_CONNECT_ERROR) { 313 if (rc == NGX_CONNECT_ERROR) {
305 ngx_event_connect_peer_failed(&p->upstream); 314 ngx_event_connect_peer_failed(&p->upstream);
306 315
307 if (p->upstream.tries == 0) { 316 if (p->upstream.tries == 0) {
308 ngx_http_finalize_request(p->request, 317 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
309 NGX_HTTP_BAD_GATEWAY);
310 return; 318 return;
311 } 319 }
312 320
313 continue; 321 continue;
314 } 322 }
328 le = NULL; 336 le = NULL;
329 #endif 337 #endif
330 p->work_request_hunks = 338 p->work_request_hunks =
331 ngx_alloc_chain_entry(p->request->pool); 339 ngx_alloc_chain_entry(p->request->pool);
332 if (p->work_request_hunks == NULL) { 340 if (p->work_request_hunks == NULL) {
333 ngx_http_proxy_close_connection(c); 341 ngx_http_proxy_finalize_request(p,
334 ngx_http_finalize_request(p->request, 342 NGX_HTTP_INTERNAL_SERVER_ERROR);
335 NGX_HTTP_INTERNAL_SERVER_ERROR);
336 return; 343 return;
337 } 344 }
338 345
339 te = p->work_request_hunks; 346 te = p->work_request_hunks;
340 347
344 le = &te->next; 351 le = &te->next;
345 ce->hunk->pos = ce->hunk->start; 352 ce->hunk->pos = ce->hunk->start;
346 353
347 te = ngx_alloc_chain_entry(p->request->pool); 354 te = ngx_alloc_chain_entry(p->request->pool);
348 if (te == NULL) { 355 if (te == NULL) {
349 ngx_http_proxy_close_connection(c); 356 ngx_http_proxy_finalize_request(p,
350 ngx_http_finalize_request(p->request,
351 NGX_HTTP_INTERNAL_SERVER_ERROR); 357 NGX_HTTP_INTERNAL_SERVER_ERROR);
352 return; 358 return;
353 } 359 }
354 } 360 }
355 361
394 if (p->header_in == NULL) { 400 if (p->header_in == NULL) {
395 p->header_in = ngx_create_temp_hunk(p->request->pool, 401 p->header_in = ngx_create_temp_hunk(p->request->pool,
396 p->lcf->header_size, 402 p->lcf->header_size,
397 0, 0); 403 0, 0);
398 if (p->header_in == NULL) { 404 if (p->header_in == NULL) {
399 ngx_http_proxy_close_connection(c); 405 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
400 ngx_http_finalize_request(p->request,
401 NGX_HTTP_INTERNAL_SERVER_ERROR);
402 return; 406 return;
403 } 407 }
404 } 408 }
405 409
406 n = ngx_http_proxy_read_upstream_header(p); 410 n = ngx_http_proxy_read_upstream_header(p);
418 422
419 if (rc == NGX_AGAIN) { 423 if (rc == NGX_AGAIN) {
420 if (p->header_in->pos == p->header_in->last) { 424 if (p->header_in->pos == p->header_in->last) {
421 ngx_log_error(NGX_LOG_ERR, rev->log, 0, 425 ngx_log_error(NGX_LOG_ERR, rev->log, 0,
422 "upstream sent too big header"); 426 "upstream sent too big header");
423 ngx_http_proxy_close_connection(c); 427 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
424 ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
425 return; 428 return;
426 } 429 }
427 430
428 return; 431 return;
429 } 432 }
436 /* rc == NGX_OK */ 439 /* rc == NGX_OK */
437 440
438 p->status_line.len = p->status_end - p->status_start; 441 p->status_line.len = p->status_end - p->status_start;
439 p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1); 442 p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1);
440 if (p->status_line.data == NULL) { 443 if (p->status_line.data == NULL) {
441 ngx_http_proxy_close_connection(c); 444 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
442 ngx_http_finalize_request(p->request, NGX_HTTP_INTERNAL_SERVER_ERROR);
443 return; 445 return;
444 } 446 }
445 ngx_cpystrn(p->status_line.data, p->status_start, p->status_line.len + 1); 447 ngx_cpystrn(p->status_line.data, p->status_start, p->status_line.len + 1);
446 448
447 ngx_log_debug(rev->log, "http proxy status %d '%s'" _ 449 ngx_log_debug(rev->log, "http proxy status %d '%s'" _
457 c->read->event_handler = ngx_http_proxy_process_upstream_headers; 459 c->read->event_handler = ngx_http_proxy_process_upstream_headers;
458 ngx_http_proxy_process_upstream_headers(rev); 460 ngx_http_proxy_process_upstream_headers(rev);
459 461
460 return; 462 return;
461 } 463 }
462
463 464
464 465
465 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev) 466 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
466 { 467 {
467 int i, rc; 468 int i, rc;
504 505
505 /* a header line has been parsed successfully */ 506 /* a header line has been parsed successfully */
506 507
507 h = ngx_push_table(p->headers_in.headers); 508 h = ngx_push_table(p->headers_in.headers);
508 if (h == NULL) { 509 if (h == NULL) {
509 ngx_http_proxy_close_connection(c); 510 ngx_http_proxy_finalize_request(p,
510 ngx_http_finalize_request(p->request, 511 NGX_HTTP_INTERNAL_SERVER_ERROR);
511 NGX_HTTP_INTERNAL_SERVER_ERROR);
512 return; 512 return;
513 } 513 }
514 514
515 h->key.len = r->header_name_end - r->header_name_start; 515 h->key.len = r->header_name_end - r->header_name_start;
516 h->value.len = r->header_end - r->header_start; 516 h->value.len = r->header_end - r->header_start;
517 517
518 h->key.data = ngx_palloc(p->request->pool, 518 h->key.data = ngx_palloc(p->request->pool,
519 h->key.len + 1 + h->value.len + 1); 519 h->key.len + 1 + h->value.len + 1);
520 if (h->key.data == NULL) { 520 if (h->key.data == NULL) {
521 ngx_http_proxy_close_connection(c); 521 ngx_http_proxy_finalize_request(p,
522 ngx_http_finalize_request(p->request, 522 NGX_HTTP_INTERNAL_SERVER_ERROR);
523 NGX_HTTP_INTERNAL_SERVER_ERROR);
524 return; 523 return;
525 } 524 }
526 525
527 h->value.data = h->key.data + h->key.len + 1; 526 h->value.data = h->key.data + h->key.len + 1;
528 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); 527 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
548 547
549 /* a whole header has been parsed successfully */ 548 /* a whole header has been parsed successfully */
550 549
551 ngx_log_debug(c->log, "HTTP header done"); 550 ngx_log_debug(c->log, "HTTP header done");
552 551
552 ngx_http_proxy_send_response(p);
553
553 return; 554 return;
554 555
555 } else if (rc != NGX_AGAIN) { 556 } else if (rc != NGX_AGAIN) {
556 557
557 /* there was error while a header line parsing */ 558 /* there was error while a header line parsing */
558 559
559 #if 0 560 #if 0
560 ngx_http_header_parse_error(r, rc); 561 ngx_http_header_parse_error(r, rc);
561 ngx_http_proxy_next_upstream(p); 562 ngx_http_proxy_next_upstream(p);
562 #endif 563 #endif
563 ngx_http_proxy_close_connection(c); 564 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
564 ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
565 return; 565 return;
566 } 566 }
567 567
568 /* NGX_AGAIN: a header line parsing is still not complete */ 568 /* NGX_AGAIN: a header line parsing is still not complete */
569 569
570 if (p->header_in->last == p->header_in->end) { 570 if (p->header_in->last == p->header_in->end) {
571 ngx_log_error(NGX_LOG_ERR, rev->log, 0, 571 ngx_log_error(NGX_LOG_ERR, rev->log, 0,
572 "upstream sent too big header"); 572 "upstream sent too big header");
573 ngx_http_proxy_close_connection(c); 573 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
574 ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
575 return; 574 return;
576 } 575 }
577 } 576 }
578 } 577 }
579 578
614 /* select, poll, /dev/poll */ 613 /* select, poll, /dev/poll */
615 event = NGX_LEVEL_EVENT; 614 event = NGX_LEVEL_EVENT;
616 } 615 }
617 616
618 if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) { 617 if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
619 ngx_http_proxy_close_connection(p->upstream.connection); 618 ngx_http_proxy_finalize_request(p,
620 ngx_http_finalize_request(p->request, 619 NGX_HTTP_INTERNAL_SERVER_ERROR);
621 NGX_HTTP_INTERNAL_SERVER_ERROR);
622 return NGX_ERROR; 620 return NGX_ERROR;
623 } 621 }
624 } 622 }
625 623
626 return NGX_AGAIN; 624 return NGX_AGAIN;
636 } 634 }
637 635
638 p->header_in->last += n; 636 p->header_in->last += n;
639 637
640 return n; 638 return n;
639 }
640
641
642 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
643 {
644 int rc, i;
645 ngx_table_elt_t *ch, *ph;
646 ngx_event_proxy_t *ep;
647 ngx_http_request_t *r;
648
649 r = p->request;
650
651 r->headers_out.content_length = -1;
652
653 /* copy an upstream header to r->headers_out */
654
655 ph = (ngx_table_elt_t *) p->headers_in.headers->elts;
656 for (i = 0; i < p->headers_in.headers->nelts; i++) {
657
658 if (&ph[i] == p->headers_in.connection) {
659 continue;
660 }
661
662 if (p->accel) {
663 if (&ph[i] == p->headers_in.date
664 || &ph[i] == p->headers_in.accept_ranges) {
665 continue;
666 }
667 }
668
669 if (&ph[i] == p->headers_in.content_length) {
670 r->headers_out.content_length =
671 ngx_atoi(p->headers_in.content_length->value.data,
672 p->headers_in.content_length->value.len);
673 continue;
674 }
675
676 ch = ngx_push_table(r->headers_out.headers);
677 if (ch == NULL) {
678 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
679 return;
680 }
681
682 *ch = ph[i];
683
684 if (&ph[i] == p->headers_in.content_type) {
685 r->headers_out.content_type = ch;
686 r->headers_out.content_type->key.len = 0;
687 continue;
688 }
689 }
690
691 /* STUB */
692
693 if (p->headers_in.server) {
694 r->headers_out.server = p->headers_in.server;
695 }
696
697 if (!p->accel && p->headers_in.date) {
698 r->headers_out.date = p->headers_in.date;
699 }
700
701 /* */
702
703 #if 0
704 /* TODO: look "Content-Length" */
705 p->block_size = p->lcf->block_size;
706 #endif
707
708 r->headers_out.status = p->status;
709
710 rc = ngx_http_send_header(r);
711
712 p->header_sent = 1;
713
714 ep = ngx_pcalloc(r->pool, sizeof(ngx_event_proxy_t));
715 if (ep == NULL) {
716 ngx_http_proxy_finalize_request(p, 0);
717 return;
718 }
719
720 ep->output_filter = (ngx_event_proxy_output_filter_pt)
721 ngx_http_output_filter;
722 ep->output_data = r;
723 ep->block_size = p->lcf->block_size;
724 ep->max_block_size = p->lcf->max_block_size;
725 ep->upstream = p->upstream.connection;
726 ep->downstream = r->connection;
727 ep->pool = r->pool;
728 ep->log = r->connection->log;
729 ep->temp_path = p->lcf->temp_path;
730
731 ep->temp_file = ngx_palloc(r->pool, sizeof(ngx_file_t));
732 if (ep->temp_file == NULL) {
733 ngx_http_proxy_finalize_request(p, 0);
734 return;
735 }
736
737 ep->temp_file->fd = NGX_INVALID_FILE;
738 ep->temp_file->log = r->connection->log;
739
740 ep->max_temp_file_size = p->lcf->max_temp_file_size;
741 ep->temp_file_write_size = p->lcf->temp_file_write_size;
742 ep->temp_file_warn = "an upstream response is buffered "
743 "to a temporary file";
744
745 ep->preread_hunks = ngx_alloc_chain_entry(r->pool);
746 if (ep->preread_hunks == NULL) {
747 ngx_http_proxy_finalize_request(p, 0);
748 return;
749 }
750 ep->preread_hunks->hunk = p->header_in;
751 ep->preread_hunks->next = NULL;
752
753 ep->preread_size = p->header_in->last - p->header_in->pos;
754
755 p->event_proxy = ep;
756
757 #if 0
758 lcx = p->log->data;
759 lcx->action = "reading an upstream";
760 #endif
761
762 ngx_event_proxy_read_upstream(ep);
763
764 p->upstream.connection->read->event_handler =
765 ngx_http_proxy_process_upstream_body;
766
767 return;
768 }
769
770
771 static void ngx_http_proxy_process_upstream_body(ngx_event_t *rev)
772 {
773 ngx_connection_t *c;
774 ngx_http_proxy_ctx_t *p;
775
776 c = rev->data;
777 p = c->data;
778
779 ngx_log_debug(rev->log, "http proxy process upstream body");
780
781 if (rev->timedout) {
782 ngx_http_proxy_next_upstream(p);
783 return;
784 }
785
786 ngx_event_proxy_read_upstream(p->event_proxy);
787
788 return;
641 } 789 }
642 790
643 791
644 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p) 792 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p)
645 { 793 {
837 985
838 p->state = state; 986 p->state = state;
839 return NGX_AGAIN; 987 return NGX_AGAIN;
840 } 988 }
841 989
990
842 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p) 991 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p)
843 { 992 {
844 if (p->upstream.connection) { 993 if (p->upstream.connection) {
845 ngx_http_proxy_close_connection(p->upstream.connection); 994 ngx_http_proxy_close_connection(p->upstream.connection);
846 p->upstream.connection = NULL; 995 p->upstream.connection = NULL;
847 996 }
997
998 if (!p->fatal_error) {
848 ngx_http_proxy_send_request(p); 999 ngx_http_proxy_send_request(p);
849 } 1000 }
850 1001
851 return; 1002 return;
852 } 1003 }
853 1004
1005 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
1006 {
1007 if (p->upstream.connection) {
1008 ngx_http_proxy_close_connection(p->upstream.connection);
1009 p->upstream.connection = NULL;
1010 }
1011
1012 if (p->header_sent) {
1013 rc = 0;
1014 }
1015
1016 ngx_http_finalize_request(p->request, rc);
1017
1018 p->fatal_error = 1;
1019
1020 return;
1021 }
1022
1023
854 1024
855 static void ngx_http_proxy_close_connection(ngx_connection_t *c) 1025 static void ngx_http_proxy_close_connection(ngx_connection_t *c)
856 { 1026 {
857 ngx_log_debug(c->log, "close connection: %d" _ c->fd); 1027 ngx_log_debug(c->log, "close connection: %d" _ c->fd);
858 1028
859 if (c->fd == -1) { 1029 if (c->fd == -1) {
1030 #if 0
860 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); 1031 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
1032 #endif
861 return; 1033 return;
862 } 1034 }
863 1035
864 if (c->read->timer_set) { 1036 if (c->read->timer_set) {
865 ngx_del_timer(c->read); 1037 ngx_del_timer(c->read);
925 } 1097 }
926 1098
927 1099
928 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) 1100 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
929 { 1101 {
1102 int i;
930 ngx_http_proxy_loc_conf_t *conf; 1103 ngx_http_proxy_loc_conf_t *conf;
931 1104
932 ngx_test_null(conf, 1105 ngx_test_null(conf,
933 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t)), 1106 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t)),
934 NGX_CONF_ERROR); 1107 NGX_CONF_ERROR);
947 1120
948 conf->connect_timeout = 30000; 1121 conf->connect_timeout = 30000;
949 conf->send_timeout = 30000; 1122 conf->send_timeout = 30000;
950 conf->header_size = 4096; 1123 conf->header_size = 4096;
951 conf->read_timeout = 30000; 1124 conf->read_timeout = 30000;
1125
1126 conf->block_size = 4096;
1127 conf->max_block_size = 4096 * 3;
1128 conf->max_temp_file_size = 4096 * 5;
1129 conf->temp_file_write_size = 4096 * 2;
1130
1131 ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)),
1132 NULL);
1133
1134 conf->temp_path->name.data = "temp";
1135 conf->temp_path->name.len = 4;
1136 conf->temp_path->level[0] = 1;
1137 conf->temp_path->level[1] = 2;
1138 conf->temp_path->level[2] = 3;
1139 conf->temp_path->len = 0;
1140
1141 for (i = 0; i < 3; i++) {
1142 if (conf->temp_path->level[i] == 0) {
1143 break;
1144 }
1145 conf->temp_path->len += conf->temp_path->level[i] + 1;
1146 }
1147
952 /* */ 1148 /* */
953 1149
954 return conf; 1150 return conf;
955 } 1151 }