diff src/http/ngx_http_upstream.c @ 348:e10168d6e371 NGINX_0_6_18

nginx 0.6.18 *) Change: now the ngx_http_userid_module adds start time microseconds to the cookie field contains a pid value. *) Change: now the full request line instead of URI only is written to error_log. *) Feature: variables support in the "proxy_pass" directive. *) Feature: the "resolver" and "resolver_timeout" directives. *) Feature: now the directive "add_header last-modified ''" deletes a "Last-Modified" response header line. *) Bugfix: the "limit_rate" directive did not allow to use full throughput, even if limit value was very high.
author Igor Sysoev <http://sysoev.ru>
date Tue, 27 Nov 2007 00:00:00 +0300
parents 05693816539c
children 583decdb82a4
line wrap: on
line diff
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -9,6 +9,7 @@
 #include <ngx_http.h>
 
 
+static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
@@ -283,10 +284,15 @@ static ngx_http_variable_t  ngx_http_ups
 void
 ngx_http_upstream_init(ngx_http_request_t *r)
 {
-    ngx_connection_t          *c;
-    ngx_http_cleanup_t        *cln;
-    ngx_http_upstream_t       *u;
-    ngx_http_core_loc_conf_t  *clcf;
+    ngx_str_t                      *host;
+    ngx_uint_t                      i;
+    ngx_connection_t               *c;
+    ngx_resolver_ctx_t             *ctx, temp;
+    ngx_http_cleanup_t             *cln;
+    ngx_http_upstream_t            *u;
+    ngx_http_core_loc_conf_t       *clcf;
+    ngx_http_upstream_srv_conf_t   *uscf, **uscfp;
+    ngx_http_upstream_main_conf_t  *umcf;
 
     c = r->connection;
 
@@ -320,11 +326,6 @@ ngx_http_upstream_init(ngx_http_request_
         u->request_bufs = r->request_body->bufs;
     }
 
-    if (u->conf->upstream->peer.init(r, u->conf->upstream) != NGX_OK) {
-        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
-        return;
-    }
-
     if (u->create_request(r) != NGX_OK) {
         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
@@ -332,7 +333,7 @@ ngx_http_upstream_init(ngx_http_request_
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    u->output.sendfile = r->connection->sendfile;
+    u->output.sendfile = c->sendfile;
     u->output.pool = r->pool;
     u->output.bufs.num = 1;
     u->output.bufs.size = clcf->client_body_buffer_size;
@@ -374,11 +375,125 @@ ngx_http_upstream_init(ngx_http_request_
 
     u->store = (u->conf->store || u->conf->store_lengths);
 
+    if (u->resolved == NULL) {
+
+        uscf = u->conf->upstream;
+
+    } else {
+
+        host = &r->upstream->resolved->host;
+
+        umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
+
+        uscfp = umcf->upstreams.elts;
+
+        for (i = 0; i < umcf->upstreams.nelts; i++) {
+
+            uscf = uscfp[i];
+
+            if (uscf->host.len == host->len
+                && ngx_memcmp(uscf->host.data, host->data, host->len) == 0)
+            {
+                goto found;
+            }
+        }
+
+        if (clcf->resolver == NULL) {
+            ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                          "no resolver defined to resolve %V", host);
+            ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
+            return;
+        }
+
+        temp.name = *host;
+
+        ctx = ngx_resolve_start(clcf->resolver, &temp);
+        if (ctx == NULL) {
+            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return;
+        }
+
+        ctx->name = *host;
+        ctx->type = NGX_RESOLVE_A;
+        ctx->handler = ngx_http_upstream_resolve_handler;
+        ctx->data = r;
+        ctx->timeout = clcf->resolver_timeout;
+
+        u->resolved->ctx = ctx;
+
+        if (ngx_resolve_name(ctx) != NGX_OK) {
+            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return;
+        }
+
+        return;
+    }
+
+found:
+
+    if (uscf->peer.init(r, uscf) != NGX_OK) {
+        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        return;
+    }
+
     ngx_http_upstream_connect(r, u);
 }
 
 
 static void
+ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
+{
+    ngx_http_request_t            *r;
+    ngx_http_upstream_resolved_t  *ur;
+
+    r = ctx->data;
+
+    r->upstream->resolved->ctx = NULL;
+
+    if (ctx->state) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "%V could not be resolved (%i: %s)",
+                      &ctx->name, ctx->state,
+                      ngx_resolver_strerror(ctx->state));
+
+        ngx_resolve_name_done(ctx);
+        ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
+        return;
+    }
+
+    ur = r->upstream->resolved;
+    ur->naddrs = ctx->naddrs;
+    ur->addrs = ctx->addrs;
+
+#if (NGX_DEBUG)
+    {
+    in_addr_t   addr;
+    ngx_uint_t  i;
+
+    for (i = 0; i < ctx->naddrs; i++) {
+        addr = ntohl(ur->addrs[i]);
+
+        ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "name was resolved to %ud.%ud.%ud.%ud",
+                       (addr >> 24) & 0xff, (addr >> 16) & 0xff,
+                       (addr >> 8) & 0xff, addr & 0xff);
+    }
+    }
+#endif
+
+    if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK) {
+        ngx_resolve_name_done(ctx);
+        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        return;
+    }
+
+    ngx_resolve_name_done(ctx);
+
+    ngx_http_upstream_connect(r, r->upstream);
+}
+
+
+static void
 ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r)
 {
     ngx_http_upstream_check_broken_connection(r, r->connection->read);
@@ -549,6 +664,7 @@ ngx_http_upstream_connect(ngx_http_reque
     tp = ngx_timeofday();
     u->state->response_sec = tp->sec;
     u->state->response_msec = tp->msec;
+    u->state->peer = u->peer.name;
 
     rc = ngx_event_connect_peer(&u->peer);
 
@@ -561,8 +677,6 @@ ngx_http_upstream_connect(ngx_http_reque
         return;
     }
 
-    u->state->peer = u->peer.name;
-
     if (rc == NGX_BUSY) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE);
@@ -638,7 +752,7 @@ ngx_http_upstream_connect(ngx_http_reque
 
 #if (NGX_HTTP_SSL)
 
-    if (u->conf->ssl && c->ssl == NULL) {
+    if (u->ssl && c->ssl == NULL) {
         ngx_http_upstream_ssl_init_connection(r, u, c);
         return;
     }
@@ -893,7 +1007,7 @@ ngx_http_upstream_send_request_handler(n
 
 #if (NGX_HTTP_SSL)
 
-    if (u->conf->ssl && c->ssl == NULL) {
+    if (u->ssl && c->ssl == NULL) {
         ngx_http_upstream_ssl_init_connection(r, u, c);
         return;
     }
@@ -2260,6 +2374,10 @@ ngx_http_upstream_cleanup(void *data)
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "cleanup http upstream request: \"%V\"", &r->uri);
 
+    if (r->upstream->resolved && r->upstream->resolved->ctx) {
+        ngx_resolve_name_done(r->upstream->resolved->ctx);
+    }
+
     ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE);
 }
 
@@ -2275,7 +2393,7 @@ ngx_http_upstream_finalize_request(ngx_h
 
     *u->cleanup = NULL;
 
-    if (u->state->response_sec) {
+    if (u->state && u->state->response_sec) {
         tp = ngx_timeofday();
         u->state->response_sec = tp->sec - u->state->response_sec;
         u->state->response_msec = tp->msec - u->state->response_msec;
@@ -2283,7 +2401,9 @@ ngx_http_upstream_finalize_request(ngx_h
 
     u->finalize_request(r, rc);
 
-    u->peer.free(&u->peer, u->peer.data, 0);
+    if (u->peer.free) {
+        u->peer.free(&u->peer, u->peer.data, 0);
+    }
 
     if (u->peer.connection) {
 
@@ -2609,6 +2729,10 @@ ngx_http_upstream_rewrite_location(ngx_h
         return rc;
     }
 
+    if (ho->value.data[0] != '/') {
+        r->headers_out.location = ho;
+    }
+
     /*
      * we do not set r->headers_out.location here to avoid the handling
      * the local redirects without a host name by ngx_http_header_filter()
@@ -2648,16 +2772,18 @@ ngx_http_upstream_rewrite_refresh(ngx_ht
             return NGX_OK;
         }
 
-#if (NGX_DEBUG)
         if (rc == NGX_OK) {
+            r->headers_out.refresh = ho;
+
             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                            "rewritten refresh: \"%V\"", &ho->value);
         }
-#endif
 
         return rc;
     }
 
+    r->headers_out.refresh = ho;
+
     return NGX_OK;
 }