diff src/http/modules/proxy/ngx_http_proxy_handler.c @ 148:5afee0074707

nginx-0.0.1-2003-10-17-00:19:16 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 16 Oct 2003 20:19:16 +0000
parents ef8c87afcfc5
children ad5f382c9e7d
line wrap: on
line diff
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -17,7 +17,8 @@ static void ngx_http_proxy_process_upstr
 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev);
 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *);
 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_process_upstream_body(ngx_event_t *rev);
+static void ngx_http_proxy_process_upstream(ngx_event_t *rev);
+static void ngx_http_proxy_process_downstream(ngx_event_t *wev);
 
 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p);
 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p);
@@ -27,8 +28,21 @@ static void ngx_http_proxy_close_connect
 static int ngx_http_proxy_init(ngx_cycle_t *cycle);
 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
 
+static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
+                                     void *conf);
+static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
+                                           ngx_http_proxy_upstream_t *u);
+
 
 static ngx_command_t ngx_http_proxy_commands[] = {
+
+    {ngx_string("proxy_pass"),
+     NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_http_proxy_set_pass,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     0,
+     NULL},
+
     ngx_null_command
 };
 
@@ -54,7 +68,7 @@ ngx_module_t  ngx_http_proxy_module = {
     &ngx_http_proxy_module_ctx,            /* module context */
     ngx_http_proxy_commands,               /* module directives */
     NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_proxy_init,                   /* init module */
+    NULL,                                  /* init module */
     NULL                                   /* init child */
 };
 
@@ -99,22 +113,9 @@ static char conn_close_header[] = "Conne
 
 
 
-static int ngx_http_proxy_translate_handler(ngx_http_request_t *r)
-{
-#if 0
-    r->handler = ngx_http_proxy_handler;
-    return NGX_OK;
-#else
-    return NGX_DECLINED;
-#endif
-}
-
-
 static int ngx_http_proxy_handler(ngx_http_request_t *r)
 {
-    int                         rc;
-    ngx_http_proxy_ctx_t       *p;
-    ngx_http_proxy_loc_conf_t  *lcf;
+    ngx_http_proxy_ctx_t  *p;
 
     ngx_http_create_ctx(r, p, ngx_http_proxy_module,
                         sizeof(ngx_http_proxy_ctx_t),
@@ -126,6 +127,8 @@ static int ngx_http_proxy_handler(ngx_ht
 
     p->request = r;
     p->method = r->method;
+
+    /* TODO: from lcf->upstream */
     p->uri.data = "/";
     p->uri.len = 1;
     p->location_len = 1;
@@ -144,7 +147,7 @@ static int ngx_http_proxy_handler(ngx_ht
 
     ngx_http_proxy_send_request(p);
 
-    return NGX_OK;
+    return NGX_DONE;
 }
 
 
@@ -580,7 +583,6 @@ static void ngx_http_proxy_process_upstr
 
 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
 {
-    int           event;
     ssize_t       n;
     ngx_event_t  *rev;
 
@@ -589,7 +591,10 @@ static ssize_t ngx_http_proxy_read_upstr
     n = p->header_in->last - p->header_in->pos;
 
     if (n > 0) {
+#if 0
+        /* TODO THINK */
         rev->ready = 0;
+#endif
         return n;
     }
 
@@ -700,11 +705,12 @@ static void ngx_http_proxy_send_response
         return;
     }
 
+    ep->input_filter = ngx_event_proxy_copy_input_filter;
     ep->output_filter = (ngx_event_proxy_output_filter_pt)
                                                         ngx_http_output_filter;
-    ep->output_data = r;
-    ep->block_size = p->lcf->block_size;
-    ep->max_block_size = p->lcf->max_block_size;
+    ep->output_ctx = r;
+    ep->bufs = p->lcf->bufs;
+    ep->max_busy_len = p->lcf->max_busy_len;
     ep->upstream = p->upstream.connection;
     ep->downstream = r->connection;
     ep->pool = r->pool;
@@ -742,16 +748,18 @@ static void ngx_http_proxy_send_response
     lcx->action = "reading an upstream";
 #endif
 
-    ngx_event_proxy_read_upstream(ep);
+    p->upstream.connection->read->event_handler =
+                                               ngx_http_proxy_process_upstream;
+    r->connection->write->event_handler =
+                                             ngx_http_proxy_process_downstream;
 
-    p->upstream.connection->read->event_handler =
-                                          ngx_http_proxy_process_upstream_body;
+    ngx_http_proxy_process_upstream(p->upstream.connection->read);
 
     return;
 }
 
 
-static void ngx_http_proxy_process_upstream_body(ngx_event_t *rev)
+static void ngx_http_proxy_process_upstream(ngx_event_t *rev)
 {
     ngx_connection_t      *c;
     ngx_http_proxy_ctx_t  *p;
@@ -759,25 +767,58 @@ static void ngx_http_proxy_process_upstr
     c = rev->data;
     p = c->data;
 
-    ngx_log_debug(rev->log, "http proxy process upstream body");
+    ngx_log_debug(rev->log, "http proxy process upstream");
 
     if (rev->timedout) {
-        ngx_http_proxy_close_connection(p->upstream.connection);
+        ngx_http_proxy_close_connection(c);
         p->upstream.connection = NULL;
         return;
     }
 
-    ngx_event_proxy_read_upstream(p->event_proxy);
+    if (ngx_event_proxy_read_upstream(p->event_proxy) == NGX_ABORT) {
+        ngx_http_proxy_finalize_request(p, 0);
+        return;
+    }
 
-    if (p->event_proxy->upstream_eof) {
-        ngx_http_proxy_close_connection(p->upstream.connection);
-        p->upstream.connection = NULL;
+    if (p->event_proxy->upstream_eof
+        || p->event_proxy->upstream_error
+        || p->event_proxy->upstream_done)
+    {
+        ngx_http_proxy_finalize_request(p, ngx_http_send_last(p->request));
         return;
     }
 
-    if (p->event_proxy->upstream_error) {
-        ngx_http_proxy_close_connection(p->upstream.connection);
-        p->upstream.connection = NULL;
+    return;
+}
+
+
+static void ngx_http_proxy_process_downstream(ngx_event_t *wev)
+{
+    ngx_connection_t      *c;
+    ngx_http_proxy_ctx_t  *p;
+
+    c = wev->data;
+    p = c->data;
+
+    ngx_log_debug(wev->log, "http proxy process downstream");
+
+    if (wev->timedout) {
+        ngx_http_close_connection(c);
+        return;
+    }
+
+    if (ngx_event_proxy_write_to_downstream(p->event_proxy) == NGX_ABORT) {
+        ngx_http_proxy_finalize_request(p, 0);
+        return;
+    }
+
+    if (p->event_proxy->downstream_done) {
+        ngx_http_proxy_finalize_request(p, 0);
+        return;
+    }
+
+    if (p->event_proxy->downstream_error) {
+        ngx_http_close_connection(c);
         return;
     }
 
@@ -1076,25 +1117,6 @@ static size_t ngx_http_proxy_log_error(v
 }
 
 
-static int ngx_http_proxy_init(ngx_cycle_t *cycle)
-{
-    ngx_http_handler_pt        *h;
-    ngx_http_conf_ctx_t        *ctx;
-    ngx_http_core_main_conf_t  *cmcf;
-
-    ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
-    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
-
-    ngx_test_null(h, ngx_push_array(
-                             &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers),
-                  NGX_ERROR);
-
-    *h = ngx_http_proxy_translate_handler;
-
-    return NGX_OK;
-}
-
-
 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
 {
     int                         i;
@@ -1121,8 +1143,9 @@ static void *ngx_http_proxy_create_loc_c
     conf->header_size = 4096;
     conf->read_timeout = 30000;
 
-    conf->block_size = 4096;
-    conf->max_block_size = 4096 * 3;
+    conf->bufs.num = 10;
+    conf->bufs.size = 4096;
+    conf->max_busy_len = 8192 + 4096;
     conf->max_temp_file_size = 4096 * 5;
     conf->temp_file_write_size = 4096 * 2;
 
@@ -1147,3 +1170,206 @@ static void *ngx_http_proxy_create_loc_c
 
     return conf;
 }
+
+
+static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
+                                     void *conf)
+{
+    ngx_http_proxy_loc_conf_t *lcf = conf;
+
+    int                        i, len;
+    char                      *err, *host;
+    ngx_str_t                 *value;
+    struct hostent            *h;
+    u_int32_t                  addr;
+    ngx_http_conf_ctx_t       *ctx;
+    ngx_http_core_loc_conf_t  *clcf;
+
+
+    value = cf->args->elts;
+
+    if (ngx_strncasecmp(value[1].data, "http://", 7) != 0) {
+        return "invalid URL prefix";
+    }
+
+    ngx_test_null(lcf->upstream,
+                  ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_upstream_t)),
+                  NGX_CONF_ERROR);
+
+    value[1].data += 7;
+    value[1].len -= 7;
+
+    err = ngx_http_proxy_parse_upstream(&value[1], lcf->upstream);
+
+    if (err) {
+        return err;
+    }
+
+    ngx_test_null(host, ngx_palloc(cf->pool, lcf->upstream->host.len + 1),
+                  NGX_CONF_ERROR);
+    ngx_cpystrn(host, lcf->upstream->host.data, lcf->upstream->host.len + 1);
+
+    addr = inet_addr(host);
+
+    if (addr == INADDR_NONE) {
+        h = gethostbyname(host);
+
+        if (h == NULL || h->h_addr_list[0] == NULL) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "host %s not found", host);
+            return NGX_CONF_ERROR;
+        }
+
+        for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
+
+        /* MP: ngx_shared_palloc() */
+
+        ngx_test_null(lcf->peers,
+                      ngx_pcalloc(cf->pool,
+                                  sizeof(ngx_peers_t)
+                                  + sizeof(ngx_peer_t) * (i - 1)),
+                      NGX_CONF_ERROR);
+
+        lcf->peers->number = i;
+
+        for (i = 0; h->h_addr_list[i] != NULL; i++) {
+            lcf->peers->peers[i].host.data = host;
+            lcf->peers->peers[i].host.len = lcf->upstream->host.len;
+            lcf->peers->peers[i].addr = *(u_int32_t *)(h->h_addr_list[i]);
+            lcf->peers->peers[i].port = lcf->upstream->port;
+
+            len = INET_ADDRSTRLEN + lcf->upstream->port_text.len + 1;
+            ngx_test_null(lcf->peers->peers[i].addr_port_text.data,
+                          ngx_palloc(cf->pool, len),
+                          NGX_CONF_ERROR);
+
+            len = ngx_inet_ntop(AF_INET,
+                                (char *) &lcf->peers->peers[i].addr,
+                                lcf->peers->peers[i].addr_port_text.data,
+                                len);
+
+            lcf->peers->peers[i].addr_port_text.data[len++] = ':';
+
+            ngx_cpystrn(lcf->peers->peers[i].addr_port_text.data + len,
+                        lcf->upstream->port_text.data,
+                        lcf->upstream->port_text.len + 1);
+
+            lcf->peers->peers[i].addr_port_text.len =
+                                        len + lcf->upstream->port_text.len + 1;
+        }
+
+    } else {
+
+        /* MP: ngx_shared_palloc() */
+
+        ngx_test_null(lcf->peers, ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)),
+                      NGX_CONF_ERROR);
+
+        lcf->peers->number = 1;
+
+        lcf->peers->peers[0].host.data = host;
+        lcf->peers->peers[0].host.len = lcf->upstream->host.len;
+        lcf->peers->peers[0].addr = addr;
+        lcf->peers->peers[0].port = lcf->upstream->port;
+
+        len = lcf->upstream->host.len + lcf->upstream->port_text.len + 1;
+
+        ngx_test_null(lcf->peers->peers[0].addr_port_text.data,
+                      ngx_palloc(cf->pool, len + 1),
+                      NGX_CONF_ERROR);
+
+        len = lcf->upstream->host.len;
+
+        ngx_memcpy(lcf->peers->peers[0].addr_port_text.data,
+                   lcf->upstream->host.data, len);
+
+        lcf->peers->peers[0].addr_port_text.data[len++] = ':';
+
+        ngx_cpystrn(lcf->peers->peers[0].addr_port_text.data + len,
+                    lcf->upstream->port_text.data,
+                    lcf->upstream->port_text.len + 1);
+    }
+
+    ctx = cf->ctx;
+    clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
+    lcf->upstream->location = &clcf->name;
+    clcf->handler = ngx_http_proxy_handler;
+
+    return NULL;
+}
+
+static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
+                                           ngx_http_proxy_upstream_t *u)
+{
+    size_t  i;
+
+    if (url->data[0] == ':' || url->data[0] == '/') {
+        return "invalid upstream URL";
+    }
+
+    u->host.data = url->data;
+    u->host_header.data = url->data;
+
+    for (i = 1; i < url->len; i++) {
+        if (url->data[i] == ':') {
+            u->port_text.data = &url->data[i] + 1;
+            u->host.len = i;
+        }
+
+        if (url->data[i] == '/') {
+            u->uri.data = &url->data[i];
+            u->uri.len = url->len - i;
+            u->host_header.len = i;
+
+            if (u->host.len == 0) {
+                u->host.len = i;
+            }
+
+            if (u->port_text.data == NULL) {
+                u->port = htons(80);
+                u->port_text.len = 2;
+                u->port_text.data = "80";
+                return NULL;
+            }
+
+            u->port_text.len = &url->data[i] - u->port_text.data;
+
+            if (u->port_text.len > 0) {
+                u->port = ngx_atoi(u->port_text.data, u->port_text.len);
+                if (u->port > 0) {
+                    u->port = htons((u_short) u->port);
+                    return NULL;
+                }
+            }
+
+            return "invalid port in upstream URL";
+        }
+    }
+
+    if (u->host.len == 0) {
+        u->host.len = i;
+    }
+
+    u->host_header.len = i;
+
+    u->uri.data = "/";
+    u->uri.len = 1;
+
+    if (u->port_text.data == NULL) {
+        u->port = htons(80);
+        u->port_text.len = 2;
+        u->port_text.data = "80";
+        return NULL;
+    }
+
+    u->port_text.len = &url->data[i] - u->port_text.data;
+
+    if (u->port_text.len > 0) {
+        u->port = ngx_atoi(u->port_text.data, u->port_text.len);
+        if (u->port > 0) {
+            u->port = htons((u_short) u->port);
+            return NULL;
+        }
+    }
+
+    return "invalid port in upstream URL";
+}