Mercurial > hg > nginx-vendor-0-7
comparison src/http/ngx_http_upstream.c @ 500:ed3d382670c7 NGINX_0_7_62
nginx 0.7.62
*) Security: a segmentation fault might occur in worker process while
specially crafted request handling.
Thanks to Chris Ries.
*) Feature: the $upstream_cache_status variable.
*) Bugfix: an expired cached response might stick in the "UPDATING"
state.
*) Bugfix: a segmentation fault might occur in worker process, if
error_log was set to info or debug level.
Thanks to Sergey Bochenkov.
*) Bugfix: in handling FastCGI headers split in records.
*) Bugfix: XSLT filter may fail with message "not well formed XML
document" for valid XML document.
Thanks to Kuramoto Eiji.
*) Bugfix: now in MacOSX, Cygwin, and nginx/Windows locations given by
a regular expression are always tested in case insensitive mode.
*) Bugfix: now nginx/Windows ignores trailing dots in URI.
Thanks to Hugo Leisink.
*) Bugfix: name of file specified in --conf-path was not honored during
installation; the bug had appeared in 0.6.6.
Thanks to Maxim Dounin.
*) Bugfix: a 500 error code was returned for invalid login/password
while HTTP Basic authentication on Windows.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 14 Sep 2009 00:00:00 +0400 |
parents | ef5c97e49c35 |
children | 89dc5654117c |
comparison
equal
deleted
inserted
replaced
499:f2c782e5161f | 500:ed3d382670c7 |
---|---|
12 #if (NGX_HTTP_CACHE) | 12 #if (NGX_HTTP_CACHE) |
13 static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r, | 13 static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r, |
14 ngx_http_upstream_t *u); | 14 ngx_http_upstream_t *u); |
15 static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r, | 15 static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r, |
16 ngx_http_upstream_t *u); | 16 ngx_http_upstream_t *u); |
17 static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r, | |
18 ngx_http_variable_value_t *v, uintptr_t data); | |
17 #endif | 19 #endif |
18 | 20 |
19 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx); | 21 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx); |
20 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r); | 22 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r); |
21 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r); | 23 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r); |
157 { ngx_string("Last-Modified"), | 159 { ngx_string("Last-Modified"), |
158 ngx_http_upstream_process_header_line, | 160 ngx_http_upstream_process_header_line, |
159 offsetof(ngx_http_upstream_headers_in_t, last_modified), | 161 offsetof(ngx_http_upstream_headers_in_t, last_modified), |
160 ngx_http_upstream_copy_last_modified, 0, 0 }, | 162 ngx_http_upstream_copy_last_modified, 0, 0 }, |
161 | 163 |
164 { ngx_string("ETag"), | |
165 ngx_http_upstream_process_header_line, | |
166 offsetof(ngx_http_upstream_headers_in_t, etag), | |
167 ngx_http_upstream_copy_header_line, | |
168 offsetof(ngx_http_headers_out_t, etag), 0 }, | |
169 | |
162 { ngx_string("Server"), | 170 { ngx_string("Server"), |
163 ngx_http_upstream_process_header_line, | 171 ngx_http_upstream_process_header_line, |
164 offsetof(ngx_http_upstream_headers_in_t, server), | 172 offsetof(ngx_http_upstream_headers_in_t, server), |
165 ngx_http_upstream_copy_header_line, | 173 ngx_http_upstream_copy_header_line, |
166 offsetof(ngx_http_headers_out_t, server), 0 }, | 174 offsetof(ngx_http_headers_out_t, server), 0 }, |
314 | 322 |
315 { ngx_string("upstream_response_length"), NULL, | 323 { ngx_string("upstream_response_length"), NULL, |
316 ngx_http_upstream_response_length_variable, 0, | 324 ngx_http_upstream_response_length_variable, 0, |
317 NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, | 325 NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
318 | 326 |
327 #if (NGX_HTTP_CACHE) | |
328 | |
329 { ngx_string("upstream_cache_status"), NULL, | |
330 ngx_http_upstream_cache_status, 0, | |
331 NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, | |
332 | |
333 #endif | |
334 | |
319 { ngx_null_string, NULL, NULL, 0, 0, 0 } | 335 { ngx_null_string, NULL, NULL, 0, 0, 0 } |
320 }; | 336 }; |
321 | 337 |
322 | 338 |
323 static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = { | 339 static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = { |
573 | 589 |
574 c->min_uses = u->conf->cache_min_uses; | 590 c->min_uses = u->conf->cache_min_uses; |
575 c->body_start = u->conf->buffer_size; | 591 c->body_start = u->conf->buffer_size; |
576 c->file_cache = u->conf->cache->data; | 592 c->file_cache = u->conf->cache->data; |
577 | 593 |
594 u->cache_status = NGX_HTTP_CACHE_MISS; | |
595 | |
578 rc = ngx_http_file_cache_open(r); | 596 rc = ngx_http_file_cache_open(r); |
579 | 597 |
580 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 598 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
581 "http upstream cache: %i", rc); | 599 "http upstream cache: %i", rc); |
582 | 600 |
583 if (rc == NGX_HTTP_CACHE_UPDATING) { | 601 switch (rc) { |
602 | |
603 case NGX_HTTP_CACHE_UPDATING: | |
604 | |
584 if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) { | 605 if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) { |
606 u->cache_status = rc; | |
585 rc = NGX_OK; | 607 rc = NGX_OK; |
586 | 608 |
587 } else { | 609 } else { |
588 rc = NGX_HTTP_CACHE_STALE; | 610 rc = NGX_HTTP_CACHE_STALE; |
589 } | 611 } |
590 } | 612 |
591 | 613 break; |
592 if (rc == NGX_OK) { | 614 |
615 case NGX_OK: | |
616 u->cache_status = NGX_HTTP_CACHE_HIT; | |
617 } | |
618 | |
619 switch (rc) { | |
620 | |
621 case NGX_OK: | |
593 | 622 |
594 rc = ngx_http_upstream_cache_send(r, u); | 623 rc = ngx_http_upstream_cache_send(r, u); |
595 | 624 |
596 if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) { | 625 if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) { |
597 return rc; | 626 return rc; |
598 } | 627 } |
599 | 628 |
600 } else if (rc == NGX_ERROR) { | 629 break; |
630 | |
631 case NGX_ERROR: | |
601 | 632 |
602 return NGX_ERROR; | 633 return NGX_ERROR; |
603 | 634 |
604 } else if (rc == NGX_HTTP_CACHE_STALE) { | 635 case NGX_HTTP_CACHE_STALE: |
605 | 636 |
606 c->valid_sec = 0; | 637 c->valid_sec = 0; |
607 u->stale_cache = 1; | |
608 u->buffer.start = NULL; | 638 u->buffer.start = NULL; |
609 | 639 u->cache_status = NGX_HTTP_CACHE_EXPIRED; |
610 } else if (rc == NGX_DECLINED) { | 640 |
641 break; | |
642 | |
643 case NGX_DECLINED: | |
611 | 644 |
612 if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) { | 645 if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) { |
613 u->buffer.start = NULL; | 646 u->buffer.start = NULL; |
614 | 647 |
615 } else { | 648 } else { |
616 u->buffer.pos = u->buffer.start + c->header_start; | 649 u->buffer.pos = u->buffer.start + c->header_start; |
617 u->buffer.last = u->buffer.pos; | 650 u->buffer.last = u->buffer.pos; |
618 } | 651 } |
619 | 652 |
620 } else if (rc == NGX_AGAIN) { | 653 break; |
654 | |
655 case NGX_AGAIN: | |
621 | 656 |
622 u->cacheable = 0; | 657 u->cacheable = 0; |
623 | 658 |
624 } else { | 659 break; |
660 | |
661 default: | |
625 | 662 |
626 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */ | 663 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */ |
664 | |
665 u->cache_status = NGX_HTTP_CACHE_HIT; | |
627 | 666 |
628 return rc; | 667 return rc; |
629 } | 668 } |
630 | 669 |
631 r->cached = 0; | 670 r->cached = 0; |
638 ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u) | 677 ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u) |
639 { | 678 { |
640 ngx_int_t rc; | 679 ngx_int_t rc; |
641 ngx_http_cache_t *c; | 680 ngx_http_cache_t *c; |
642 | 681 |
682 r->cached = 1; | |
643 c = r->cache; | 683 c = r->cache; |
644 | 684 |
645 /* TODO: cache stack */ | 685 /* TODO: cache stack */ |
646 | 686 |
647 u->buffer = *c->buf; | 687 u->buffer = *c->buf; |
1519 return NGX_OK; | 1559 return NGX_OK; |
1520 } | 1560 } |
1521 | 1561 |
1522 #if (NGX_HTTP_CACHE) | 1562 #if (NGX_HTTP_CACHE) |
1523 | 1563 |
1524 if (u->stale_cache && (u->conf->cache_use_stale & un->mask)) { | 1564 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED |
1565 && (u->conf->cache_use_stale & un->mask)) | |
1566 { | |
1525 ngx_int_t rc; | 1567 ngx_int_t rc; |
1526 | 1568 |
1527 rc = u->reinit_request(r); | 1569 rc = u->reinit_request(r); |
1528 | 1570 |
1529 if (rc == NGX_OK) { | 1571 if (rc == NGX_OK) { |
1572 u->cache_status = NGX_HTTP_CACHE_STALE; | |
1530 rc = ngx_http_upstream_cache_send(r, u); | 1573 rc = ngx_http_upstream_cache_send(r, u); |
1531 } | 1574 } |
1532 | 1575 |
1533 ngx_http_upstream_finalize_request(r, u, rc); | 1576 ngx_http_upstream_finalize_request(r, u, rc); |
1534 return NGX_OK; | 1577 return NGX_OK; |
2004 } | 2047 } |
2005 } | 2048 } |
2006 | 2049 |
2007 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 2050 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
2008 "http cacheable: %d", u->cacheable); | 2051 "http cacheable: %d", u->cacheable); |
2052 | |
2053 if (u->cacheable == 0 && r->cache) { | |
2054 ngx_http_file_cache_free(r, u->pipe->temp_file); | |
2055 } | |
2009 | 2056 |
2010 #endif | 2057 #endif |
2011 | 2058 |
2012 p = u->pipe; | 2059 p = u->pipe; |
2013 | 2060 |
2679 | 2726 |
2680 if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) { | 2727 if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) { |
2681 | 2728 |
2682 #if (NGX_HTTP_CACHE) | 2729 #if (NGX_HTTP_CACHE) |
2683 | 2730 |
2684 if (u->stale_cache && (u->conf->cache_use_stale & ft_type)) { | 2731 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED |
2732 && (u->conf->cache_use_stale & ft_type)) | |
2733 { | |
2685 ngx_int_t rc; | 2734 ngx_int_t rc; |
2686 | 2735 |
2687 rc = u->reinit_request(r); | 2736 rc = u->reinit_request(r); |
2688 | 2737 |
2689 if (rc == NGX_OK) { | 2738 if (rc == NGX_OK) { |
2739 u->cache_status = NGX_HTTP_CACHE_STALE; | |
2690 rc = ngx_http_upstream_cache_send(r, u); | 2740 rc = ngx_http_upstream_cache_send(r, u); |
2691 } | 2741 } |
2692 | 2742 |
2693 ngx_http_upstream_finalize_request(r, u, rc); | 2743 ngx_http_upstream_finalize_request(r, u, rc); |
2694 return; | 2744 return; |
3261 | 3311 |
3262 *ho = *h; | 3312 *ho = *h; |
3263 | 3313 |
3264 #if (NGX_HTTP_CACHE) | 3314 #if (NGX_HTTP_CACHE) |
3265 | 3315 |
3266 if (r->cached || r->upstream->cacheable) { | 3316 if (r->upstream->cacheable) { |
3267 r->headers_out.last_modified = ho; | 3317 r->headers_out.last_modified = ho; |
3268 r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data, | 3318 r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data, |
3269 h->value.len); | 3319 h->value.len); |
3270 } | 3320 } |
3271 | 3321 |
3710 | 3760 |
3711 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, | 3761 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, |
3712 &r->upstream->headers_in.headers.part, | 3762 &r->upstream->headers_in.headers.part, |
3713 sizeof("upstream_http_") - 1); | 3763 sizeof("upstream_http_") - 1); |
3714 } | 3764 } |
3765 | |
3766 | |
3767 #if (NGX_HTTP_CACHE) | |
3768 | |
3769 ngx_int_t | |
3770 ngx_http_upstream_cache_status(ngx_http_request_t *r, | |
3771 ngx_http_variable_value_t *v, uintptr_t data) | |
3772 { | |
3773 ngx_uint_t n; | |
3774 | |
3775 if (r->upstream == NULL || r->upstream->cache_status == 0) { | |
3776 v->not_found = 1; | |
3777 return NGX_OK; | |
3778 } | |
3779 | |
3780 n = r->upstream->cache_status - 1; | |
3781 | |
3782 v->valid = 1; | |
3783 v->no_cacheable = 0; | |
3784 v->not_found = 0; | |
3785 v->len = ngx_http_cache_status[n].len; | |
3786 v->data = ngx_http_cache_status[n].data; | |
3787 | |
3788 return NGX_OK; | |
3789 } | |
3790 | |
3791 #endif | |
3715 | 3792 |
3716 | 3793 |
3717 static char * | 3794 static char * |
3718 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) | 3795 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) |
3719 { | 3796 { |