[nginx] svn commit: r4838 - in trunk: auto src/http/modules

mdounin at mdounin.ru mdounin at mdounin.ru
Mon Sep 10 16:52:48 UTC 2012


Author: mdounin
Date: 2012-09-10 16:52:47 +0000 (Mon, 10 Sep 2012)
New Revision: 4838
URL: http://trac.nginx.org/nginx/changeset/4838/nginx

Log:
Gunzip filter import.


Added:
   trunk/src/http/modules/ngx_http_gunzip_filter_module.c
Modified:
   trunk/auto/modules
   trunk/auto/options
   trunk/auto/sources

Modified: trunk/auto/modules
===================================================================
--- trunk/auto/modules	2012-09-10 16:48:25 UTC (rev 4837)
+++ trunk/auto/modules	2012-09-10 16:52:47 UTC (rev 4838)
@@ -109,6 +109,7 @@
 #         ngx_http_image_filter
 #         ngx_http_sub_filter
 #         ngx_http_addition_filter
+#         ngx_http_gunzip_filter
 #         ngx_http_userid_filter
 #         ngx_http_headers_filter
 #     ngx_http_copy_filter
@@ -166,6 +167,13 @@
     HTTP_SRCS="$HTTP_SRCS $HTTP_ADDITION_SRCS"
 fi
 
+if [ $HTTP_GUNZIP = YES ]; then
+    have=NGX_HTTP_GZIP . auto/have
+    USE_ZLIB=YES
+    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_GUNZIP_FILTER_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_GUNZIP_SRCS"
+fi
+
 if [ $HTTP_USERID = YES ]; then
     HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_USERID_FILTER_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS"

Modified: trunk/auto/options
===================================================================
--- trunk/auto/options	2012-09-10 16:48:25 UTC (rev 4837)
+++ trunk/auto/options	2012-09-10 16:52:47 UTC (rev 4838)
@@ -94,6 +94,7 @@
 HTTP_DEGRADATION=NO
 HTTP_FLV=NO
 HTTP_MP4=NO
+HTTP_GUNZIP=NO
 HTTP_GZIP_STATIC=NO
 HTTP_UPSTREAM_IP_HASH=YES
 HTTP_UPSTREAM_LEAST_CONN=YES
@@ -210,6 +211,7 @@
         --with-http_dav_module)          HTTP_DAV=YES               ;;
         --with-http_flv_module)          HTTP_FLV=YES               ;;
         --with-http_mp4_module)          HTTP_MP4=YES               ;;
+        --with-http_gunzip_module)       HTTP_GUNZIP=YES            ;;
         --with-http_gzip_static_module)  HTTP_GZIP_STATIC=YES       ;;
         --with-http_random_index_module) HTTP_RANDOM_INDEX=YES      ;;
         --with-http_secure_link_module)  HTTP_SECURE_LINK=YES       ;;
@@ -356,6 +358,7 @@
   --with-http_dav_module             enable ngx_http_dav_module
   --with-http_flv_module             enable ngx_http_flv_module
   --with-http_mp4_module             enable ngx_http_mp4_module
+  --with-http_gunzip_module          enable ngx_http_gunzip_module
   --with-http_gzip_static_module     enable ngx_http_gzip_static_module
   --with-http_random_index_module    enable ngx_http_random_index_module
   --with-http_secure_link_module     enable ngx_http_secure_link_module

Modified: trunk/auto/sources
===================================================================
--- trunk/auto/sources	2012-09-10 16:48:25 UTC (rev 4837)
+++ trunk/auto/sources	2012-09-10 16:52:47 UTC (rev 4838)
@@ -331,6 +331,10 @@
 HTTP_GZIP_SRCS=src/http/modules/ngx_http_gzip_filter_module.c
 
 
+HTTP_GUNZIP_FILTER_MODULE=ngx_http_gunzip_filter_module
+HTTP_GUNZIP_SRCS=src/http/modules/ngx_http_gunzip_filter_module.c
+
+
 HTTP_SSI_FILTER_MODULE=ngx_http_ssi_filter_module
 HTTP_SSI_DEPS=src/http/modules/ngx_http_ssi_filter_module.h
 HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter_module.c

Added: trunk/src/http/modules/ngx_http_gunzip_filter_module.c
===================================================================
--- trunk/src/http/modules/ngx_http_gunzip_filter_module.c	                        (rev 0)
+++ trunk/src/http/modules/ngx_http_gunzip_filter_module.c	2012-09-10 16:52:47 UTC (rev 4838)
@@ -0,0 +1,677 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) Maxim Dounin
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+#include <nginx.h>
+
+#include <zlib.h>
+
+
+typedef struct {
+    ngx_flag_t           enable;
+    ngx_bufs_t           bufs;
+} ngx_http_gunzip_conf_t;
+
+
+typedef struct {
+    ngx_chain_t         *in;
+    ngx_chain_t         *free;
+    ngx_chain_t         *busy;
+    ngx_chain_t         *out;
+    ngx_chain_t        **last_out;
+
+    ngx_buf_t           *in_buf;
+    ngx_buf_t           *out_buf;
+    ngx_int_t            bufs;
+
+    unsigned             started:1;
+    unsigned             flush:4;
+    unsigned             redo:1;
+    unsigned             done:1;
+    unsigned             nomem:1;
+
+    z_stream             zstream;
+    ngx_http_request_t  *request;
+} ngx_http_gunzip_ctx_t;
+
+
+static ngx_int_t ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx);
+static ngx_int_t ngx_http_gunzip_filter_add_data(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx);
+static ngx_int_t ngx_http_gunzip_filter_get_buf(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx);
+static ngx_int_t ngx_http_gunzip_filter_inflate(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx);
+static ngx_int_t ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx);
+
+static void *ngx_http_gunzip_filter_alloc(void *opaque, u_int items,
+    u_int size);
+static void ngx_http_gunzip_filter_free(void *opaque, void *address);
+
+static ngx_int_t ngx_http_gunzip_filter_init(ngx_conf_t *cf);
+static void *ngx_http_gunzip_create_conf(ngx_conf_t *cf);
+static char *ngx_http_gunzip_merge_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+
+
+static ngx_command_t  ngx_http_gunzip_filter_commands[] = {
+
+    { ngx_string("gunzip"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gunzip_conf_t, enable),
+      NULL },
+
+    { ngx_string("gunzip_buffers"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+      ngx_conf_set_bufs_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gunzip_conf_t, bufs),
+      NULL },
+
+      ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_gunzip_filter_module_ctx = {
+    NULL,                                  /* preconfiguration */
+    ngx_http_gunzip_filter_init,           /* postconfiguration */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_gunzip_create_conf,           /* create location configuration */
+    ngx_http_gunzip_merge_conf             /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_gunzip_filter_module = {
+    NGX_MODULE_V1,
+    &ngx_http_gunzip_filter_module_ctx,    /* module context */
+    ngx_http_gunzip_filter_commands,       /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    NULL,                                  /* init master */
+    NULL,                                  /* init module */
+    NULL,                                  /* init process */
+    NULL,                                  /* init thread */
+    NULL,                                  /* exit thread */
+    NULL,                                  /* exit process */
+    NULL,                                  /* exit master */
+    NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
+
+
+static ngx_int_t
+ngx_http_gunzip_header_filter(ngx_http_request_t *r)
+{
+    ngx_http_gunzip_ctx_t   *ctx;
+    ngx_http_gunzip_conf_t  *conf;
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
+
+    /* TODO support multiple content-codings */
+    /* TODO always gunzip - due to configuration or module request */
+    /* TODO ignore content encoding? */
+
+    if (!conf->enable
+        || r->headers_out.content_encoding == NULL
+        || r->headers_out.content_encoding->value.len != 4
+        || ngx_strncasecmp(r->headers_out.content_encoding->value.data,
+                           (u_char *) "gzip", 4) != 0)
+    {
+        return ngx_http_next_header_filter(r);
+    }
+
+    r->gzip_vary = 1;
+
+    if (!r->gzip_tested) {
+        if (ngx_http_gzip_ok(r) == NGX_OK) {
+            return ngx_http_next_header_filter(r);
+        }
+
+    } else if (!r->gzip_ok) {
+        return ngx_http_next_header_filter(r);
+    }
+
+    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gunzip_ctx_t));
+    if (ctx == NULL) {
+        return NGX_ERROR;
+    }
+
+    ngx_http_set_ctx(r, ctx, ngx_http_gunzip_filter_module);
+
+    ctx->request = r;
+
+    r->filter_need_in_memory = 1;
+
+    r->headers_out.content_encoding->hash = 0;
+    r->headers_out.content_encoding = NULL;
+
+    ngx_http_clear_content_length(r);
+    ngx_http_clear_accept_ranges(r);
+
+    return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    int                     rc;
+    ngx_chain_t            *cl;
+    ngx_http_gunzip_ctx_t  *ctx;
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_gunzip_filter_module);
+
+    if (ctx == NULL || ctx->done) {
+        return ngx_http_next_body_filter(r, in);
+    }
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http gunzip filter");
+
+    if (!ctx->started) {
+        if (ngx_http_gunzip_filter_inflate_start(r, ctx) != NGX_OK) {
+            goto failed;
+        }
+    }
+
+    if (in) {
+        if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
+            goto failed;
+        }
+    }
+
+    if (ctx->nomem) {
+
+        /* flush busy buffers */
+
+        if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) {
+            goto failed;
+        }
+
+        cl = NULL;
+
+        ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
+                                (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
+        ctx->nomem = 0;
+    }
+
+    for ( ;; ) {
+
+        /* cycle while we can write to a client */
+
+        for ( ;; ) {
+
+            /* cycle while there is data to feed zlib and ... */
+
+            rc = ngx_http_gunzip_filter_add_data(r, ctx);
+
+            if (rc == NGX_DECLINED) {
+                break;
+            }
+
+            if (rc == NGX_AGAIN) {
+                continue;
+            }
+
+
+            /* ... there are buffers to write zlib output */
+
+            rc = ngx_http_gunzip_filter_get_buf(r, ctx);
+
+            if (rc == NGX_DECLINED) {
+                break;
+            }
+
+            if (rc == NGX_ERROR) {
+                goto failed;
+            }
+
+            rc = ngx_http_gunzip_filter_inflate(r, ctx);
+
+            if (rc == NGX_OK) {
+                break;
+            }
+
+            if (rc == NGX_ERROR) {
+                goto failed;
+            }
+
+            /* rc == NGX_AGAIN */
+        }
+
+        if (ctx->out == NULL) {
+            return ctx->busy ? NGX_AGAIN : NGX_OK;
+        }
+
+        rc = ngx_http_next_body_filter(r, ctx->out);
+
+        if (rc == NGX_ERROR) {
+            goto failed;
+        }
+
+        ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out,
+                                (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
+        ctx->last_out = &ctx->out;
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "gunzip out: %p", ctx->out);
+
+        ctx->nomem = 0;
+
+        if (ctx->done) {
+            return rc;
+        }
+    }
+
+    /* unreachable */
+
+failed:
+
+    ctx->done = 1;
+
+    return NGX_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx)
+{
+    int  rc;
+
+    ctx->zstream.next_in = Z_NULL;
+    ctx->zstream.avail_in = 0;
+
+    ctx->zstream.zalloc = ngx_http_gunzip_filter_alloc;
+    ctx->zstream.zfree = ngx_http_gunzip_filter_free;
+    ctx->zstream.opaque = ctx;
+
+    /* windowBits +16 to decode gzip, zlib 1.2.0.4+ */
+    rc = inflateInit2(&ctx->zstream, MAX_WBITS + 16);
+
+    if (rc != Z_OK) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      "inflateInit2() failed: %d", rc);
+        return NGX_ERROR;
+    }
+
+    ctx->started = 1;
+
+    ctx->last_out = &ctx->out;
+    ctx->flush = Z_NO_FLUSH;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_gunzip_filter_add_data(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx)
+{
+    if (ctx->zstream.avail_in || ctx->flush != Z_NO_FLUSH || ctx->redo) {
+        return NGX_OK;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "gunzip in: %p", ctx->in);
+
+    if (ctx->in == NULL) {
+        return NGX_DECLINED;
+    }
+
+    ctx->in_buf = ctx->in->buf;
+    ctx->in = ctx->in->next;
+
+    ctx->zstream.next_in = ctx->in_buf->pos;
+    ctx->zstream.avail_in = ctx->in_buf->last - ctx->in_buf->pos;
+
+    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "gunzip in_buf:%p ni:%p ai:%ud",
+                   ctx->in_buf,
+                   ctx->zstream.next_in, ctx->zstream.avail_in);
+
+    if (ctx->in_buf->last_buf || ctx->in_buf->last_in_chain) {
+        ctx->flush = Z_FINISH;
+
+    } else if (ctx->in_buf->flush) {
+        ctx->flush = Z_SYNC_FLUSH;
+
+    } else if (ctx->zstream.avail_in == 0) {
+        /* ctx->flush == Z_NO_FLUSH */
+        return NGX_AGAIN;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_gunzip_filter_get_buf(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx)
+{
+    ngx_http_gunzip_conf_t  *conf;
+
+    if (ctx->zstream.avail_out) {
+        return NGX_OK;
+    }
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
+
+    if (ctx->free) {
+        ctx->out_buf = ctx->free->buf;
+        ctx->free = ctx->free->next;
+
+        ctx->out_buf->flush = 0;
+
+    } else if (ctx->bufs < conf->bufs.num) {
+
+        ctx->out_buf = ngx_create_temp_buf(r->pool, conf->bufs.size);
+        if (ctx->out_buf == NULL) {
+            return NGX_ERROR;
+        }
+
+        ctx->out_buf->tag = (ngx_buf_tag_t) &ngx_http_gunzip_filter_module;
+        ctx->out_buf->recycled = 1;
+        ctx->bufs++;
+
+    } else {
+        ctx->nomem = 1;
+        return NGX_DECLINED;
+    }
+
+    ctx->zstream.next_out = ctx->out_buf->pos;
+    ctx->zstream.avail_out = conf->bufs.size;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_gunzip_filter_inflate(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx)
+{
+    int           rc;
+    ngx_buf_t    *b;
+    ngx_chain_t  *cl;
+
+    ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "inflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d",
+                   ctx->zstream.next_in, ctx->zstream.next_out,
+                   ctx->zstream.avail_in, ctx->zstream.avail_out,
+                   ctx->flush, ctx->redo);
+
+    rc = inflate(&ctx->zstream, ctx->flush);
+
+    if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      "inflate() failed: %d, %d", ctx->flush, rc);
+        return NGX_ERROR;
+    }
+
+    ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
+                   ctx->zstream.next_in, ctx->zstream.next_out,
+                   ctx->zstream.avail_in, ctx->zstream.avail_out,
+                   rc);
+
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "gunzip in_buf:%p pos:%p",
+                   ctx->in_buf, ctx->in_buf->pos);
+
+    if (ctx->zstream.next_in) {
+        ctx->in_buf->pos = ctx->zstream.next_in;
+
+        if (ctx->zstream.avail_in == 0) {
+            ctx->zstream.next_in = NULL;
+        }
+    }
+
+    ctx->out_buf->last = ctx->zstream.next_out;
+
+    if (ctx->zstream.avail_out == 0) {
+
+        /* zlib wants to output some more data */
+
+        cl = ngx_alloc_chain_link(r->pool);
+        if (cl == NULL) {
+            return NGX_ERROR;
+        }
+
+        cl->buf = ctx->out_buf;
+        cl->next = NULL;
+        *ctx->last_out = cl;
+        ctx->last_out = &cl->next;
+
+        ctx->redo = 1;
+
+        return NGX_AGAIN;
+    }
+
+    ctx->redo = 0;
+
+    if (ctx->flush == Z_SYNC_FLUSH) {
+
+        ctx->flush = Z_NO_FLUSH;
+
+        cl = ngx_alloc_chain_link(r->pool);
+        if (cl == NULL) {
+            return NGX_ERROR;
+        }
+
+        b = ctx->out_buf;
+
+        if (ngx_buf_size(b) == 0) {
+
+            b = ngx_calloc_buf(ctx->request->pool);
+            if (b == NULL) {
+                return NGX_ERROR;
+            }
+
+        } else {
+            ctx->zstream.avail_out = 0;
+        }
+
+        b->flush = 1;
+
+        cl->buf = b;
+        cl->next = NULL;
+        *ctx->last_out = cl;
+        ctx->last_out = &cl->next;
+
+        return NGX_OK;
+    }
+
+    if (rc == Z_STREAM_END && ctx->flush == Z_FINISH
+        && ctx->zstream.avail_in == 0)
+    {
+
+        if (ngx_http_gunzip_filter_inflate_end(r, ctx) != NGX_OK) {
+            return NGX_ERROR;
+        }
+
+        return NGX_OK;
+    }
+
+    if (rc == Z_STREAM_END && ctx->zstream.avail_in > 0) {
+
+        rc = inflateReset(&ctx->zstream);
+
+        if (rc != Z_OK) {
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                          "inflateReset() failed: %d", rc);
+            return NGX_ERROR;
+        }
+
+        ctx->redo = 1;
+
+        return NGX_AGAIN;
+    }
+
+    if (ctx->in == NULL) {
+
+        b = ctx->out_buf;
+
+        if (ngx_buf_size(b) == 0) {
+            return NGX_OK;
+        }
+
+        cl = ngx_alloc_chain_link(r->pool);
+        if (cl == NULL) {
+            return NGX_ERROR;
+        }
+
+        ctx->zstream.avail_out = 0;
+
+        cl->buf = b;
+        cl->next = NULL;
+        *ctx->last_out = cl;
+        ctx->last_out = &cl->next;
+
+        return NGX_OK;
+    }
+
+    return NGX_AGAIN;
+}
+
+
+static ngx_int_t
+ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r,
+    ngx_http_gunzip_ctx_t *ctx)
+{
+    int           rc;
+    ngx_buf_t    *b;
+    ngx_chain_t  *cl;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "gunzip inflate end");
+
+    rc = inflateEnd(&ctx->zstream);
+
+    if (rc != Z_OK) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      "inflateEnd() failed: %d", rc);
+        return NGX_ERROR;
+    }
+
+    b = ctx->out_buf;
+
+    if (ngx_buf_size(b) == 0) {
+
+        b = ngx_calloc_buf(ctx->request->pool);
+        if (b == NULL) {
+            return NGX_ERROR;
+        }
+    }
+
+    cl = ngx_alloc_chain_link(r->pool);
+    if (cl == NULL) {
+        return NGX_ERROR;
+    }
+
+    cl->buf = b;
+    cl->next = NULL;
+    *ctx->last_out = cl;
+    ctx->last_out = &cl->next;
+
+    b->last_buf = (r == r->main) ? 1 : 0;
+    b->last_in_chain = 1;
+    b->sync = 1;
+
+    ctx->done = 1;
+
+    return NGX_OK;
+}
+
+
+static void *
+ngx_http_gunzip_filter_alloc(void *opaque, u_int items, u_int size)
+{
+    ngx_http_gunzip_ctx_t *ctx = opaque;
+
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
+                   "gunzip alloc: n:%ud s:%ud",
+                   items, size);
+
+    return ngx_palloc(ctx->request->pool, items * size);
+}
+
+
+static void
+ngx_http_gunzip_filter_free(void *opaque, void *address)
+{
+#if 0
+    ngx_http_gunzip_ctx_t *ctx = opaque;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
+                   "gunzip free: %p", address);
+#endif
+}
+
+
+static void *
+ngx_http_gunzip_create_conf(ngx_conf_t *cf)
+{
+    ngx_http_gunzip_conf_t  *conf;
+
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_gunzip_conf_t));
+    if (conf == NULL) {
+        return NULL;
+    }
+
+    /*
+     * set by ngx_pcalloc():
+     *
+     *     conf->bufs.num = 0;
+     */
+
+    conf->enable = NGX_CONF_UNSET;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_gunzip_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_gunzip_conf_t *prev = parent;
+    ngx_http_gunzip_conf_t *conf = child;
+
+    ngx_conf_merge_value(conf->enable, prev->enable, 0);
+
+    ngx_conf_merge_bufs_value(conf->bufs, prev->bufs,
+                              (128 * 1024) / ngx_pagesize, ngx_pagesize);
+
+    return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_http_gunzip_filter_init(ngx_conf_t *cf)
+{
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_gunzip_header_filter;
+
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_gunzip_body_filter;
+
+    return NGX_OK;
+}



More information about the nginx-devel mailing list