changeset 135:e29909bd9b8a

nginx-0.0.1-2003-09-28-23:29:06 import
author Igor Sysoev <igor@sysoev.ru>
date Sun, 28 Sep 2003 19:29:06 +0000
parents d57c6835225c
children da00cde00e8a
files src/core/ngx_hunk.c src/core/ngx_modules.c src/core/ngx_string.h src/http/modules/ngx_http_chunked_filter.c src/http/modules/ngx_http_gzip_filter.c src/http/modules/ngx_http_not_modified_filter.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/ngx_http.h src/http/ngx_http_event.c src/http/ngx_http_header_filter.c src/http/ngx_http_output_filter.c src/http/ngx_http_request.h
diffstat 12 files changed, 232 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_hunk.c
+++ b/src/core/ngx_hunk.c
@@ -152,6 +152,10 @@ void ngx_chain_update_chains(ngx_chain_t
             break;
         }
 #endif
+        if (((*busy)->hunk->type & NGX_HUNK_TEMP) == 0) {
+            *busy = (*busy)->next;
+            continue;
+        }
 
         (*busy)->hunk->pos = (*busy)->hunk->last = (*busy)->hunk->start;
 
--- a/src/core/ngx_modules.c
+++ b/src/core/ngx_modules.c
@@ -34,6 +34,7 @@ extern ngx_module_t  ngx_http_header_fil
 
 extern ngx_module_t  ngx_http_chunked_filter_module;
 extern ngx_module_t  ngx_http_gzip_filter_module;
+extern ngx_module_t  ngx_http_not_modified_filter_module;
 extern ngx_module_t  ngx_http_range_filter_module;
 extern ngx_module_t  ngx_http_charset_filter_module;
 
@@ -83,6 +84,7 @@ ngx_module_t *ngx_modules[] = {
 
     &ngx_http_chunked_filter_module,
     &ngx_http_gzip_filter_module,
+    &ngx_http_not_modified_filter_module,
     &ngx_http_range_filter_module,
     /* &ngx_http_ssi_filter_module, */
     &ngx_http_charset_filter_module,
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -23,6 +23,7 @@ typedef struct {
 #define ngx_strncmp               strncmp
 #define ngx_strcmp                strcmp
 
+#define ngx_strstr                strstr
 #define ngx_strlen                strlen
 
 #define ngx_snprintf              _snprintf
@@ -35,6 +36,7 @@ typedef struct {
 #define ngx_strncmp               strncmp
 #define ngx_strcmp                strcmp
 
+#define ngx_strstr                strstr
 #define ngx_strlen                strlen
 
 #define ngx_snprintf              snprintf
--- a/src/http/modules/ngx_http_chunked_filter.c
+++ b/src/http/modules/ngx_http_chunked_filter.c
@@ -35,6 +35,10 @@ static int (*next_body_filter) (ngx_http
 
 static int ngx_http_chunked_header_filter(ngx_http_request_t *r)
 {
+    if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
+        return next_header_filter(r);
+    }
+
     if (r->headers_out.content_length == -1) {
         if (r->http_version < NGX_HTTP_VERSION_11) {
             r->keepalive = 0;
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -27,7 +27,9 @@ typedef struct {
     int            length;
     void          *alloc;
 
-    int            flush;
+    unsigned       flush:4;
+    unsigned       redo:1;
+
     u_int          crc32;
     z_stream       zstream;
 } ngx_http_gzip_ctx_t;
@@ -125,22 +127,26 @@ static int ngx_http_gzip_header_filter(n
     ngx_http_gzip_ctx_t   *ctx;
     ngx_http_gzip_conf_t  *conf;
 
-    if (r->headers_out.status != NGX_HTTP_OK
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
+
+    if (!conf->enable
+        || r->headers_out.status != NGX_HTTP_OK
         || r->header_only
-        /* || r->content_encoding */
-        /* || r->accept_encoding == NULL */
-        || r->main)
+        || r->main
+        /* TODO: conf->http_version */
+        || (r->headers_out.content_encoding
+            && r->headers_out.content_encoding->value.len)
+        || r->headers_in.accept_encoding == NULL
+        || ngx_strstr(r->headers_in.accept_encoding->value.data, "gzip") == NULL
+       )
     {
         return next_header_filter(r);
     }
 
-    conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
-    if (!conf->enable
-        /* TODO: conf->version */
-        /* TODO: "text/" -> custom types */
-        || ngx_strncasecmp(r->headers_out.content_type->value.data,
-                            "text/", 5) != 0)
+    /* TODO: "text/html" -> custom types */
+    if (r->headers_out.content_type
+        && ngx_strncasecmp(r->headers_out.content_type->value.data,
+                                                          "text/html", 5) != 0)
     {
         return next_header_filter(r);
     }
@@ -148,6 +154,15 @@ static int ngx_http_gzip_header_filter(n
     ngx_http_create_ctx(r, ctx, ngx_http_gzip_filter_module,
                         sizeof(ngx_http_gzip_ctx_t), NGX_ERROR);
 
+    ngx_test_null(r->headers_out.content_encoding,
+                  ngx_push_table(r->headers_out.headers),
+                  NGX_ERROR);
+
+    r->headers_out.content_encoding->key.len = 0;
+    r->headers_out.content_encoding->key.data = NULL;
+    r->headers_out.content_encoding->value.len = 4;
+    r->headers_out.content_encoding->value.data = "gzip";
+
     ctx->length = r->headers_out.content_length;
     r->headers_out.content_length = -1;
     r->filter |= NGX_HTTP_FILTER_NEED_IN_MEMORY;
@@ -212,38 +227,46 @@ static int ngx_http_gzip_body_filter(ngx
         }
     }
 
-    while (ctx->in || ctx->out
-           || ctx->zstream.avail_in || ctx->zstream.avail_out
-           || ctx->flush != Z_NO_FLUSH)
-    {
+    for ( ;; ) {
+
         for ( ;; ) {
 
-            if (ctx->in
-                && ctx->zstream.avail_in == 0
-                && ctx->flush == Z_NO_FLUSH)
-            {
+            /* is there a data to gzip ? */
+
+            if (ctx->zstream.avail_in == 0
+                && ctx->flush == Z_NO_FLUSH
+                && !ctx->redo) {
+
+                if (ctx->in == NULL) {
+                    break;
+                }
+
                 ctx->in_hunk = ctx->in->hunk;
                 ctx->in = ctx->in->next;
 
+                ctx->zstream.next_in = ctx->in_hunk->pos;
                 ctx->zstream.avail_in = ctx->in_hunk->last - ctx->in_hunk->pos;
 
-                if (ctx->zstream.avail_in == 0) {
-                    continue;
-                }
-
-                ctx->zstream.next_in = ctx->in_hunk->pos;
-
-                ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
-                                   ctx->zstream.avail_in);
-
                 if (ctx->in_hunk->type & NGX_HUNK_LAST) {
                     ctx->flush = Z_FINISH;
 
                 } else if (ctx->in_hunk->type & NGX_HUNK_FLUSH) {
                     ctx->flush = Z_SYNC_FLUSH;
                 }
+
+                if (ctx->zstream.avail_in == 0) {
+                    if (ctx->flush == Z_NO_FLUSH) {
+                        continue;
+                    }
+
+                } else {
+                    ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
+                                       ctx->zstream.avail_in);
+                }
             }
 
+            /* is there a space for the gzipped data ? */
+
             if (ctx->zstream.avail_out == 0) {
                 if (ctx->free) {
                     ctx->out_hunk = ctx->free->hunk;
@@ -257,13 +280,17 @@ static int ngx_http_gzip_body_filter(ngx
                     ctx->hunks++;
 
                 } else {
-                     break;
+                    break;
                 }
 
                 ctx->zstream.next_out = ctx->out_hunk->pos;
                 ctx->zstream.avail_out = conf->hunk_size;
             }
 
+ngx_log_debug(r->connection->log, "deflate(): %08x %08x %d %d %d" _
+              ctx->zstream.next_in _ ctx->zstream.next_out _
+              ctx->zstream.avail_in _ ctx->zstream.avail_out _ ctx->flush);
+
             rc = deflate(&ctx->zstream, ctx->flush);
             if (rc != Z_OK && rc != Z_STREAM_END) {
                 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
@@ -271,7 +298,9 @@ static int ngx_http_gzip_body_filter(ngx
                 return ngx_http_gzip_error(ctx);
             }
 
-ngx_log_debug(r->connection->log, "deflate(): %d %d" _ ctx->flush _ rc);
+ngx_log_debug(r->connection->log, "DEFLATE(): %08x %08x %d %d %d" _
+              ctx->zstream.next_in _ ctx->zstream.next_out _
+              ctx->zstream.avail_in _ ctx->zstream.avail_out _ rc);
 
             ctx->in_hunk->pos = ctx->zstream.next_in;
 
@@ -281,9 +310,11 @@ ngx_log_debug(r->connection->log, "defla
                                       ngx_http_gzip_error(ctx));
                 *ctx->last_out = ce;
                 ctx->last_out = &ce->next;
+                ctx->redo = 1;
 
             } else {
                 ctx->out_hunk->last = ctx->zstream.next_out;
+                ctx->redo = 0;
 
                 if (ctx->flush == Z_SYNC_FLUSH) {
                     ctx->out_hunk->type |= NGX_HUNK_FLUSH;
@@ -302,6 +333,13 @@ ngx_log_debug(r->connection->log, "defla
                     zin = ctx->zstream.total_in;
                     zout = 10 + ctx->zstream.total_out + 8;
 
+                    rc = deflateEnd(&ctx->zstream);
+                    if (rc != Z_OK) {
+                        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                                      "deflateEnd() failed: %d", rc);
+                        return ngx_http_gzip_error(ctx);
+                    }
+
                     ctx->flush = Z_NO_FLUSH;
 
                     ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool,
@@ -310,12 +348,25 @@ ngx_log_debug(r->connection->log, "defla
                     ctx->last_out = &ce->next;
 
                     if (ctx->zstream.avail_out >= 8) {
-                        trailer = (struct gztrailer *) &ctx->zstream.avail_in;
+                        trailer = (struct gztrailer *) ctx->out_hunk->last;
                         ctx->out_hunk->type |= NGX_HUNK_LAST;
                         ctx->out_hunk->last += 8;
 
                     } else {
-                        /* STUB */ trailer = NULL;
+                        ngx_test_null(h,
+                                      ngx_create_temp_hunk(r->pool, 8, 0, 0),
+                                      ngx_http_gzip_error(ctx));
+
+                        h->type |= NGX_HUNK_LAST;
+
+                        ngx_test_null(ce, ngx_alloc_chain_entry(r->pool),
+                                      ngx_http_gzip_error(ctx));
+                        ce->hunk = h;
+                        ce->next = NULL;
+                        *ctx->last_out = ce;
+                        ctx->last_out = &ce->next;
+                        trailer = (struct gztrailer *) h->pos;
+                        h->last += 8;
                     }
 
 #if (HAVE_LITTLE_ENDIAN)
@@ -325,10 +376,11 @@ ngx_log_debug(r->connection->log, "defla
                     /* STUB */
 #endif
 
-                    deflateEnd(&ctx->zstream);
+                    ctx->zstream.avail_in = 0;
+                    ctx->zstream.avail_out = 0;
+                    ngx_http_delete_ctx(r, ngx_http_gzip_filter_module);
 #if 0
                     ngx_free();
-                    set ctx = NULL;
 #endif
                     break;
 
@@ -343,17 +395,21 @@ ngx_log_debug(r->connection->log, "defla
             }
         }
 
-        rc = next_body_filter(r, ctx->out);
-        if (rc == NGX_ERROR) {
+        if (ctx->out == NULL) {
+            if (ctx->in || ctx->zstream.avail_in) {
+                return NGX_AGAIN;
+            } else {
+                return NGX_OK;
+            }
+        }
+
+        if (next_body_filter(r, ctx->out) == NGX_ERROR) {
             return ngx_http_gzip_error(ctx);
         }
 
         ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out);
         ctx->last_out = &ctx->out;
     }
-
-    /* STUB */
-    return next_body_filter(r, NULL);
 }
 
 
@@ -361,8 +417,13 @@ ngx_inline static int ngx_http_gzip_erro
 {
 #if 0
     ngx_free(ctx->alloc);
+#else
+    deflateEnd(&ctx->zstream);
 #endif
 
+    ctx->zstream.avail_in = 0;
+    ctx->zstream.avail_out = 0;
+
     return NGX_ERROR;
 }
 
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_not_modified_filter.c
@@ -0,0 +1,74 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+
+static int ngx_http_not_modified_filter_init(ngx_cycle_t *cycle);
+
+
+static ngx_http_module_t  ngx_http_not_modified_filter_module_ctx = {
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL                                   /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_not_modified_filter_module = {
+    NGX_MODULE,
+    &ngx_http_not_modified_filter_module_ctx, /* module context */
+    NULL,                                  /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_not_modified_filter_init,     /* init module */
+    NULL                                   /* init child */
+};
+
+
+static int (*next_header_filter) (ngx_http_request_t *r);
+
+
+static int ngx_http_not_modified_header_filter(ngx_http_request_t *r)
+{
+    time_t  ims;
+
+    if (r->headers_out.status != NGX_HTTP_OK
+        || r->headers_in.if_modified_since == NULL
+        || r->headers_out.last_modified_time == NULL)
+    {
+        return next_header_filter(r);
+    }
+
+    ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
+                              r->headers_in.if_modified_since->value.len);
+    
+    ngx_log_debug(r->connection->log, "%d %d" _
+                  ims _ r->headers_out.last_modified_time);
+
+    /* I think that the date equality is correcter */
+
+    if (ims != NGX_ERROR && ims == r->headers_out.last_modified_time) {
+        r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
+        r->headers_out.content_length = -1;
+        r->headers_out.content_type->key.len = 0;
+        r->headers_out.content_type = NULL;
+
+        /* TODO: delete "Accept-Ranges" header
+    }
+
+    return next_header_filter(r);
+}
+
+
+static int ngx_http_not_modified_filter_init(ngx_cycle_t *cycle)
+{
+    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_not_modified_header_filter;
+
+    return NGX_OK;
+}
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -79,11 +79,11 @@ int ngx_http_proxy_handler(ngx_http_requ
 
         if (rc == NGX_OK) {
             ngx_http_proxy_send_request(p->upstream.connection->write);
-            /* ??? */ return NGX_OK;
+            return NGX_OK;
         }
 
         if (rc == NGX_AGAIN) {
-            /* ??? */ return NGX_OK;
+            /* TODO */ return NGX_OK;
         }
 
         /* rc == NGX_CONNECT_FAILED */
@@ -116,9 +116,22 @@ static void ngx_http_proxy_send_request(
                 rc = ngx_event_connect_peer(&p->upstream);
 
                 if (rc == NGX_OK) {
-#if 0
-                    copy chain and hunks p->request_hunks from p->initial_request_hunks;
-#endif
+
+                    /* copy chain and hunks p->request_hunks
+                       from p->initial_request_hunks */
+
+                    p->request_hunks = NULL;
+                    if (ngx_chain_add_copy(r->pool, p->request_hunks,
+                                        p->initial_request_hunks) == NGX_ERROR)
+                    {
+                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                    }
+
+                    for (ce = p->request_hunks; ce; ce = ce->next) {
+                        ce->hunk->pos = ce->hunk->start;
+                    }
+
+
                     c = p->connection;
                     wev = c->write;
 
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -33,6 +33,8 @@ typedef int (*ngx_http_output_body_filte
                 r->ctx[module.ctx_index] = cx;                                \
             } while (0)
 
+#define ngx_http_delete_ctx(r, module)                                        \
+            r->ctx[module.ctx_index] = NULL;
 
 
 /* STUB */
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_event.c
@@ -49,6 +49,8 @@ static ngx_http_header_t headers_in[] = 
                          offsetof(ngx_http_headers_in_t, if_modified_since) },
     { ngx_string("Content-Length"),
                             offsetof(ngx_http_headers_in_t, content_length) },
+    { ngx_string("Accept-Encoding"),
+                           offsetof(ngx_http_headers_in_t, accept_encoding) },
 
     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) },
 #if 0
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -96,7 +96,6 @@ static ngx_str_t http_codes[] = {
 static int ngx_http_header_filter(ngx_http_request_t *r)
 {
     int                len, status, i;
-    time_t             ims;
     ngx_hunk_t        *h;
     ngx_chain_t       *ch;
     ngx_table_elt_t   *header;
@@ -130,26 +129,6 @@ static int ngx_http_header_filter(ngx_ht
        and 2 is for end of header */
     len = 9 + 2 + 2;
 
-    if (r->headers_in.if_modified_since && r->headers_out.status == NGX_HTTP_OK)
-    {
-        /* TODO: check LM header */
-        if (r->headers_out.last_modified_time) {
-            ims = ngx_http_parse_time(
-                                  r->headers_in.if_modified_since->value.data,
-                                  r->headers_in.if_modified_since->value.len);
-
-            ngx_log_debug(r->connection->log, "%d %d" _
-                          ims _ r->headers_out.last_modified_time);
-
-            /* I think that the date equality is correcter */
-            if (ims != NGX_ERROR && ims == r->headers_out.last_modified_time) {
-                r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
-                r->headers_out.content_length = -1;
-                r->headers_out.content_type->key.len = 0;
-            }
-        }
-    }
-
     /* status line */
     if (r->headers_out.status_line.len) {
         len += r->headers_out.status_line.len;
@@ -207,7 +186,7 @@ static int ngx_http_header_filter(ngx_ht
 
     if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
         r->headers_out.content_type->key.len = 0;
-        len += 16 + r->headers_out.content_type->value.len;
+        len += 14 + r->headers_out.content_type->value.len + 2;
 
         if (r->headers_out.charset.len) {
             /* "; charset= ... " */
@@ -215,6 +194,12 @@ static int ngx_http_header_filter(ngx_ht
         }
     }
 
+    if (r->headers_out.content_encoding
+        && r->headers_out.content_encoding->value.len)
+    {
+        len += 18 + r->headers_out.content_encoding->value.len + 2;
+    }
+
     if (r->headers_out.location
         && r->headers_out.location->value.len
         && r->headers_out.location->value.data[0] == '/')
@@ -316,6 +301,17 @@ static int ngx_http_header_filter(ngx_ht
         *(h->last++) = CR; *(h->last++) = LF;
     }
 
+    if (r->headers_out.content_encoding
+        && r->headers_out.content_encoding->value.len)
+    {
+        h->last = ngx_cpymem(h->last, "Content-Encoding: ", 18);
+        h->last = ngx_cpymem(h->last,
+                             r->headers_out.content_encoding->value.data,
+                             r->headers_out.content_encoding->value.len);
+
+        *(h->last++) = CR; *(h->last++) = LF;
+    }
+
     if (r->headers_out.location
         && r->headers_out.location->value.len
         && r->headers_out.location->value.data[0] == '/')
--- a/src/http/ngx_http_output_filter.c
+++ b/src/http/ngx_http_output_filter.c
@@ -151,8 +151,10 @@ int ngx_http_output_filter(ngx_http_requ
         }
 
         /* NGX_OK */
+#if 1
         /* set our hunk free */
         ctx->hunk->pos = ctx->hunk->last = ctx->hunk->start;
+#endif
     }
 
 #if (NGX_SUPPRESS_WARN)
@@ -225,8 +227,10 @@ int ngx_http_output_filter(ngx_http_requ
             }
 
             /* NGX_OK */
+#if 1
             /* set our hunk free */
             ctx->hunk->pos = ctx->hunk->last = ctx->hunk->start;
+#endif
 
             /* repeat until we will have copied the whole first hunk from
                the chain ctx->incoming */
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -117,6 +117,7 @@ typedef struct {
     ngx_table_elt_t  *server;
     ngx_table_elt_t  *date;
     ngx_table_elt_t  *content_type;
+    ngx_table_elt_t  *content_encoding;
     ngx_table_elt_t  *location;
     ngx_table_elt_t  *last_modified;
     ngx_table_elt_t  *content_range;