changeset 139:54307053f185

nginx-0.0.1-2003-10-07-19:30:05 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 07 Oct 2003 15:30:05 +0000
parents 3b168e12bd2d
children e32405df0e77
files src/event/ngx_event.h src/event/ngx_event_connect.c src/event/ngx_event_proxy.c src/event/ngx_event_proxy.h src/http/modules/ngx_http_charset_filter.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h
diffstat 7 files changed, 257 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -289,6 +289,7 @@ typedef struct {
 /* ***************************** */
 
 #define ngx_recv             ngx_io.recv
+#define ngx_recv_chain       ngx_io.recv_chain
 #define ngx_write_chain      ngx_io.send_chain
 
 
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -193,6 +193,8 @@ int ngx_event_connect_peer(ngx_peer_conn
                               ngx_close_socket_n " failed");
             }
 
+            c->fd = -1;
+
             return NGX_CONNECT_ERROR;
         }
     }
--- a/src/event/ngx_event_proxy.c
+++ b/src/event/ngx_event_proxy.c
@@ -1,4 +1,7 @@
 
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
 #include <ngx_event_proxy.h>
 
 
@@ -46,7 +49,7 @@ ngx_log_debug(p->log, "read upstream");
 
 #if (HAVE_KQUEUE) /* kqueue notifies about the end of file or a pending error */
 
-            if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) {
+            if (ngx_event_flags == NGX_HAVE_KQUEUE_EVENT) {
 
                 if (p->upstream->read->error) {
                     ngx_log_error(NGX_LOG_ERR, p->log,
--- a/src/event/ngx_event_proxy.h
+++ b/src/event/ngx_event_proxy.h
@@ -4,10 +4,7 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_hunk.h>
-#include <ngx_file.h>
-#include <ngx_files.h>
-#include <ngx_connection.h>
+#include <ngx_event.h>
 
 
 typedef struct ngx_event_proxy_s  ngx_event_proxy_t;
--- a/src/http/modules/ngx_http_charset_filter.c
+++ b/src/http/modules/ngx_http_charset_filter.c
@@ -60,8 +60,13 @@ static int ngx_http_charset_header_filte
 {
     ngx_http_charset_loc_conf_t  *lcf;
 
-    if (ngx_strncasecmp(r->headers_out.content_type->value.data, "text/", 5)
-                                                                        != 0) {
+    if (r->headers_out.content_type == NULL
+        || ngx_strncasecmp(r->headers_out.content_type->value.data,
+                                                           "text/", 5) != 0
+        || ngx_strstr(r->headers_out.content_type->value.data, "charset")
+                                                                       != NULL
+       )
+    {
         return next_header_filter(r);
     }
 
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -3,6 +3,7 @@
 #include <ngx_core.h>
 #include <ngx_event.h>
 /* STUB */ #include <ngx_event_connect.h>
+/* STUB */ #include <ngx_event_proxy.h>
 #include <ngx_http.h>
 #include <ngx_http_proxy_handler.h>
 
@@ -15,8 +16,12 @@ static void ngx_http_proxy_send_request(
 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev);
 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 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);
+static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
 static void ngx_http_proxy_close_connection(ngx_connection_t *c);
 
 static int ngx_http_proxy_init(ngx_cycle_t *cycle);
@@ -81,6 +86,8 @@ static ngx_http_header_t headers_in[] = 
                        offsetof(ngx_http_proxy_headers_in_t, content_length) },
     { ngx_string("Last-Modified"),
                         offsetof(ngx_http_proxy_headers_in_t, last_modified) },
+    { ngx_string("Accept-Ranges"),
+                        offsetof(ngx_http_proxy_headers_in_t, accept_ranges) },
 
     { ngx_null_string, 0 }
 };
@@ -119,6 +126,8 @@ static int ngx_http_proxy_handler(ngx_ht
     p->uri.len = 1;
     p->location_len = 1;
 
+    /* STUB */ p->accel = 1;
+
     p->host_header = p->upstream.peers->peers[0].host;
 
     ngx_test_null(p->request_hunks, ngx_http_proxy_create_request(p),
@@ -296,8 +305,8 @@ static void ngx_http_proxy_send_request(
             rc = ngx_event_connect_peer(&p->upstream);
 
             if (rc == NGX_ERROR) {
-                ngx_http_finalize_request(p->request,
-                                          NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_proxy_finalize_request(p,
+                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
             }
 
@@ -305,8 +314,7 @@ static void ngx_http_proxy_send_request(
                 ngx_event_connect_peer_failed(&p->upstream);
 
                 if (p->upstream.tries == 0) {
-                    ngx_http_finalize_request(p->request,
-                                              NGX_HTTP_BAD_GATEWAY);
+                    ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
                     return;
                 }
 
@@ -330,9 +338,8 @@ static void ngx_http_proxy_send_request(
                 p->work_request_hunks =
                                        ngx_alloc_chain_entry(p->request->pool);
                 if (p->work_request_hunks == NULL) {
-                    ngx_http_proxy_close_connection(c);
-                    ngx_http_finalize_request(p->request,
-                                              NGX_HTTP_INTERNAL_SERVER_ERROR);
+                    ngx_http_proxy_finalize_request(p,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
                     return;
                 }
 
@@ -346,8 +353,7 @@ static void ngx_http_proxy_send_request(
 
                     te = ngx_alloc_chain_entry(p->request->pool);
                     if (te == NULL) {
-                        ngx_http_proxy_close_connection(c);
-                        ngx_http_finalize_request(p->request,
+                        ngx_http_proxy_finalize_request(p,
                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
                         return;
                     }
@@ -396,9 +402,7 @@ static void ngx_http_proxy_process_upstr
                                             p->lcf->header_size,
                                             0, 0);
         if (p->header_in == NULL) {
-            ngx_http_proxy_close_connection(c);
-            ngx_http_finalize_request(p->request,
-                                      NGX_HTTP_INTERNAL_SERVER_ERROR);
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
             return;
         }
     }
@@ -420,8 +424,7 @@ static void ngx_http_proxy_process_upstr
         if (p->header_in->pos == p->header_in->last) {
             ngx_log_error(NGX_LOG_ERR, rev->log, 0,
                           "upstream sent too big header");
-            ngx_http_proxy_close_connection(c);
-            ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
             return;
         }
 
@@ -438,8 +441,7 @@ static void ngx_http_proxy_process_upstr
     p->status_line.len = p->status_end - p->status_start;
     p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1);
     if (p->status_line.data == NULL) {
-        ngx_http_proxy_close_connection(c);
-        ngx_http_finalize_request(p->request, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
     ngx_cpystrn(p->status_line.data, p->status_start, p->status_line.len + 1);
@@ -461,7 +463,6 @@ static void ngx_http_proxy_process_upstr
 }
 
 
-
 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
 {
     int                    i, rc;
@@ -506,9 +507,8 @@ static void ngx_http_proxy_process_upstr
 
             h = ngx_push_table(p->headers_in.headers);
             if (h == NULL) {
-                ngx_http_proxy_close_connection(c);
-                ngx_http_finalize_request(p->request,
-                                          NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_proxy_finalize_request(p,
+                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
             }
 
@@ -518,9 +518,8 @@ static void ngx_http_proxy_process_upstr
             h->key.data = ngx_palloc(p->request->pool,
                                      h->key.len + 1 + h->value.len + 1);
             if (h->key.data == NULL) {
-                ngx_http_proxy_close_connection(c);
-                ngx_http_finalize_request(p->request,
-                                          NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_proxy_finalize_request(p,
+                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
             }
 
@@ -550,6 +549,8 @@ static void ngx_http_proxy_process_upstr
 
             ngx_log_debug(c->log, "HTTP header done");
 
+            ngx_http_proxy_send_response(p);
+
             return;
 
         } else if (rc != NGX_AGAIN) {
@@ -560,8 +561,7 @@ static void ngx_http_proxy_process_upstr
             ngx_http_header_parse_error(r, rc);
             ngx_http_proxy_next_upstream(p);
 #endif
-            ngx_http_proxy_close_connection(c);
-            ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
             return;
         }
 
@@ -570,8 +570,7 @@ static void ngx_http_proxy_process_upstr
         if (p->header_in->last == p->header_in->end) {
             ngx_log_error(NGX_LOG_ERR, rev->log, 0,
                           "upstream sent too big header");
-            ngx_http_proxy_close_connection(c);
-            ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
             return;
         }
     }
@@ -616,9 +615,8 @@ static ssize_t ngx_http_proxy_read_upstr
             }
 
             if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
-                ngx_http_proxy_close_connection(p->upstream.connection);
-                ngx_http_finalize_request(p->request,
-                                          NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_proxy_finalize_request(p,
+                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return NGX_ERROR;
             }
         }
@@ -641,6 +639,156 @@ static ssize_t ngx_http_proxy_read_upstr
 }
 
 
+static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
+{
+    int                  rc, i;
+    ngx_table_elt_t     *ch, *ph;
+    ngx_event_proxy_t   *ep;
+    ngx_http_request_t  *r;
+
+    r = p->request;
+
+    r->headers_out.content_length = -1;
+
+    /* copy an upstream header to r->headers_out */
+
+    ph = (ngx_table_elt_t *) p->headers_in.headers->elts;
+    for (i = 0; i < p->headers_in.headers->nelts; i++) {
+
+        if (&ph[i] == p->headers_in.connection) {
+            continue;
+        }
+
+        if (p->accel) {
+            if (&ph[i] == p->headers_in.date
+                || &ph[i] == p->headers_in.accept_ranges) {
+                continue;
+            }
+        }
+
+        if (&ph[i] == p->headers_in.content_length) {
+            r->headers_out.content_length =
+                             ngx_atoi(p->headers_in.content_length->value.data,
+                                      p->headers_in.content_length->value.len);
+            continue;
+        }
+
+        ch = ngx_push_table(r->headers_out.headers);
+        if (ch == NULL) {
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return;
+        }
+
+        *ch = ph[i];
+
+        if (&ph[i] == p->headers_in.content_type) {
+            r->headers_out.content_type = ch;
+            r->headers_out.content_type->key.len = 0;
+            continue;
+        }
+    }
+
+    /* STUB */
+
+    if (p->headers_in.server) {
+        r->headers_out.server = p->headers_in.server;
+    }
+
+    if (!p->accel && p->headers_in.date) {
+        r->headers_out.date = p->headers_in.date;
+    }
+
+    /* */
+
+#if 0
+    /* TODO: look "Content-Length" */
+    p->block_size = p->lcf->block_size;
+#endif
+
+    r->headers_out.status = p->status;
+
+    rc = ngx_http_send_header(r);
+
+    p->header_sent = 1;
+
+    ep = ngx_pcalloc(r->pool, sizeof(ngx_event_proxy_t));
+    if (ep == NULL) {
+        ngx_http_proxy_finalize_request(p, 0);
+        return;
+    }
+
+    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->upstream = p->upstream.connection;
+    ep->downstream = r->connection;
+    ep->pool = r->pool;
+    ep->log = r->connection->log;
+    ep->temp_path = p->lcf->temp_path;
+
+    ep->temp_file = ngx_palloc(r->pool, sizeof(ngx_file_t));
+    if (ep->temp_file == NULL) {
+        ngx_http_proxy_finalize_request(p, 0);
+        return;
+    }
+
+    ep->temp_file->fd = NGX_INVALID_FILE;
+    ep->temp_file->log = r->connection->log;
+
+    ep->max_temp_file_size = p->lcf->max_temp_file_size;
+    ep->temp_file_write_size = p->lcf->temp_file_write_size;
+    ep->temp_file_warn = "an upstream response is buffered "
+                         "to a temporary file";
+
+    ep->preread_hunks = ngx_alloc_chain_entry(r->pool);
+    if (ep->preread_hunks == NULL) {
+        ngx_http_proxy_finalize_request(p, 0);
+        return;
+    }
+    ep->preread_hunks->hunk = p->header_in;
+    ep->preread_hunks->next = NULL;
+
+    ep->preread_size = p->header_in->last - p->header_in->pos;
+
+    p->event_proxy = ep;
+
+#if 0
+    lcx = p->log->data;
+    lcx->action = "reading an upstream";
+#endif
+
+    ngx_event_proxy_read_upstream(ep);
+
+    p->upstream.connection->read->event_handler =
+                                          ngx_http_proxy_process_upstream_body;
+
+    return;
+}
+
+
+static void ngx_http_proxy_process_upstream_body(ngx_event_t *rev)
+{
+    ngx_connection_t      *c;
+    ngx_http_proxy_ctx_t  *p;
+
+    c = rev->data;
+    p = c->data;
+
+    ngx_log_debug(rev->log, "http proxy process upstream body");
+
+    if (rev->timedout) {
+        ngx_http_proxy_next_upstream(p);
+        return;
+    }
+
+    ngx_event_proxy_read_upstream(p->event_proxy);
+
+    return;
+}
+
+
 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p)
 {
     char   ch;
@@ -839,25 +987,49 @@ static int ngx_http_proxy_parse_status_l
     return NGX_AGAIN;
 }
 
+
 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p)
 {
     if (p->upstream.connection) {
         ngx_http_proxy_close_connection(p->upstream.connection);
         p->upstream.connection = NULL;
+    }
 
+    if (!p->fatal_error) {
         ngx_http_proxy_send_request(p);
     }
 
     return;
 }
 
+static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
+{
+    if (p->upstream.connection) {
+        ngx_http_proxy_close_connection(p->upstream.connection);
+        p->upstream.connection = NULL;
+    }
+
+    if (p->header_sent) {
+        rc = 0;
+    }
+
+    ngx_http_finalize_request(p->request, rc);
+
+    p->fatal_error = 1;
+
+    return;
+}
+
+
 
 static void ngx_http_proxy_close_connection(ngx_connection_t *c)
 {
     ngx_log_debug(c->log, "close connection: %d" _ c->fd);
 
     if (c->fd == -1) {
+#if 0
         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
+#endif
         return;
     }
 
@@ -927,6 +1099,7 @@ static int ngx_http_proxy_init(ngx_cycle
 
 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
 {
+    int                         i;
     ngx_http_proxy_loc_conf_t  *conf;
 
     ngx_test_null(conf,
@@ -949,6 +1122,29 @@ static void *ngx_http_proxy_create_loc_c
     conf->send_timeout = 30000;
     conf->header_size = 4096;
     conf->read_timeout = 30000;
+
+    conf->block_size = 4096;
+    conf->max_block_size = 4096 * 3;
+    conf->max_temp_file_size = 4096 * 5;
+    conf->temp_file_write_size = 4096 * 2;
+
+    ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)),
+                  NULL);
+
+    conf->temp_path->name.data = "temp";
+    conf->temp_path->name.len = 4;
+    conf->temp_path->level[0] = 1;
+    conf->temp_path->level[1] = 2;
+    conf->temp_path->level[2] = 3;
+    conf->temp_path->len = 0;
+
+    for (i = 0; i < 3; i++) {
+        if (conf->temp_path->level[i] == 0) {
+            break;
+        }
+        conf->temp_path->len += conf->temp_path->level[i] + 1;
+    }
+
     /* */
 
     return conf;
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -14,6 +14,15 @@ typedef struct {
     ssize_t       header_size;
     ngx_msec_t    read_timeout;
 
+    /* STUB */
+    int           block_size;
+    int           max_block_size;
+    int           max_temp_file_size;
+    int           temp_file_write_size;
+    /* */
+
+    ngx_path_t   *temp_path;
+
     ngx_peers_t  *peers;
 } ngx_http_proxy_loc_conf_t;
 
@@ -25,6 +34,7 @@ typedef struct {
     ngx_table_elt_t  *content_type;
     ngx_table_elt_t  *content_length;
     ngx_table_elt_t  *last_modified;
+    ngx_table_elt_t  *accept_ranges;
 
     ngx_table_t      *headers;
 } ngx_http_proxy_headers_in_t;
@@ -52,6 +62,12 @@ struct ngx_http_proxy_ctx_s {
     int                         location_len;
     ngx_str_t                   host_header;
 
+    ngx_event_proxy_t          *event_proxy;
+
+    unsigned                    accel:1;
+    unsigned                    fatal_error:1;
+    unsigned                    header_sent:1;
+
     /* used to parse an upstream HTTP header */
     char                       *status_start;
     char                       *status_end;