diff src/http/modules/ngx_http_gzip_filter.c @ 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
line wrap: on
line diff
--- 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;
 }