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 {