diff 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
line wrap: on
line diff
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -72,6 +72,8 @@ static void ngx_http_upstream_finalize_r
 
 static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
+    ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t
     ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
@@ -189,7 +191,7 @@ ngx_http_upstream_header_t  ngx_http_ups
                  ngx_http_upstream_rewrite_refresh, 0, 0 },
 
     { ngx_string("Set-Cookie"),
-                 ngx_http_upstream_ignore_header_line, 0,
+                 ngx_http_upstream_process_set_cookie, 0,
                  ngx_http_upstream_copy_header_line, 0, 1 },
 
     { ngx_string("Content-Disposition"),
@@ -355,6 +357,16 @@ ngx_conf_bitmask_t  ngx_http_upstream_ca
 };
 
 
+ngx_conf_bitmask_t  ngx_http_upstream_ignore_headers_masks[] = {
+    { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
+    { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
+    { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
+    { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
+    { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
+    { ngx_null_string, 0 }
+};
+
+
 ngx_int_t
 ngx_http_upstream_create(ngx_http_request_t *r)
 {
@@ -365,8 +377,6 @@ ngx_http_upstream_create(ngx_http_reques
     if (u && u->cleanup) {
         r->main->count++;
         ngx_http_upstream_cleanup(r);
-        *u->cleanup = NULL;
-        u->cleanup = NULL;
     }
 
     u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
@@ -564,6 +574,14 @@ ngx_http_upstream_init_request(ngx_http_
             }
         }
 
+        if (u->resolved->port == 0) {
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                          "no port in upstream \"%V\"", host);
+            ngx_http_upstream_finalize_request(r, u,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return;
+        }
+
         temp.name = *host;
 
         ctx = ngx_resolve_start(clcf->resolver, &temp);
@@ -623,6 +641,19 @@ ngx_http_upstream_cache(ngx_http_request
 
     if (c == NULL) {
 
+        switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
+
+        case NGX_ERROR:
+            return NGX_ERROR;
+
+        case NGX_DECLINED:
+            u->cache_status = NGX_HTTP_CACHE_BYPASS;
+            return NGX_DECLINED;
+
+        default: /* NGX_OK */
+            break;
+        }
+
         if (!(r->method & u->conf->cache_methods)) {
             return NGX_DECLINED;
         }
@@ -631,18 +662,10 @@ ngx_http_upstream_cache(ngx_http_request
             u->method = ngx_http_core_get_method;
         }
 
-        c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
-        if (c == NULL) {
+        if (ngx_http_file_cache_new(r) != NGX_OK) {
             return NGX_ERROR;
         }
 
-        if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
-            return NGX_ERROR;
-        }
-
-        r->cache = c;
-        c->file.log = r->connection->log;
-
         if (u->create_key(r) != NGX_OK) {
             return NGX_ERROR;
         }
@@ -653,6 +676,8 @@ ngx_http_upstream_cache(ngx_http_request
 
         u->cacheable = 1;
 
+        c = r->cache;
+
         c->min_uses = u->conf->cache_min_uses;
         c->body_start = u->conf->buffer_size;
         c->file_cache = u->conf->cache->data;
@@ -1703,6 +1728,21 @@ ngx_http_upstream_intercept_errors(ngx_h
                 r->headers_out.www_authenticate = h;
             }
 
+#if (NGX_HTTP_CACHE)
+
+            if (r->cache) {
+                time_t  valid;
+
+                valid = ngx_http_file_cache_valid(u->conf->cache_valid, status);
+
+                if (valid) {
+                    r->cache->valid_sec = ngx_time() + valid;
+                    r->cache->error = status;
+                }
+
+                ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
+            }
+#endif
             ngx_http_upstream_finalize_request(r, u, status);
 
             return NGX_OK;
@@ -1802,8 +1842,7 @@ ngx_http_upstream_process_headers(ngx_ht
         }
 
         uri = &u->headers_in.x_accel_redirect->value;
-        args.len = 0;
-        args.data = NULL;
+        ngx_str_null(&args);
         flags = NGX_HTTP_LOG_UNSAFE;
 
         if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
@@ -1811,10 +1850,6 @@ ngx_http_upstream_process_headers(ngx_ht
             return NGX_DONE;
         }
 
-        if (flags & NGX_HTTP_ZERO_IN_URI) {
-            r->zero_in_uri = 1;
-        }
-
         if (r->method != NGX_HTTP_HEAD) {
             r->method = NGX_HTTP_GET;
         }
@@ -1921,7 +1956,7 @@ ngx_http_upstream_process_body_in_memory
 
         if (size == 0) {
             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
-                          "upstream buffer is too small to read repsonse");
+                          "upstream buffer is too small to read response");
             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
             return;
         }
@@ -2086,6 +2121,47 @@ ngx_http_upstream_send_response(ngx_http
         r->cache->file.fd = NGX_INVALID_FILE;
     }
 
+    switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
+
+    case NGX_ERROR:
+        ngx_http_upstream_finalize_request(r, u, 0);
+        return;
+
+    case NGX_DECLINED:
+        u->cacheable = 0;
+        break;
+
+    default: /* NGX_OK */
+
+        if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
+
+            if (ngx_http_file_cache_new(r) != NGX_OK) {
+                ngx_http_upstream_finalize_request(r, u, 0);
+                return;
+            }
+
+            if (u->create_key(r) != NGX_OK) {
+                ngx_http_upstream_finalize_request(r, u, 0);
+                return;
+            }
+
+            /* TODO: add keys */
+
+            r->cache->min_uses = u->conf->cache_min_uses;
+            r->cache->body_start = u->conf->buffer_size;
+            r->cache->file_cache = u->conf->cache->data;
+
+            if (ngx_http_file_cache_create(r) != NGX_OK) {
+                ngx_http_upstream_finalize_request(r, u, 0);
+                return;
+            }
+
+            u->cacheable = 1;
+        }
+
+        break;
+    }
+
     if (u->cacheable) {
         time_t  now, valid;
 
@@ -2118,7 +2194,7 @@ ngx_http_upstream_send_response(ngx_http
                    "http cacheable: %d", u->cacheable);
 
     if (u->cacheable == 0 && r->cache) {
-        ngx_http_file_cache_free(r, u->pipe->temp_file);
+        ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
     }
 
 #endif
@@ -2593,7 +2669,7 @@ ngx_http_upstream_process_request(ngx_ht
                 ngx_http_file_cache_update(r, u->pipe->temp_file);
 
             } else if (p->upstream_error) {
-                ngx_http_file_cache_free(r, u->pipe->temp_file);
+                ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
             }
         }
 
@@ -2921,10 +2997,6 @@ ngx_http_upstream_finalize_request(ngx_h
     if (u->cacheable && r->cache) {
         time_t  valid;
 
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "http upstream cache fd: %d",
-                       r->cache->file.fd);
-
         if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
 
             valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
@@ -2935,7 +3007,7 @@ ngx_http_upstream_finalize_request(ngx_h
             }
         }
 
-        ngx_http_file_cache_free(r, u->pipe->temp_file);
+        ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
     }
 
 #endif
@@ -2985,6 +3057,24 @@ ngx_http_upstream_ignore_header_line(ngx
 
 
 static ngx_int_t
+ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
+    ngx_uint_t offset)
+{
+#if (NGX_HTTP_CACHE)
+    ngx_http_upstream_t  *u;
+
+    u = r->upstream;
+
+    if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
+        u->cacheable = 0;
+    }
+#endif
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset)
 {
@@ -3026,16 +3116,18 @@ ngx_http_upstream_process_cache_control(
         return NGX_OK;
     }
 
-    last = h->value.data + h->value.len;
-
-    if (ngx_strlcasestrn(h->value.data, last, (u_char *) "no-cache", 8 - 1)
-        != NULL)
+    p = h->value.data;
+    last = p + h->value.len;
+
+    if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL
+        || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL
+        || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
     {
         u->cacheable = 0;
         return NGX_OK;
     }
 
-    p = ngx_strlcasestrn(h->value.data, last, (u_char *) "max-age=", 8 - 1);
+    p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
 
     if (p == NULL) {
         return NGX_OK;
@@ -3712,7 +3804,7 @@ ngx_http_upstream_response_time_variable
         if (state[i].status) {
             ms = (ngx_msec_int_t)
                      (state[i].response_sec * 1000 + state[i].response_msec);
-            ms = (ms >= 0) ? ms : 0;
+            ms = ngx_max(ms, 0);
             p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
 
         } else {