comparison src/http/ngx_http_upstream.c @ 502:f0cac61857ae NGINX_0_8_3

nginx 0.8.3 *) Feature: the $upstream_cache_status variable. *) Bugfix: nginx could not be built on MacOSX 10.6. the bug had appeared in 0.8.2. *) Bugfix: nginx could not be built --without-http-cache; the bug had appeared in 0.8.2. *) Bugfix: a segmentation fault occurred in worker process, if a backend 401 error was intercepted and the backend did not set the "WWW-Authenticate" response header line. Thanks to Eugene Mychlo.
author Igor Sysoev <http://sysoev.ru>
date Fri, 19 Jun 2009 00:00:00 +0400
parents 207ae3ff0444
children c178dbab489a
comparison
equal deleted inserted replaced
501:531b6bbae529 502:f0cac61857ae
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);
314 316
315 { ngx_string("upstream_response_length"), NULL, 317 { ngx_string("upstream_response_length"), NULL,
316 ngx_http_upstream_response_length_variable, 0, 318 ngx_http_upstream_response_length_variable, 0,
317 NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, 319 NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
318 320
321 { ngx_string("upstream_cache_status"), NULL,
322 ngx_http_upstream_cache_status, 0,
323 NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
324
319 { ngx_null_string, NULL, NULL, 0, 0, 0 } 325 { ngx_null_string, NULL, NULL, 0, 0, 0 }
320 }; 326 };
321 327
322 328
323 static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = { 329 static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = {
573 579
574 c->min_uses = u->conf->cache_min_uses; 580 c->min_uses = u->conf->cache_min_uses;
575 c->body_start = u->conf->buffer_size; 581 c->body_start = u->conf->buffer_size;
576 c->file_cache = u->conf->cache->data; 582 c->file_cache = u->conf->cache->data;
577 583
584 u->cache_status = NGX_HTTP_CACHE_MISS;
585
578 rc = ngx_http_file_cache_open(r); 586 rc = ngx_http_file_cache_open(r);
579 587
580 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 588 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
581 "http upstream cache: %i", rc); 589 "http upstream cache: %i", rc);
582 590
583 if (rc == NGX_HTTP_CACHE_UPDATING) { 591 switch (rc) {
592
593 case NGX_HTTP_CACHE_UPDATING:
594
584 if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) { 595 if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) {
596 u->cache_status = rc;
585 rc = NGX_OK; 597 rc = NGX_OK;
586 598
587 } else { 599 } else {
588 rc = NGX_HTTP_CACHE_STALE; 600 rc = NGX_HTTP_CACHE_STALE;
589 } 601 }
590 } 602
591 603 break;
592 if (rc == NGX_OK) { 604
605 case NGX_OK:
606 u->cache_status = NGX_HTTP_CACHE_HIT;
607 }
608
609 switch (rc) {
610
611 case NGX_OK:
593 612
594 rc = ngx_http_upstream_cache_send(r, u); 613 rc = ngx_http_upstream_cache_send(r, u);
595 614
596 if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) { 615 if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) {
597 return rc; 616 return rc;
598 } 617 }
599 618
600 } else if (rc == NGX_ERROR) { 619 break;
620
621 case NGX_ERROR:
601 622
602 return NGX_ERROR; 623 return NGX_ERROR;
603 624
604 } else if (rc == NGX_HTTP_CACHE_STALE) { 625 case NGX_HTTP_CACHE_STALE:
605 626
606 c->valid_sec = 0; 627 c->valid_sec = 0;
607 u->stale_cache = 1;
608 u->buffer.start = NULL; 628 u->buffer.start = NULL;
609 629 u->cache_status = NGX_HTTP_CACHE_EXPIRED;
610 } else if (rc == NGX_DECLINED) { 630
631 break;
632
633 case NGX_DECLINED:
611 634
612 if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) { 635 if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
613 u->buffer.start = NULL; 636 u->buffer.start = NULL;
614 637
615 } else { 638 } else {
616 u->buffer.pos = u->buffer.start + c->header_start; 639 u->buffer.pos = u->buffer.start + c->header_start;
617 u->buffer.last = u->buffer.pos; 640 u->buffer.last = u->buffer.pos;
618 } 641 }
619 642
620 } else if (rc == NGX_AGAIN) { 643 break;
644
645 case NGX_AGAIN:
621 646
622 u->cacheable = 0; 647 u->cacheable = 0;
623 648
624 } else { 649 break;
650
651 default:
625 652
626 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */ 653 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
654
655 u->cache_status = NGX_HTTP_CACHE_HIT;
627 656
628 return rc; 657 return rc;
629 } 658 }
630 659
631 r->cached = 0; 660 r->cached = 0;
638 ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u) 667 ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
639 { 668 {
640 ngx_int_t rc; 669 ngx_int_t rc;
641 ngx_http_cache_t *c; 670 ngx_http_cache_t *c;
642 671
672 r->cached = 1;
643 c = r->cache; 673 c = r->cache;
644 674
645 /* TODO: cache stack */ 675 /* TODO: cache stack */
646 676
647 u->buffer = *c->buf; 677 u->buffer = *c->buf;
1519 return NGX_OK; 1549 return NGX_OK;
1520 } 1550 }
1521 1551
1522 #if (NGX_HTTP_CACHE) 1552 #if (NGX_HTTP_CACHE)
1523 1553
1524 if (u->stale_cache && (u->conf->cache_use_stale & un->mask)) { 1554 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
1555 && (u->conf->cache_use_stale & un->mask))
1556 {
1525 ngx_int_t rc; 1557 ngx_int_t rc;
1526 1558
1527 rc = u->reinit_request(r); 1559 rc = u->reinit_request(r);
1528 1560
1529 if (rc == NGX_OK) { 1561 if (rc == NGX_OK) {
1562 u->cache_status = NGX_HTTP_CACHE_STALE;
1530 rc = ngx_http_upstream_cache_send(r, u); 1563 rc = ngx_http_upstream_cache_send(r, u);
1531 } 1564 }
1532 1565
1533 ngx_http_upstream_finalize_request(r, u, rc); 1566 ngx_http_upstream_finalize_request(r, u, rc);
1534 return NGX_OK; 1567 return NGX_OK;
1571 err_page = clcf->error_pages->elts; 1604 err_page = clcf->error_pages->elts;
1572 for (i = 0; i < clcf->error_pages->nelts; i++) { 1605 for (i = 0; i < clcf->error_pages->nelts; i++) {
1573 1606
1574 if (err_page[i].status == status) { 1607 if (err_page[i].status == status) {
1575 1608
1576 if (status == NGX_HTTP_UNAUTHORIZED) { 1609 if (status == NGX_HTTP_UNAUTHORIZED
1577 1610 && u->headers_in.www_authenticate)
1611 {
1578 h = ngx_list_push(&r->headers_out.headers); 1612 h = ngx_list_push(&r->headers_out.headers);
1579 1613
1580 if (h == NULL) { 1614 if (h == NULL) {
1581 ngx_http_upstream_finalize_request(r, u, 1615 ngx_http_upstream_finalize_request(r, u,
1582 NGX_HTTP_INTERNAL_SERVER_ERROR); 1616 NGX_HTTP_INTERNAL_SERVER_ERROR);
2678 2712
2679 if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) { 2713 if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) {
2680 2714
2681 #if (NGX_HTTP_CACHE) 2715 #if (NGX_HTTP_CACHE)
2682 2716
2683 if (u->stale_cache && (u->conf->cache_use_stale & ft_type)) { 2717 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
2718 && (u->conf->cache_use_stale & ft_type))
2719 {
2684 ngx_int_t rc; 2720 ngx_int_t rc;
2685 2721
2686 rc = u->reinit_request(r); 2722 rc = u->reinit_request(r);
2687 2723
2688 if (rc == NGX_OK) { 2724 if (rc == NGX_OK) {
2725 u->cache_status = NGX_HTTP_CACHE_STALE;
2689 rc = ngx_http_upstream_cache_send(r, u); 2726 rc = ngx_http_upstream_cache_send(r, u);
2690 } 2727 }
2691 2728
2692 ngx_http_upstream_finalize_request(r, u, rc); 2729 ngx_http_upstream_finalize_request(r, u, rc);
2693 return; 2730 return;
3260 3297
3261 *ho = *h; 3298 *ho = *h;
3262 3299
3263 #if (NGX_HTTP_CACHE) 3300 #if (NGX_HTTP_CACHE)
3264 3301
3265 if (r->cached || r->upstream->cacheable) { 3302 if (r->upstream->cacheable) {
3266 r->headers_out.last_modified = ho; 3303 r->headers_out.last_modified = ho;
3267 r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data, 3304 r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
3268 h->value.len); 3305 h->value.len);
3269 } 3306 }
3270 3307
3709 3746
3710 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, 3747 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
3711 &r->upstream->headers_in.headers.part, 3748 &r->upstream->headers_in.headers.part,
3712 sizeof("upstream_http_") - 1); 3749 sizeof("upstream_http_") - 1);
3713 } 3750 }
3751
3752
3753 #if (NGX_HTTP_CACHE)
3754
3755 ngx_int_t
3756 ngx_http_upstream_cache_status(ngx_http_request_t *r,
3757 ngx_http_variable_value_t *v, uintptr_t data)
3758 {
3759 ngx_uint_t n;
3760
3761 if (r->upstream == NULL || r->upstream->cache_status == 0) {
3762 v->not_found = 1;
3763 return NGX_OK;
3764 }
3765
3766 n = r->upstream->cache_status - 1;
3767
3768 v->valid = 1;
3769 v->no_cacheable = 0;
3770 v->not_found = 0;
3771 v->len = ngx_http_cache_status[n].len;
3772 v->data = ngx_http_cache_status[n].data;
3773
3774 return NGX_OK;
3775 }
3776
3777 #endif
3714 3778
3715 3779
3716 static char * 3780 static char *
3717 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) 3781 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
3718 { 3782 {
4084 && conf->pass_headers == NGX_CONF_UNSET_PTR) 4148 && conf->pass_headers == NGX_CONF_UNSET_PTR)
4085 { 4149 {
4086 conf->hide_headers_hash = prev->hide_headers_hash; 4150 conf->hide_headers_hash = prev->hide_headers_hash;
4087 4151
4088 if (conf->hide_headers_hash.buckets 4152 if (conf->hide_headers_hash.buckets
4089 && ((conf->cache == NULL) == (prev->cache == NULL))) 4153 #if (NGX_HTTP_CACHE)
4154 && ((conf->cache == NULL) == (prev->cache == NULL))
4155 #endif
4156 )
4090 { 4157 {
4091 return NGX_OK; 4158 return NGX_OK;
4092 } 4159 }
4093 4160
4094 conf->hide_headers = prev->hide_headers; 4161 conf->hide_headers = prev->hide_headers;