comparison src/http/ngx_http_upstream.c @ 635:e67b227c8dbb default tip

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 25 Apr 2011 04:07:55 +0400
parents b9763778e212
children
comparison
equal deleted inserted replaced
578:f3a9e57d2e17 635:e67b227c8dbb
70 static void ngx_http_upstream_finalize_request(ngx_http_request_t *r, 70 static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
71 ngx_http_upstream_t *u, ngx_int_t rc); 71 ngx_http_upstream_t *u, ngx_int_t rc);
72 72
73 static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r, 73 static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
74 ngx_table_elt_t *h, ngx_uint_t offset); 74 ngx_table_elt_t *h, ngx_uint_t offset);
75 static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
76 ngx_table_elt_t *h, ngx_uint_t offset);
75 static ngx_int_t 77 static ngx_int_t
76 ngx_http_upstream_process_cache_control(ngx_http_request_t *r, 78 ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
77 ngx_table_elt_t *h, ngx_uint_t offset); 79 ngx_table_elt_t *h, ngx_uint_t offset);
78 static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, 80 static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
79 ngx_table_elt_t *h, ngx_uint_t offset); 81 ngx_table_elt_t *h, ngx_uint_t offset);
187 { ngx_string("Refresh"), 189 { ngx_string("Refresh"),
188 ngx_http_upstream_ignore_header_line, 0, 190 ngx_http_upstream_ignore_header_line, 0,
189 ngx_http_upstream_rewrite_refresh, 0, 0 }, 191 ngx_http_upstream_rewrite_refresh, 0, 0 },
190 192
191 { ngx_string("Set-Cookie"), 193 { ngx_string("Set-Cookie"),
192 ngx_http_upstream_ignore_header_line, 0, 194 ngx_http_upstream_process_set_cookie, 0,
193 ngx_http_upstream_copy_header_line, 0, 1 }, 195 ngx_http_upstream_copy_header_line, 0, 1 },
194 196
195 { ngx_string("Content-Disposition"), 197 { ngx_string("Content-Disposition"),
196 ngx_http_upstream_ignore_header_line, 0, 198 ngx_http_upstream_ignore_header_line, 0,
197 ngx_http_upstream_copy_header_line, 0, 1 }, 199 ngx_http_upstream_copy_header_line, 0, 1 },
353 { ngx_string("POST"), NGX_HTTP_POST }, 355 { ngx_string("POST"), NGX_HTTP_POST },
354 { ngx_null_string, 0 } 356 { ngx_null_string, 0 }
355 }; 357 };
356 358
357 359
360 ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks[] = {
361 { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
362 { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
363 { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
364 { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
365 { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
366 { ngx_null_string, 0 }
367 };
368
369
358 ngx_int_t 370 ngx_int_t
359 ngx_http_upstream_create(ngx_http_request_t *r) 371 ngx_http_upstream_create(ngx_http_request_t *r)
360 { 372 {
361 ngx_http_upstream_t *u; 373 ngx_http_upstream_t *u;
362 374
363 u = r->upstream; 375 u = r->upstream;
364 376
365 if (u && u->cleanup) { 377 if (u && u->cleanup) {
366 r->main->count++; 378 r->main->count++;
367 ngx_http_upstream_cleanup(r); 379 ngx_http_upstream_cleanup(r);
368 *u->cleanup = NULL;
369 u->cleanup = NULL;
370 } 380 }
371 381
372 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); 382 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
373 if (u == NULL) { 383 if (u == NULL) {
374 return NGX_ERROR; 384 return NGX_ERROR;
562 { 572 {
563 goto found; 573 goto found;
564 } 574 }
565 } 575 }
566 576
577 if (u->resolved->port == 0) {
578 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
579 "no port in upstream \"%V\"", host);
580 ngx_http_upstream_finalize_request(r, u,
581 NGX_HTTP_INTERNAL_SERVER_ERROR);
582 return;
583 }
584
567 temp.name = *host; 585 temp.name = *host;
568 586
569 ctx = ngx_resolve_start(clcf->resolver, &temp); 587 ctx = ngx_resolve_start(clcf->resolver, &temp);
570 if (ctx == NULL) { 588 if (ctx == NULL) {
571 ngx_http_upstream_finalize_request(r, u, 589 ngx_http_upstream_finalize_request(r, u,
621 639
622 c = r->cache; 640 c = r->cache;
623 641
624 if (c == NULL) { 642 if (c == NULL) {
625 643
644 switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
645
646 case NGX_ERROR:
647 return NGX_ERROR;
648
649 case NGX_DECLINED:
650 u->cache_status = NGX_HTTP_CACHE_BYPASS;
651 return NGX_DECLINED;
652
653 default: /* NGX_OK */
654 break;
655 }
656
626 if (!(r->method & u->conf->cache_methods)) { 657 if (!(r->method & u->conf->cache_methods)) {
627 return NGX_DECLINED; 658 return NGX_DECLINED;
628 } 659 }
629 660
630 if (r->method & NGX_HTTP_HEAD) { 661 if (r->method & NGX_HTTP_HEAD) {
631 u->method = ngx_http_core_get_method; 662 u->method = ngx_http_core_get_method;
632 } 663 }
633 664
634 c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t)); 665 if (ngx_http_file_cache_new(r) != NGX_OK) {
635 if (c == NULL) {
636 return NGX_ERROR; 666 return NGX_ERROR;
637 } 667 }
638
639 if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
640 return NGX_ERROR;
641 }
642
643 r->cache = c;
644 c->file.log = r->connection->log;
645 668
646 if (u->create_key(r) != NGX_OK) { 669 if (u->create_key(r) != NGX_OK) {
647 return NGX_ERROR; 670 return NGX_ERROR;
648 } 671 }
649 672
650 /* TODO: add keys */ 673 /* TODO: add keys */
651 674
652 ngx_http_file_cache_create_key(r); 675 ngx_http_file_cache_create_key(r);
653 676
654 u->cacheable = 1; 677 u->cacheable = 1;
678
679 c = r->cache;
655 680
656 c->min_uses = u->conf->cache_min_uses; 681 c->min_uses = u->conf->cache_min_uses;
657 c->body_start = u->conf->buffer_size; 682 c->body_start = u->conf->buffer_size;
658 c->file_cache = u->conf->cache->data; 683 c->file_cache = u->conf->cache->data;
659 684
1701 *h = *u->headers_in.www_authenticate; 1726 *h = *u->headers_in.www_authenticate;
1702 1727
1703 r->headers_out.www_authenticate = h; 1728 r->headers_out.www_authenticate = h;
1704 } 1729 }
1705 1730
1731 #if (NGX_HTTP_CACHE)
1732
1733 if (r->cache) {
1734 time_t valid;
1735
1736 valid = ngx_http_file_cache_valid(u->conf->cache_valid, status);
1737
1738 if (valid) {
1739 r->cache->valid_sec = ngx_time() + valid;
1740 r->cache->error = status;
1741 }
1742
1743 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
1744 }
1745 #endif
1706 ngx_http_upstream_finalize_request(r, u, status); 1746 ngx_http_upstream_finalize_request(r, u, status);
1707 1747
1708 return NGX_OK; 1748 return NGX_OK;
1709 } 1749 }
1710 } 1750 }
1800 } 1840 }
1801 } 1841 }
1802 } 1842 }
1803 1843
1804 uri = &u->headers_in.x_accel_redirect->value; 1844 uri = &u->headers_in.x_accel_redirect->value;
1805 args.len = 0; 1845 ngx_str_null(&args);
1806 args.data = NULL;
1807 flags = NGX_HTTP_LOG_UNSAFE; 1846 flags = NGX_HTTP_LOG_UNSAFE;
1808 1847
1809 if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) { 1848 if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
1810 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); 1849 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1811 return NGX_DONE; 1850 return NGX_DONE;
1812 }
1813
1814 if (flags & NGX_HTTP_ZERO_IN_URI) {
1815 r->zero_in_uri = 1;
1816 } 1851 }
1817 1852
1818 if (r->method != NGX_HTTP_HEAD) { 1853 if (r->method != NGX_HTTP_HEAD) {
1819 r->method = NGX_HTTP_GET; 1854 r->method = NGX_HTTP_GET;
1820 } 1855 }
1919 1954
1920 size = b->end - b->last; 1955 size = b->end - b->last;
1921 1956
1922 if (size == 0) { 1957 if (size == 0) {
1923 ngx_log_error(NGX_LOG_ALERT, c->log, 0, 1958 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1924 "upstream buffer is too small to read repsonse"); 1959 "upstream buffer is too small to read response");
1925 ngx_http_upstream_finalize_request(r, u, NGX_ERROR); 1960 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
1926 return; 1961 return;
1927 } 1962 }
1928 1963
1929 n = c->recv(c, b->last, size); 1964 n = c->recv(c, b->last, size);
2084 if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) { 2119 if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) {
2085 ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd); 2120 ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
2086 r->cache->file.fd = NGX_INVALID_FILE; 2121 r->cache->file.fd = NGX_INVALID_FILE;
2087 } 2122 }
2088 2123
2124 switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
2125
2126 case NGX_ERROR:
2127 ngx_http_upstream_finalize_request(r, u, 0);
2128 return;
2129
2130 case NGX_DECLINED:
2131 u->cacheable = 0;
2132 break;
2133
2134 default: /* NGX_OK */
2135
2136 if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
2137
2138 if (ngx_http_file_cache_new(r) != NGX_OK) {
2139 ngx_http_upstream_finalize_request(r, u, 0);
2140 return;
2141 }
2142
2143 if (u->create_key(r) != NGX_OK) {
2144 ngx_http_upstream_finalize_request(r, u, 0);
2145 return;
2146 }
2147
2148 /* TODO: add keys */
2149
2150 r->cache->min_uses = u->conf->cache_min_uses;
2151 r->cache->body_start = u->conf->buffer_size;
2152 r->cache->file_cache = u->conf->cache->data;
2153
2154 if (ngx_http_file_cache_create(r) != NGX_OK) {
2155 ngx_http_upstream_finalize_request(r, u, 0);
2156 return;
2157 }
2158
2159 u->cacheable = 1;
2160 }
2161
2162 break;
2163 }
2164
2089 if (u->cacheable) { 2165 if (u->cacheable) {
2090 time_t now, valid; 2166 time_t now, valid;
2091 2167
2092 now = ngx_time(); 2168 now = ngx_time();
2093 2169
2116 2192
2117 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 2193 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
2118 "http cacheable: %d", u->cacheable); 2194 "http cacheable: %d", u->cacheable);
2119 2195
2120 if (u->cacheable == 0 && r->cache) { 2196 if (u->cacheable == 0 && r->cache) {
2121 ngx_http_file_cache_free(r, u->pipe->temp_file); 2197 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
2122 } 2198 }
2123 2199
2124 #endif 2200 #endif
2125 2201
2126 p = u->pipe; 2202 p = u->pipe;
2591 /* TODO: check length & update cache */ 2667 /* TODO: check length & update cache */
2592 2668
2593 ngx_http_file_cache_update(r, u->pipe->temp_file); 2669 ngx_http_file_cache_update(r, u->pipe->temp_file);
2594 2670
2595 } else if (p->upstream_error) { 2671 } else if (p->upstream_error) {
2596 ngx_http_file_cache_free(r, u->pipe->temp_file); 2672 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
2597 } 2673 }
2598 } 2674 }
2599 2675
2600 #endif 2676 #endif
2601 2677
2919 #if (NGX_HTTP_CACHE) 2995 #if (NGX_HTTP_CACHE)
2920 2996
2921 if (u->cacheable && r->cache) { 2997 if (u->cacheable && r->cache) {
2922 time_t valid; 2998 time_t valid;
2923 2999
2924 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2925 "http upstream cache fd: %d",
2926 r->cache->file.fd);
2927
2928 if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) { 3000 if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
2929 3001
2930 valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc); 3002 valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
2931 3003
2932 if (valid) { 3004 if (valid) {
2933 r->cache->valid_sec = ngx_time() + valid; 3005 r->cache->valid_sec = ngx_time() + valid;
2934 r->cache->error = rc; 3006 r->cache->error = rc;
2935 } 3007 }
2936 } 3008 }
2937 3009
2938 ngx_http_file_cache_free(r, u->pipe->temp_file); 3010 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
2939 } 3011 }
2940 3012
2941 #endif 3013 #endif
2942 3014
2943 if (u->header_sent 3015 if (u->header_sent
2978 3050
2979 static ngx_int_t 3051 static ngx_int_t
2980 ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, 3052 ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
2981 ngx_uint_t offset) 3053 ngx_uint_t offset)
2982 { 3054 {
3055 return NGX_OK;
3056 }
3057
3058
3059 static ngx_int_t
3060 ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
3061 ngx_uint_t offset)
3062 {
3063 #if (NGX_HTTP_CACHE)
3064 ngx_http_upstream_t *u;
3065
3066 u = r->upstream;
3067
3068 if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
3069 u->cacheable = 0;
3070 }
3071 #endif
3072
2983 return NGX_OK; 3073 return NGX_OK;
2984 } 3074 }
2985 3075
2986 3076
2987 static ngx_int_t 3077 static ngx_int_t
3024 3114
3025 if (r->cache->valid_sec != 0) { 3115 if (r->cache->valid_sec != 0) {
3026 return NGX_OK; 3116 return NGX_OK;
3027 } 3117 }
3028 3118
3029 last = h->value.data + h->value.len; 3119 p = h->value.data;
3030 3120 last = p + h->value.len;
3031 if (ngx_strlcasestrn(h->value.data, last, (u_char *) "no-cache", 8 - 1) 3121
3032 != NULL) 3122 if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL
3123 || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL
3124 || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
3033 { 3125 {
3034 u->cacheable = 0; 3126 u->cacheable = 0;
3035 return NGX_OK; 3127 return NGX_OK;
3036 } 3128 }
3037 3129
3038 p = ngx_strlcasestrn(h->value.data, last, (u_char *) "max-age=", 8 - 1); 3130 p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
3039 3131
3040 if (p == NULL) { 3132 if (p == NULL) {
3041 return NGX_OK; 3133 return NGX_OK;
3042 } 3134 }
3043 3135
3710 3802
3711 for ( ;; ) { 3803 for ( ;; ) {
3712 if (state[i].status) { 3804 if (state[i].status) {
3713 ms = (ngx_msec_int_t) 3805 ms = (ngx_msec_int_t)
3714 (state[i].response_sec * 1000 + state[i].response_msec); 3806 (state[i].response_sec * 1000 + state[i].response_msec);
3715 ms = (ms >= 0) ? ms : 0; 3807 ms = ngx_max(ms, 0);
3716 p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000); 3808 p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
3717 3809
3718 } else { 3810 } else {
3719 *p++ = '-'; 3811 *p++ = '-';
3720 } 3812 }