Mercurial > hg > nginx
comparison src/http/modules/ngx_http_proxy_module.c @ 577:4d9ea73a627a release-0.3.10
nginx-0.3.10-RELEASE import
*) Change: the "valid_referers" directive and the "$invalid_referer"
variable were moved to the new ngx_http_referer_module from the
ngx_http_rewrite_module.
*) Change: the "$apache_bytes_sent" variable name was changed to
"$body_bytes_sent".
*) Feature: the "$sent_http_..." variables.
*) Feature: the "if" directive supports the "=" and "!=" operations.
*) Feature: the "proxy_pass" directive supports the HTTPS protocol.
*) Feature: the "proxy_set_body" directive.
*) Feature: the "post_action" directive.
*) Feature: the ngx_http_empty_gif_module.
*) Feature: the "worker_cpu_affinity" directive for Linux.
*) Bugfix: the "rewrite" directive did not unescape URI part in
redirect, now it is unescaped except the %00-%25 and %7F-%FF
characters.
*) Bugfix: nginx could not be built by the icc 9.0 compiler.
*) Bugfix: if the SSI was enabled for zero size static file, then the
chunked response was encoded incorrectly.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 15 Nov 2005 13:30:52 +0000 |
parents | 58475592100c |
children | 4c5c2c55975c |
comparison
equal
deleted
inserted
replaced
576:3e0b61c26426 | 577:4d9ea73a627a |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright (C) Igor Sysoev | 3 * Copyright (C) Igor Sysoev |
4 */ | 4 */ |
5 | 5 |
6 | 6 |
7 #include <ngx_config.h> | 7 #include <ngx_config.h> |
36 ngx_http_upstream_conf_t upstream; | 36 ngx_http_upstream_conf_t upstream; |
37 | 37 |
38 ngx_peers_t *peers; | 38 ngx_peers_t *peers; |
39 | 39 |
40 ngx_array_t *flushes; | 40 ngx_array_t *flushes; |
41 ngx_array_t *body_set_len; | |
42 ngx_array_t *body_set; | |
41 ngx_array_t *headers_set_len; | 43 ngx_array_t *headers_set_len; |
42 ngx_array_t *headers_set; | 44 ngx_array_t *headers_set; |
43 ngx_hash_t *headers_set_hash; | 45 ngx_hash_t *headers_set_hash; |
44 | 46 |
45 ngx_array_t *headers_source; | 47 ngx_array_t *headers_source; |
46 ngx_array_t *headers_names; | 48 ngx_array_t *headers_names; |
47 | 49 |
48 ngx_array_t *redirects; | 50 ngx_array_t *redirects; |
51 | |
52 ngx_str_t body_source; | |
49 | 53 |
50 ngx_str_t method; | 54 ngx_str_t method; |
51 ngx_str_t host_header; | 55 ngx_str_t host_header; |
52 ngx_str_t port_text; | 56 ngx_str_t port_text; |
53 | 57 |
58 typedef struct { | 62 typedef struct { |
59 ngx_uint_t status; | 63 ngx_uint_t status; |
60 ngx_uint_t status_count; | 64 ngx_uint_t status_count; |
61 u_char *status_start; | 65 u_char *status_start; |
62 u_char *status_end; | 66 u_char *status_end; |
67 | |
68 size_t internal_body_length; | |
63 } ngx_http_proxy_ctx_t; | 69 } ngx_http_proxy_ctx_t; |
64 | 70 |
65 | 71 |
66 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20 | 72 #define NGX_HTTP_PROXY_PARSE_NO_HEADER 20 |
67 | 73 |
81 static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r, | 87 static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r, |
82 ngx_http_variable_value_t *v, uintptr_t data); | 88 ngx_http_variable_value_t *v, uintptr_t data); |
83 static ngx_int_t | 89 static ngx_int_t |
84 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, | 90 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, |
85 ngx_http_variable_value_t *v, uintptr_t data); | 91 ngx_http_variable_value_t *v, uintptr_t data); |
92 static ngx_int_t | |
93 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r, | |
94 ngx_http_variable_value_t *v, uintptr_t data); | |
86 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, | 95 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, |
87 ngx_table_elt_t *h, size_t prefix); | 96 ngx_table_elt_t *h, size_t prefix); |
88 | 97 |
89 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); | 98 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); |
90 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); | 99 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); |
160 { ngx_string("proxy_set_header"), | 169 { ngx_string("proxy_set_header"), |
161 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, | 170 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, |
162 ngx_conf_set_table_elt_slot, | 171 ngx_conf_set_table_elt_slot, |
163 NGX_HTTP_LOC_CONF_OFFSET, | 172 NGX_HTTP_LOC_CONF_OFFSET, |
164 offsetof(ngx_http_proxy_loc_conf_t, headers_source), | 173 offsetof(ngx_http_proxy_loc_conf_t, headers_source), |
174 NULL }, | |
175 | |
176 { ngx_string("proxy_set_body"), | |
177 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
178 ngx_conf_set_str_slot, | |
179 NGX_HTTP_LOC_CONF_OFFSET, | |
180 offsetof(ngx_http_proxy_loc_conf_t, body_source), | |
165 NULL }, | 181 NULL }, |
166 | 182 |
167 { ngx_string("proxy_method"), | 183 { ngx_string("proxy_method"), |
168 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 184 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
169 ngx_conf_set_str_slot, | 185 ngx_conf_set_str_slot, |
334 | 350 |
335 #if 0 | 351 #if 0 |
336 { ngx_string("proxy_add_via"), NULL, 0, 0, 0 }, | 352 { ngx_string("proxy_add_via"), NULL, 0, 0, 0 }, |
337 #endif | 353 #endif |
338 | 354 |
355 { ngx_string("proxy_internal_body_length"), | |
356 ngx_http_proxy_internal_body_length_variable, 0, 0, 0 }, | |
357 | |
339 { ngx_null_string, NULL, 0, 0, 0 } | 358 { ngx_null_string, NULL, 0, 0, 0 } |
340 }; | 359 }; |
341 | 360 |
342 | 361 |
343 static ngx_int_t | 362 static ngx_int_t |
344 ngx_http_proxy_handler(ngx_http_request_t *r) | 363 ngx_http_proxy_handler(ngx_http_request_t *r) |
345 { | 364 { |
346 ngx_int_t rc; | 365 ngx_int_t rc; |
347 ngx_http_upstream_t *u; | 366 ngx_http_upstream_t *u; |
348 ngx_http_proxy_loc_conf_t *plcf; | 367 ngx_http_proxy_loc_conf_t *plcf; |
349 | 368 |
350 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | 369 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
351 | 370 |
352 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); | 371 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); |
353 if (u == NULL) { | 372 if (u == NULL) { |
354 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 373 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
355 } | 374 } |
356 | 375 |
357 u->peer.log = r->connection->log; | 376 u->peer.log = r->connection->log; |
358 u->peer.log_error = NGX_ERROR_ERR; | 377 u->peer.log_error = NGX_ERROR_ERR; |
359 u->peer.peers = plcf->peers; | 378 u->peer.peers = plcf->peers; |
360 u->peer.tries = plcf->peers->number; | 379 u->peer.tries = plcf->peers->number; |
361 #if (NGX_THREADS) | 380 #if (NGX_THREADS) |
377 } | 396 } |
378 | 397 |
379 u->pipe.input_filter = ngx_event_pipe_copy_input_filter; | 398 u->pipe.input_filter = ngx_event_pipe_copy_input_filter; |
380 | 399 |
381 u->accel = 1; | 400 u->accel = 1; |
382 | 401 |
383 r->upstream = u; | 402 r->upstream = u; |
384 | 403 |
385 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); | 404 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); |
386 | 405 |
387 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | 406 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { |
393 | 412 |
394 | 413 |
395 static ngx_int_t | 414 static ngx_int_t |
396 ngx_http_proxy_create_request(ngx_http_request_t *r) | 415 ngx_http_proxy_create_request(ngx_http_request_t *r) |
397 { | 416 { |
398 size_t len, loc_len; | 417 size_t len, loc_len, body_len; |
399 ngx_uint_t i, key; | 418 ngx_uint_t i, key; |
400 uintptr_t escape; | 419 uintptr_t escape; |
401 ngx_buf_t *b; | 420 ngx_buf_t *b; |
402 ngx_str_t *hh, method; | 421 ngx_str_t *hh, method; |
403 ngx_chain_t *cl, *body; | 422 ngx_chain_t *cl, *body; |
404 ngx_list_part_t *part; | 423 ngx_list_part_t *part; |
405 ngx_table_elt_t *header; | 424 ngx_table_elt_t *header; |
406 ngx_http_upstream_t *u; | 425 ngx_http_upstream_t *u; |
426 ngx_http_proxy_ctx_t *p; | |
407 ngx_http_script_code_pt code; | 427 ngx_http_script_code_pt code; |
408 ngx_http_script_engine_t e, le; | 428 ngx_http_script_engine_t e, le; |
409 ngx_http_proxy_loc_conf_t *plcf; | 429 ngx_http_proxy_loc_conf_t *plcf; |
410 ngx_http_script_len_code_pt lcode; | 430 ngx_http_script_len_code_pt lcode; |
411 | 431 |
412 u = r->upstream; | 432 u = r->upstream; |
413 | 433 |
414 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | 434 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
415 | 435 |
436 p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t)); | |
437 if (p == NULL) { | |
438 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
439 } | |
440 | |
441 ngx_http_set_ctx(r, p, ngx_http_proxy_module); | |
442 | |
416 len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1; | 443 len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1; |
417 | 444 |
418 if (u->method.len) { | 445 if (u->method.len) { |
419 /* HEAD was changed to GET to cache response */ | 446 /* HEAD was changed to GET to cache response */ |
420 method = u->method; | 447 method = u->method; |
444 } | 471 } |
445 | 472 |
446 len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len; | 473 len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len; |
447 } | 474 } |
448 | 475 |
449 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
450 | |
451 ngx_http_script_flush_no_cachable_variables(r, plcf->flushes); | 476 ngx_http_script_flush_no_cachable_variables(r, plcf->flushes); |
477 | |
478 if (plcf->body_set_len) { | |
479 le.ip = plcf->body_set_len->elts; | |
480 le.request = r; | |
481 le.flushed = 1; | |
482 body_len = 0; | |
483 | |
484 while (*(uintptr_t *) le.ip) { | |
485 lcode = *(ngx_http_script_len_code_pt *) le.ip; | |
486 body_len += lcode(&le); | |
487 } | |
488 | |
489 p->internal_body_length = body_len; | |
490 len += body_len; | |
491 } | |
452 | 492 |
453 le.ip = plcf->headers_set_len->elts; | 493 le.ip = plcf->headers_set_len->elts; |
454 le.request = r; | 494 le.request = r; |
455 le.flushed = 1; | 495 le.flushed = 1; |
456 | 496 |
476 break; | 516 break; |
477 } | 517 } |
478 | 518 |
479 part = part->next; | 519 part = part->next; |
480 header = part->elts; | 520 header = part->elts; |
481 i = 0; | 521 i = 0; |
482 } | 522 } |
483 | 523 |
484 key = header[i].hash % plcf->headers_set_hash->hash_size; | 524 key = header[i].hash % plcf->headers_set_hash->hash_size; |
485 | 525 |
486 if (hh[key].len == header[i].key.len | 526 if (hh[key].len == header[i].key.len |
525 if (escape) { | 565 if (escape) { |
526 ngx_escape_uri(b->last, r->uri.data + loc_len, | 566 ngx_escape_uri(b->last, r->uri.data + loc_len, |
527 r->uri.len - loc_len, NGX_ESCAPE_URI); | 567 r->uri.len - loc_len, NGX_ESCAPE_URI); |
528 b->last += r->uri.len - loc_len + escape; | 568 b->last += r->uri.len - loc_len + escape; |
529 | 569 |
530 } else { | 570 } else { |
531 b->last = ngx_copy(b->last, r->uri.data + loc_len, | 571 b->last = ngx_copy(b->last, r->uri.data + loc_len, |
532 r->uri.len - loc_len); | 572 r->uri.len - loc_len); |
533 } | 573 } |
534 | 574 |
535 if (r->args.len > 0) { | 575 if (r->args.len > 0) { |
541 u->uri.len = b->last - u->uri.data; | 581 u->uri.len = b->last - u->uri.data; |
542 | 582 |
543 b->last = ngx_cpymem(b->last, ngx_http_proxy_version, | 583 b->last = ngx_cpymem(b->last, ngx_http_proxy_version, |
544 sizeof(ngx_http_proxy_version) - 1); | 584 sizeof(ngx_http_proxy_version) - 1); |
545 | 585 |
586 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
546 | 587 |
547 e.ip = plcf->headers_set->elts; | 588 e.ip = plcf->headers_set->elts; |
548 e.pos = b->last; | 589 e.pos = b->last; |
549 e.request = r; | 590 e.request = r; |
550 e.flushed = 1; | 591 e.flushed = 1; |
572 le.ip += sizeof(uintptr_t); | 613 le.ip += sizeof(uintptr_t); |
573 | 614 |
574 while (*(uintptr_t *) e.ip) { | 615 while (*(uintptr_t *) e.ip) { |
575 code = *(ngx_http_script_code_pt *) e.ip; | 616 code = *(ngx_http_script_code_pt *) e.ip; |
576 code((ngx_http_script_engine_t *) &e); | 617 code((ngx_http_script_engine_t *) &e); |
577 } | 618 } |
578 e.ip += sizeof(uintptr_t); | 619 e.ip += sizeof(uintptr_t); |
579 } | 620 } |
580 | 621 |
581 b->last = e.pos; | 622 b->last = e.pos; |
582 | 623 |
583 | 624 |
584 if (plcf->upstream.pass_request_headers) { | 625 if (plcf->upstream.pass_request_headers) { |
585 part = &r->headers_in.headers.part; | 626 part = &r->headers_in.headers.part; |
586 header = part->elts; | 627 header = part->elts; |
587 | 628 |
588 for (i = 0; /* void */; i++) { | 629 for (i = 0; /* void */; i++) { |
589 | 630 |
590 if (i >= part->nelts) { | 631 if (i >= part->nelts) { |
591 if (part->next == NULL) { | 632 if (part->next == NULL) { |
592 break; | 633 break; |
593 } | 634 } |
594 | 635 |
595 part = part->next; | 636 part = part->next; |
596 header = part->elts; | 637 header = part->elts; |
597 i = 0; | 638 i = 0; |
598 } | 639 } |
599 | 640 |
600 key = header[i].hash % plcf->headers_set_hash->hash_size; | 641 key = header[i].hash % plcf->headers_set_hash->hash_size; |
601 | 642 |
602 if (hh[key].len == header[i].key.len | 643 if (hh[key].len == header[i].key.len |
618 "http proxy header: \"%V: %V\"", | 659 "http proxy header: \"%V: %V\"", |
619 &header[i].key, &header[i].value); | 660 &header[i].key, &header[i].value); |
620 } | 661 } |
621 } | 662 } |
622 | 663 |
664 | |
623 /* add "\r\n" at the header end */ | 665 /* add "\r\n" at the header end */ |
624 *b->last++ = CR; *b->last++ = LF; | 666 *b->last++ = CR; *b->last++ = LF; |
667 | |
668 if (plcf->body_set) { | |
669 e.ip = plcf->body_set->elts; | |
670 e.pos = b->last; | |
671 | |
672 while (*(uintptr_t *) e.ip) { | |
673 code = *(ngx_http_script_code_pt *) e.ip; | |
674 code((ngx_http_script_engine_t *) &e); | |
675 } | |
676 } | |
677 | |
678 b->last = e.pos; | |
625 | 679 |
626 #if (NGX_DEBUG) | 680 #if (NGX_DEBUG) |
627 { | 681 { |
628 ngx_str_t s; | 682 ngx_str_t s; |
629 | 683 |
632 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 686 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
633 "http proxy header:\n\"%V\"", &s); | 687 "http proxy header:\n\"%V\"", &s); |
634 } | 688 } |
635 #endif | 689 #endif |
636 | 690 |
637 if (plcf->upstream.pass_request_body) { | 691 if (plcf->body_set == NULL && plcf->upstream.pass_request_body) { |
638 | 692 |
639 body = u->request_bufs; | 693 body = u->request_bufs; |
640 u->request_bufs = cl; | 694 u->request_bufs = cl; |
641 | 695 |
642 while (body) { | 696 while (body) { |
698 ngx_http_proxy_ctx_t *p; | 752 ngx_http_proxy_ctx_t *p; |
699 | 753 |
700 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); | 754 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
701 | 755 |
702 if (p == NULL) { | 756 if (p == NULL) { |
703 p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t)); | 757 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
704 if (p == NULL) { | |
705 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
706 } | |
707 | |
708 ngx_http_set_ctx(r, p, ngx_http_proxy_module); | |
709 } | 758 } |
710 | 759 |
711 rc = ngx_http_proxy_parse_status_line(r, p); | 760 rc = ngx_http_proxy_parse_status_line(r, p); |
712 | 761 |
713 if (rc == NGX_AGAIN) { | 762 if (rc == NGX_AGAIN) { |
716 | 765 |
717 u = r->upstream; | 766 u = r->upstream; |
718 | 767 |
719 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { | 768 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { |
720 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 769 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
721 "upstream sent no valid HTTP/1.0 header"); | 770 "upstream sent no valid HTTP/1.0 header"); |
722 | 771 |
723 if (u->accel) { | 772 if (u->accel) { |
724 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | 773 return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
725 } | 774 } |
726 | 775 |
727 r->http_version = NGX_HTTP_VERSION_9; | 776 r->http_version = NGX_HTTP_VERSION_9; |
728 p->status = NGX_HTTP_OK; | 777 p->status = NGX_HTTP_OK; |
729 | 778 |
730 return NGX_OK; | 779 return NGX_OK; |
731 } | 780 } |
732 | 781 |
733 u->headers_in.status_n = p->status; | 782 u->headers_in.status_n = p->status; |
734 u->state->status = p->status; | 783 u->state->status = p->status; |
771 sw_minor_digit, | 820 sw_minor_digit, |
772 sw_status, | 821 sw_status, |
773 sw_space_after_status, | 822 sw_space_after_status, |
774 sw_status_text, | 823 sw_status_text, |
775 sw_almost_done | 824 sw_almost_done |
776 } state; | 825 } state; |
777 | 826 |
778 u = r->upstream; | 827 u = r->upstream; |
779 | 828 |
780 state = r->state; | 829 state = r->state; |
781 | 830 |
785 switch (state) { | 834 switch (state) { |
786 | 835 |
787 /* "HTTP/" */ | 836 /* "HTTP/" */ |
788 case sw_start: | 837 case sw_start: |
789 switch (ch) { | 838 switch (ch) { |
790 case 'H': | 839 case 'H': |
791 state = sw_H; | 840 state = sw_H; |
792 break; | 841 break; |
793 default: | 842 default: |
794 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | 843 return NGX_HTTP_PROXY_PARSE_NO_HEADER; |
795 } | 844 } |
796 break; | 845 break; |
797 | 846 |
798 case sw_H: | 847 case sw_H: |
799 switch (ch) { | 848 switch (ch) { |
800 case 'T': | 849 case 'T': |
801 state = sw_HT; | 850 state = sw_HT; |
802 break; | 851 break; |
803 default: | 852 default: |
804 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | 853 return NGX_HTTP_PROXY_PARSE_NO_HEADER; |
805 } | 854 } |
806 break; | 855 break; |
807 | 856 |
808 case sw_HT: | 857 case sw_HT: |
809 switch (ch) { | 858 switch (ch) { |
810 case 'T': | 859 case 'T': |
811 state = sw_HTT; | 860 state = sw_HTT; |
812 break; | 861 break; |
813 default: | 862 default: |
814 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | 863 return NGX_HTTP_PROXY_PARSE_NO_HEADER; |
815 } | 864 } |
816 break; | 865 break; |
817 | 866 |
818 case sw_HTT: | 867 case sw_HTT: |
819 switch (ch) { | 868 switch (ch) { |
820 case 'P': | 869 case 'P': |
821 state = sw_HTTP; | 870 state = sw_HTTP; |
822 break; | 871 break; |
823 default: | 872 default: |
824 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | 873 return NGX_HTTP_PROXY_PARSE_NO_HEADER; |
825 } | 874 } |
826 break; | 875 break; |
827 | 876 |
828 case sw_HTTP: | 877 case sw_HTTP: |
829 switch (ch) { | 878 switch (ch) { |
830 case '/': | 879 case '/': |
831 state = sw_first_major_digit; | 880 state = sw_first_major_digit; |
832 break; | 881 break; |
833 default: | 882 default: |
834 return NGX_HTTP_PROXY_PARSE_NO_HEADER; | 883 return NGX_HTTP_PROXY_PARSE_NO_HEADER; |
835 } | 884 } |
895 break; | 944 break; |
896 | 945 |
897 /* space or end of line */ | 946 /* space or end of line */ |
898 case sw_space_after_status: | 947 case sw_space_after_status: |
899 switch (ch) { | 948 switch (ch) { |
900 case ' ': | 949 case ' ': |
901 state = sw_status_text; | 950 state = sw_status_text; |
902 break; | 951 break; |
903 case '.': /* IIS may send 403.1, 403.2, etc */ | 952 case '.': /* IIS may send 403.1, 403.2, etc */ |
904 state = sw_status_text; | 953 state = sw_status_text; |
905 break; | 954 break; |
1042 static void | 1091 static void |
1043 ngx_http_proxy_abort_request(ngx_http_request_t *r) | 1092 ngx_http_proxy_abort_request(ngx_http_request_t *r) |
1044 { | 1093 { |
1045 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1094 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1046 "abort http proxy request"); | 1095 "abort http proxy request"); |
1047 | 1096 |
1048 return; | 1097 return; |
1049 } | 1098 } |
1050 | 1099 |
1051 | 1100 |
1052 static void | 1101 static void |
1053 ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc) | 1102 ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc) |
1054 { | 1103 { |
1055 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1104 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1056 "finalize http proxy request"); | 1105 "finalize http proxy request"); |
1057 | 1106 |
1058 return; | 1107 return; |
1059 } | 1108 } |
1066 ngx_http_proxy_loc_conf_t *plcf; | 1115 ngx_http_proxy_loc_conf_t *plcf; |
1067 | 1116 |
1068 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | 1117 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
1069 | 1118 |
1070 v->len = plcf->host_header.len; | 1119 v->len = plcf->host_header.len; |
1071 v->valid = 1; | 1120 v->valid = 1; |
1072 v->no_cachable = 0; | 1121 v->no_cachable = 0; |
1073 v->not_found = 0; | 1122 v->not_found = 0; |
1074 v->data = plcf->host_header.data; | 1123 v->data = plcf->host_header.data; |
1075 | 1124 |
1076 return NGX_OK; | 1125 return NGX_OK; |
1084 ngx_http_proxy_loc_conf_t *plcf; | 1133 ngx_http_proxy_loc_conf_t *plcf; |
1085 | 1134 |
1086 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | 1135 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
1087 | 1136 |
1088 v->len = plcf->port_text.len; | 1137 v->len = plcf->port_text.len; |
1089 v->valid = 1; | 1138 v->valid = 1; |
1090 v->no_cachable = 0; | 1139 v->no_cachable = 0; |
1091 v->not_found = 0; | 1140 v->not_found = 0; |
1092 v->data = plcf->port_text.data; | 1141 v->data = plcf->port_text.data; |
1093 | 1142 |
1094 return NGX_OK; | 1143 return NGX_OK; |
1095 } | 1144 } |
1096 | 1145 |
1097 | 1146 |
1098 static ngx_int_t | 1147 static ngx_int_t |
1099 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, | 1148 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, |
1100 | |
1101 ngx_http_variable_value_t *v, uintptr_t data) | 1149 ngx_http_variable_value_t *v, uintptr_t data) |
1102 { | 1150 { |
1103 u_char *p; | 1151 u_char *p; |
1104 | 1152 |
1105 v->valid = 1; | 1153 v->valid = 1; |
1106 v->no_cachable = 0; | 1154 v->no_cachable = 0; |
1107 v->not_found = 0; | 1155 v->not_found = 0; |
1108 | 1156 |
1109 if (r->headers_in.x_forwarded_for == NULL) { | 1157 if (r->headers_in.x_forwarded_for == NULL) { |
1110 v->len = r->connection->addr_text.len; | 1158 v->len = r->connection->addr_text.len; |
1126 r->headers_in.x_forwarded_for->value.len); | 1174 r->headers_in.x_forwarded_for->value.len); |
1127 | 1175 |
1128 *p++ = ','; *p++ = ' '; | 1176 *p++ = ','; *p++ = ' '; |
1129 | 1177 |
1130 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); | 1178 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); |
1179 | |
1180 return NGX_OK; | |
1181 } | |
1182 | |
1183 | |
1184 static ngx_int_t | |
1185 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r, | |
1186 ngx_http_variable_value_t *v, uintptr_t data) | |
1187 { | |
1188 ngx_http_proxy_ctx_t *p; | |
1189 | |
1190 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); | |
1191 | |
1192 if (p == NULL) { | |
1193 v->not_found = 1; | |
1194 return NGX_OK; | |
1195 } | |
1196 | |
1197 v->valid = 1; | |
1198 v->no_cachable = 0; | |
1199 v->not_found = 0; | |
1200 | |
1201 v->data = ngx_palloc(r->connection->pool, NGX_SIZE_T_LEN); | |
1202 | |
1203 if (v->data == NULL) { | |
1204 return NGX_ERROR; | |
1205 } | |
1206 | |
1207 v->len = ngx_sprintf(v->data, "%uz", p->internal_body_length) - v->data; | |
1131 | 1208 |
1132 return NGX_OK; | 1209 return NGX_OK; |
1133 } | 1210 } |
1134 | 1211 |
1135 | 1212 |
1292 * conf->method = NULL; | 1369 * conf->method = NULL; |
1293 * conf->headers_source = NULL; | 1370 * conf->headers_source = NULL; |
1294 * conf->headers_set_len = NULL; | 1371 * conf->headers_set_len = NULL; |
1295 * conf->headers_set = NULL; | 1372 * conf->headers_set = NULL; |
1296 * conf->headers_set_hash = NULL; | 1373 * conf->headers_set_hash = NULL; |
1374 * conf->body_set_len = NULL; | |
1375 * conf->body_set = NULL; | |
1376 * conf->body_source = { 0, NULL }; | |
1297 * conf->rewrite_locations = NULL; | 1377 * conf->rewrite_locations = NULL; |
1298 */ | 1378 */ |
1299 | 1379 |
1300 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; | 1380 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; |
1301 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; | 1381 conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; |
1302 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; | 1382 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; |
1303 | 1383 |
1304 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; | 1384 conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; |
1305 conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE; | 1385 conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE; |
1306 | 1386 |
1307 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; | 1387 conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; |
1308 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; | 1388 conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; |
1309 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; | 1389 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; |
1310 | 1390 |
1311 conf->upstream.max_fails = NGX_CONF_UNSET_UINT; | 1391 conf->upstream.max_fails = NGX_CONF_UNSET_UINT; |
1312 conf->upstream.fail_timeout = NGX_CONF_UNSET; | 1392 conf->upstream.fail_timeout = NGX_CONF_UNSET; |
1313 | 1393 |
1364 | 1444 |
1365 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, | 1445 ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, |
1366 8, ngx_pagesize); | 1446 8, ngx_pagesize); |
1367 | 1447 |
1368 if (conf->upstream.bufs.num < 2) { | 1448 if (conf->upstream.bufs.num < 2) { |
1369 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 1449 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1370 "there must be at least 2 \"proxy_buffers\""); | 1450 "there must be at least 2 \"proxy_buffers\""); |
1371 return NGX_CONF_ERROR; | 1451 return NGX_CONF_ERROR; |
1372 } | 1452 } |
1373 | 1453 |
1374 | 1454 |
1375 size = conf->upstream.header_buffer_size; | 1455 size = conf->upstream.header_buffer_size; |
1376 if (size < conf->upstream.bufs.size) { | 1456 if (size < conf->upstream.bufs.size) { |
1377 size = conf->upstream.bufs.size; | 1457 size = conf->upstream.bufs.size; |
1378 } | 1458 } |
1379 | 1459 |
1380 | 1460 |
1381 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf, | 1461 ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf, |
1386 conf->upstream.busy_buffers_size = 2 * size; | 1466 conf->upstream.busy_buffers_size = 2 * size; |
1387 } else { | 1467 } else { |
1388 conf->upstream.busy_buffers_size = | 1468 conf->upstream.busy_buffers_size = |
1389 conf->upstream.busy_buffers_size_conf; | 1469 conf->upstream.busy_buffers_size_conf; |
1390 } | 1470 } |
1391 | 1471 |
1392 if (conf->upstream.busy_buffers_size < size) { | 1472 if (conf->upstream.busy_buffers_size < size) { |
1393 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 1473 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1394 "\"proxy_busy_buffers_size\" must be equal or bigger than " | 1474 "\"proxy_busy_buffers_size\" must be equal or bigger than " |
1395 "maximum of the value of \"proxy_header_buffer_size\" and " | 1475 "maximum of the value of \"proxy_header_buffer_size\" and " |
1396 "one of the \"proxy_buffers\""); | 1476 "one of the \"proxy_buffers\""); |
1417 conf->upstream.temp_file_write_size = 2 * size; | 1497 conf->upstream.temp_file_write_size = 2 * size; |
1418 } else { | 1498 } else { |
1419 conf->upstream.temp_file_write_size = | 1499 conf->upstream.temp_file_write_size = |
1420 conf->upstream.temp_file_write_size_conf; | 1500 conf->upstream.temp_file_write_size_conf; |
1421 } | 1501 } |
1422 | 1502 |
1423 if (conf->upstream.temp_file_write_size < size) { | 1503 if (conf->upstream.temp_file_write_size < size) { |
1424 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 1504 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1425 "\"proxy_temp_file_write_size\" must be equal or bigger than " | 1505 "\"proxy_temp_file_write_size\" must be equal or bigger than " |
1426 "maximum of the value of \"proxy_header_buffer_size\" and " | 1506 "maximum of the value of \"proxy_header_buffer_size\" and " |
1427 "one of the \"proxy_buffers\""); | 1507 "one of the \"proxy_buffers\""); |
1532 | 1612 |
1533 if (conf->peers == NULL) { | 1613 if (conf->peers == NULL) { |
1534 conf->peers = prev->peers; | 1614 conf->peers = prev->peers; |
1535 } | 1615 } |
1536 | 1616 |
1617 | |
1618 if (conf->body_source.data == NULL) { | |
1619 conf->body_source = prev->body_source; | |
1620 conf->body_set_len = prev->body_set_len; | |
1621 conf->body_set = prev->body_set; | |
1622 } | |
1623 | |
1624 if (conf->body_set_len == 0) { | |
1625 | |
1626 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1627 | |
1628 sc.cf = cf; | |
1629 sc.source = &conf->body_source; | |
1630 sc.flushes = &conf->flushes; | |
1631 sc.lengths = &conf->body_set_len; | |
1632 sc.values = &conf->body_set; | |
1633 sc.complete_lengths = 1; | |
1634 sc.complete_values = 1; | |
1635 | |
1636 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1637 return NGX_CONF_ERROR; | |
1638 } | |
1639 | |
1640 if (conf->headers_source == NULL) { | |
1641 conf->headers_source = ngx_array_create(cf->pool, 4, | |
1642 sizeof(ngx_table_elt_t)); | |
1643 if (conf->headers_source == NULL) { | |
1644 return NGX_CONF_ERROR; | |
1645 } | |
1646 } | |
1647 | |
1648 s = ngx_array_push(conf->headers_source); | |
1649 if (s == NULL) { | |
1650 return NGX_CONF_ERROR; | |
1651 } | |
1652 | |
1653 s->hash = 0; | |
1654 s->key.len = sizeof("Content-Length") - 1; | |
1655 s->key.data = (u_char *) "Content-Length"; | |
1656 s->value.len = sizeof("$proxy_internal_body_length") - 1; | |
1657 s->value.data = (u_char *) "$proxy_internal_body_length"; | |
1658 } | |
1659 | |
1660 | |
1537 if (conf->headers_source == NULL) { | 1661 if (conf->headers_source == NULL) { |
1538 conf->flushes = prev->flushes; | 1662 conf->flushes = prev->flushes; |
1539 conf->headers_set_len = prev->headers_set_len; | 1663 conf->headers_set_len = prev->headers_set_len; |
1540 conf->headers_set = prev->headers_set; | 1664 conf->headers_set = prev->headers_set; |
1541 conf->headers_set_hash = prev->headers_set_hash; | 1665 conf->headers_set_hash = prev->headers_set_hash; |
1593 next: | 1717 next: |
1594 | 1718 |
1595 continue; | 1719 continue; |
1596 } | 1720 } |
1597 | 1721 |
1722 | |
1723 src = conf->headers_source->elts; | |
1598 for (i = 0; i < conf->headers_source->nelts; i++) { | 1724 for (i = 0; i < conf->headers_source->nelts; i++) { |
1599 | 1725 |
1600 name = ngx_array_push(conf->headers_names); | 1726 name = ngx_array_push(conf->headers_names); |
1601 if (name == NULL) { | 1727 if (name == NULL) { |
1602 return NGX_CONF_ERROR; | 1728 return NGX_CONF_ERROR; |
1764 static char * | 1890 static char * |
1765 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1891 ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
1766 { | 1892 { |
1767 ngx_http_proxy_loc_conf_t *plcf = conf; | 1893 ngx_http_proxy_loc_conf_t *plcf = conf; |
1768 | 1894 |
1895 size_t add; | |
1769 ngx_str_t *value, *url; | 1896 ngx_str_t *value, *url; |
1770 ngx_inet_upstream_t inet_upstream; | 1897 ngx_inet_upstream_t inet_upstream; |
1771 ngx_http_core_loc_conf_t *clcf; | 1898 ngx_http_core_loc_conf_t *clcf; |
1899 #if (NGX_HTTP_SSL) | |
1900 ngx_pool_cleanup_t *cln; | |
1901 #endif | |
1772 #if (NGX_HAVE_UNIX_DOMAIN) | 1902 #if (NGX_HAVE_UNIX_DOMAIN) |
1773 ngx_unix_domain_upstream_t unix_upstream; | 1903 ngx_unix_domain_upstream_t unix_upstream; |
1774 #endif | 1904 #endif |
1775 | 1905 |
1776 if (plcf->upstream.schema.len) { | 1906 if (plcf->upstream.schema.len) { |
1779 | 1909 |
1780 value = cf->args->elts; | 1910 value = cf->args->elts; |
1781 | 1911 |
1782 url = &value[1]; | 1912 url = &value[1]; |
1783 | 1913 |
1784 if (ngx_strncasecmp(url->data, "http://", 7) != 0) { | 1914 if (ngx_strncasecmp(url->data, "http://", 7) == 0) { |
1915 add = 7; | |
1916 | |
1917 } else if (ngx_strncasecmp(url->data, "https://", 8) == 0) { | |
1918 | |
1919 #if (NGX_HTTP_SSL) | |
1920 | |
1921 add = 8; | |
1922 | |
1923 plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); | |
1924 if (plcf->upstream.ssl == NULL) { | |
1925 return NGX_CONF_ERROR; | |
1926 } | |
1927 | |
1928 plcf->upstream.ssl->log = cf->log; | |
1929 | |
1930 if (ngx_ssl_create(plcf->upstream.ssl, | |
1931 NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1) | |
1932 != NGX_OK) | |
1933 { | |
1934 return NGX_CONF_ERROR; | |
1935 } | |
1936 | |
1937 cln = ngx_pool_cleanup_add(cf->pool, 0); | |
1938 if (cln == NULL) { | |
1939 return NGX_CONF_ERROR; | |
1940 } | |
1941 | |
1942 cln->handler = ngx_ssl_cleanup_ctx; | |
1943 cln->data = plcf->upstream.ssl; | |
1944 | |
1945 #else | |
1946 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1947 "https protocol requires SSL support"); | |
1948 return NGX_CONF_ERROR; | |
1949 #endif | |
1950 | |
1951 } else { | |
1785 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix"); | 1952 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix"); |
1786 return NGX_CONF_ERROR; | 1953 return NGX_CONF_ERROR; |
1787 } | 1954 } |
1788 | 1955 |
1789 if (ngx_strncasecmp(url->data + 7, "unix:", 5) == 0) { | 1956 if (ngx_strncasecmp(url->data + add, "unix:", 5) == 0) { |
1790 | 1957 |
1791 #if (NGX_HAVE_UNIX_DOMAIN) | 1958 #if (NGX_HAVE_UNIX_DOMAIN) |
1792 | 1959 |
1793 ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t)); | 1960 ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t)); |
1794 | 1961 |
1795 unix_upstream.name = *url; | 1962 unix_upstream.name = *url; |
1796 unix_upstream.url.len = url->len - 7; | 1963 unix_upstream.url.len = url->len - add; |
1797 unix_upstream.url.data = url->data + 7; | 1964 unix_upstream.url.data = url->data + add; |
1798 unix_upstream.uri_part = 1; | 1965 unix_upstream.uri_part = 1; |
1799 | 1966 |
1800 plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream); | 1967 plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream); |
1801 if (plcf->peers == NULL) { | 1968 if (plcf->peers == NULL) { |
1802 return NGX_CONF_ERROR; | 1969 return NGX_CONF_ERROR; |
1816 | 1983 |
1817 } else { | 1984 } else { |
1818 ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t)); | 1985 ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t)); |
1819 | 1986 |
1820 inet_upstream.name = *url; | 1987 inet_upstream.name = *url; |
1821 inet_upstream.url.len = url->len - 7; | 1988 inet_upstream.url.len = url->len - add; |
1822 inet_upstream.url.data = url->data + 7; | 1989 inet_upstream.url.data = url->data + add; |
1823 inet_upstream.default_port_value = 80; | 1990 inet_upstream.default_port_value = 80; |
1824 inet_upstream.uri_part = 1; | 1991 inet_upstream.uri_part = 1; |
1825 | 1992 |
1826 plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream); | 1993 plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream); |
1827 if (plcf->peers == NULL) { | 1994 if (plcf->peers == NULL) { |