diff src/http/modules/ngx_http_gzip_filter.c @ 2:cc9f381affaa NGINX_0_1_1

nginx 0.1.1 *) Feature: the gzip_types directive. *) Feature: the tcp_nodelay directive. *) Feature: the send_lowat directive is working not only on OSes that support kqueue NOTE_LOWAT, but also on OSes that support SO_SNDLOWAT. *) Feature: the setproctitle() emulation for Linux and Solaris. *) Bugfix: the "Location" header rewrite bug fixed while the proxying. *) Bugfix: the ngx_http_chunked_module module may get caught in an endless loop. *) Bugfix: the /dev/poll module bugs fixed. *) Bugfix: the responses were corrupted when the temporary files were used while the proxying. *) Bugfix: the unescaped requests were passed to the backend. *) Bugfix: while the build configuration on Linux 2.4 the --with-poll_module parameter was required.
author Igor Sysoev <http://sysoev.ru>
date Mon, 11 Oct 2004 00:00:00 +0400
parents f0b350454894
children 4b2dafa26fe2
line wrap: on
line diff
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -15,6 +15,8 @@ typedef struct {
     ngx_flag_t           enable;
     ngx_flag_t           no_buffer;
 
+    ngx_array_t         *types;     /* array of ngx_http_gzip_type_t */
+
     ngx_bufs_t           bufs;
 
     ngx_uint_t           http_version;
@@ -27,6 +29,12 @@ typedef struct {
 } ngx_http_gzip_conf_t;
 
 
+typedef struct {
+    ngx_str_t            name;
+    ngx_uint_t           enable;
+} ngx_http_gzip_type_t;
+
+
 #define NGX_HTTP_GZIP_PROXIED_OFF       0x0002
 #define NGX_HTTP_GZIP_PROXIED_EXPIRED   0x0004
 #define NGX_HTTP_GZIP_PROXIED_NO_CACHE  0x0008
@@ -57,10 +65,6 @@ typedef struct {
     unsigned             flush:4;
     unsigned             redo:1;
     unsigned             done:1;
-#if 0
-    unsigned             pass:1;
-    unsigned             blocked:1;
-#endif
 
     size_t               zin;
     size_t               zout;
@@ -86,6 +90,8 @@ static ngx_int_t ngx_http_gzip_filter_in
 static void *ngx_http_gzip_create_conf(ngx_conf_t *cf);
 static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf,
                                       void *parent, void *child);
+static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd,
+                                     void *conf);
 static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data);
 static char *ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data);
 
@@ -138,6 +144,13 @@ static ngx_command_t  ngx_http_gzip_filt
       offsetof(ngx_http_gzip_conf_t, bufs),
       NULL },
 
+    { ngx_string("gzip_types"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+      ngx_http_gzip_set_types,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
     { ngx_string("gzip_comp_level"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_num_slot,
@@ -211,7 +224,7 @@ ngx_module_t  ngx_http_gzip_filter_modul
     ngx_http_gzip_filter_commands,         /* module directives */
     NGX_HTTP_MODULE,                       /* module type */
     ngx_http_gzip_filter_init,             /* init module */
-    NULL                                   /* init child */
+    NULL                                   /* init process */
 };
 
 
@@ -247,15 +260,20 @@ static ngx_http_output_body_filter_pt   
 
 static ngx_int_t ngx_http_gzip_header_filter(ngx_http_request_t *r)
 {
+    ngx_uint_t             i, found;
     ngx_http_gzip_ctx_t   *ctx;
     ngx_http_gzip_conf_t  *conf;
+    ngx_http_gzip_type_t  *type;
 
     conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
 
     if (!conf->enable
-        || r->headers_out.status != NGX_HTTP_OK
+        || (r->headers_out.status != NGX_HTTP_OK
+            && r->headers_out.status != NGX_HTTP_FORBIDDEN
+            && r->headers_out.status != NGX_HTTP_NOT_FOUND)
         || r->header_only
         || r->http_version < conf->http_version
+        || r->headers_out.content_type == NULL
         || (r->headers_out.content_encoding
             && r->headers_out.content_encoding->value.len)
         || r->headers_in.accept_encoding == NULL
@@ -267,11 +285,21 @@ static ngx_int_t ngx_http_gzip_header_fi
         return ngx_http_next_header_filter(r);
     }
 
-    /* TODO: "text/html" -> custom types */
-    if (r->headers_out.content_type
-        && ngx_strncasecmp(r->headers_out.content_type->value.data,
-                                                          "text/html", 9) != 0)
-    {
+
+    found = 0;
+    type = conf->types->elts;
+
+    for (i = 0; i < conf->types->nelts; i++) {
+        if (r->headers_out.content_type->value.len >= type[i].name.len
+            && ngx_strncasecmp(r->headers_out.content_type->value.data, 
+                               type[i].name.data, type[i].name.len) == 0)
+        {
+            found = 1;
+            break;
+        }
+    }
+
+    if (!found) {
         return ngx_http_next_header_filter(r);
     }
 
@@ -572,15 +600,9 @@ static ngx_int_t ngx_http_gzip_body_filt
                     ctx->bufs++;
 
                 } else {
-#if 0
-                    ctx->blocked = 1;
-#endif
                     break;
                 }
 
-#if 0
-                ctx->blocked = 0;
-#endif
                 ctx->zstream.next_out = ctx->out_buf->pos;
                 ctx->zstream.avail_out = conf->bufs.size;
             }
@@ -646,10 +668,6 @@ static ngx_int_t ngx_http_gzip_body_filt
                 *ctx->last_out = cl;
                 ctx->last_out = &cl->next;
 
-#if 0
-                ctx->pass = 1;
-#endif
-
                 break;
             }
 
@@ -712,9 +730,6 @@ static ngx_int_t ngx_http_gzip_body_filt
                 ctx->zstream.avail_out = 0;
 
                 ctx->done = 1;
-#if 0
-                ctx->pass = 1;
-#endif
 
                 break;
             }
@@ -725,47 +740,10 @@ static ngx_int_t ngx_http_gzip_body_filt
                 *ctx->last_out = cl;
                 ctx->last_out = &cl->next;
 
-#if 0
-                ctx->pass = 1;
-#endif
-
                 break;
             }
         }
 
-#if 0
-
-        /* OLD CODE */
-
-        if (ctx->out) {
-            if (ctx->pass) {
-                ctx->pass = 0;
-
-            } else if (last == NGX_AGAIN) {
-                return last;
-            }
-
-        } else if (ctx->busy->buf && ngx_buf_size(ctx->busy->buf)) {
-            if (last != NGX_NONE) {
-                return last;
-            }
-
-        } else if (ctx->blocked) {
-            if (last != NGX_NONE) {
-                return last;
-            }
-
-        } else {
-            if (last == NGX_NONE) {
-                return NGX_OK;
-            }
-
-            return last;
-        }
-#endif
-
-        /* NEW CODE */
-
         if (last == NGX_AGAIN) {
             return NGX_AGAIN;
         }
@@ -774,8 +752,6 @@ static ngx_int_t ngx_http_gzip_body_filt
             return NGX_OK;
         }
 
-        /**/
-
         last = ngx_http_next_body_filter(r, ctx->out);
 
         /*
@@ -866,7 +842,7 @@ static u_char *ngx_http_gzip_log_ratio(n
                               (float) ctx->zin / ctx->zout);
 #endif
 
-    /* we prefer do not use FPU */
+    /* we prefer do not use the FPU */
 
     zint = (ngx_uint_t) (ctx->zin / ctx->zout);
     zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100);
@@ -947,6 +923,8 @@ static void *ngx_http_gzip_create_conf(n
     conf->bufs.num = 0;
     conf->proxied = 0;
 
+    conf->types = NULL;
+
      */
 
     conf->enable = NGX_CONF_UNSET;
@@ -969,6 +947,8 @@ static char *ngx_http_gzip_merge_conf(ng
     ngx_http_gzip_conf_t *prev = parent;
     ngx_http_gzip_conf_t *conf = child;
 
+    ngx_http_gzip_type_t  *type;
+
     ngx_conf_merge_value(conf->enable, prev->enable, 0);
 
     ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, ngx_pagesize);
@@ -986,6 +966,77 @@ static char *ngx_http_gzip_merge_conf(ng
     ngx_conf_merge_value(conf->min_length, prev->min_length, 0);
     ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0);
 
+    if (conf->types == NULL) {
+        if (prev->types == NULL) {
+            conf->types = ngx_array_create(cf->pool, 1,
+                                           sizeof(ngx_http_gzip_type_t));
+            if (conf->types == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            if (!(type = ngx_array_push(conf->types))) {
+                return NGX_CONF_ERROR;
+            }
+
+            type->name.len = sizeof("text/html") - 1;
+            type->name.data = (u_char *) "text/html";
+            type->enable = 1;
+
+        } else {
+            conf->types = prev->types;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd,
+                                     void *conf)
+{
+    ngx_http_gzip_conf_t *gcf = conf;
+
+    ngx_str_t             *value;
+    ngx_uint_t             i;
+    ngx_http_gzip_type_t  *type;
+
+    if (gcf->types == NULL) {
+        gcf->types = ngx_array_create(cf->pool, 5,
+                                       sizeof(ngx_http_gzip_type_t));
+        if (gcf->types == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        if (!(type = ngx_array_push(gcf->types))) {
+            return NGX_CONF_ERROR;
+        }
+
+        type->name.len = sizeof("text/html") - 1;
+        type->name.data = (u_char *) "text/html";
+        type->enable = 1;
+    }
+
+    value = cf->args->elts;
+
+    for (i = 1; i < cf->args->nelts; i++) {
+
+        if (ngx_strcmp(value[i].data, "text/html") == 0) {
+            continue;
+        }
+
+        if (!(type = ngx_array_push(gcf->types))) {
+            return NGX_CONF_ERROR;
+        }
+
+        type->name.len = value[i].len;
+
+        if (!(type->name.data = ngx_palloc(cf->pool, type->name.len + 1))) {
+            return NGX_CONF_ERROR;
+        }
+
+        ngx_cpystrn(type->name.data, value[i].data, type->name.len + 1);
+    }
+
     return NGX_CONF_OK;
 }