[PATCH] deflate support for gunzip module
Serge Sitnikov
serge.sitnikov at gmail.com
Fri Feb 25 09:11:26 MSK 2011
Adds deflate decompression support for gunzip module:
--- ngx_http_gunzip_filter_module.c
+++ ngx_http_gunzip_filter_module.c 2011-02-24 09:07:08.000000000 +0100
@@ -30,6 +30,8 @@
ngx_buf_t *out_buf;
ngx_int_t bufs;
+ unsigned deflate:1;
+
unsigned started:1;
unsigned flush:4;
unsigned redo:1;
@@ -122,42 +124,45 @@
{
ngx_http_gunzip_ctx_t *ctx;
ngx_http_gunzip_conf_t *conf;
+ int deflate = 0, client_deflate = 0;
conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
- /* TODO support multiple content-codings */
+ /* TODO support even more encodings */
/* 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)
- {
+ if (!conf->enable || r->headers_out.content_encoding == NULL) {
return ngx_http_next_header_filter(r);
+ } else if (r->headers_out.content_encoding->value.len != 4 ||
+ ngx_strncasecmp(r->headers_out.content_encoding->value.data,
(u_char *) "gzip", 4) != 0)
+ {
+ deflate = r->headers_out.content_encoding->value.len == 7 &&
+ ngx_strncasecmp(r->headers_out.content_encoding->value.data,
(u_char *) "deflate", 7) == 0;
+
+ if (!deflate) return ngx_http_next_header_filter(r);
+ else client_deflate = r->headers_in.accept_encoding != NULL ?
+ ngx_strcasestrn(r->headers_in.accept_encoding->value.data,
"deflate", 7 - 1) != NULL : 0;
}
#if (nginx_version >= 8025 || (nginx_version >= 7065 && nginx_version < 8000))
r->gzip_vary = 1;
+ int ok = r->gzip_tested ? r->gzip_ok : ngx_http_gzip_ok(r) == NGX_OK;
- if (!r->gzip_tested) {
- if (ngx_http_gzip_ok(r) == NGX_OK) {
- return ngx_http_next_header_filter(r);
- }
+#else
- } else if (!r->gzip_ok) {
- return ngx_http_next_header_filter(r);
- }
+ int ok = ngx_http_gzip_ok(r) == NGX_OK;
-#else
+#endif
- if (ngx_http_gzip_ok(r) == NGX_OK) {
- return ngx_http_next_header_filter(r);
+ if (deflate) {
+ if (ok && client_deflate) return ngx_http_next_header_filter(r);
+ } else {
+ if (ok) return ngx_http_next_header_filter(r);
}
-#endif
+ // --
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gunzip_ctx_t));
if (ctx == NULL) {
@@ -167,6 +172,7 @@
ngx_http_set_ctx(r, ctx, ngx_http_gunzip_filter_module);
ctx->request = r;
+ ctx->deflate = deflate;
r->filter_need_in_memory = 1;
@@ -314,8 +320,8 @@
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);
+ /* windowBits +32 to auto decode gzip and deflate */
+ rc = inflateInit2(&ctx->zstream, MAX_WBITS + 32);
if (rc != Z_OK) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
@@ -328,6 +334,33 @@
ctx->last_out = &ctx->out;
ctx->flush = Z_NO_FLUSH;
+ // --
+
+ if (!ctx->deflate) return NGX_OK;
+
+ /* Header inflation should not produce any output, so all
+ these hacks below are valid. */
+
+ static unsigned char deflate_header[] = { 0x78, 0x9C };
+ unsigned char temp;
+
+ ctx->zstream.next_in = deflate_header;
+ ctx->zstream.avail_in = 2;
+ ctx->zstream.next_out = &temp;
+ ctx->zstream.avail_out = 1;
+
+ rc = inflate(&ctx->zstream, Z_NO_FLUSH);
+ if (rc != Z_OK) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "deflate: inflate() failed: %d, %d", ctx->flush, rc);
+ return NGX_ERROR;
+ }
+
+ ctx->zstream.next_in = Z_NULL;
+ ctx->zstream.avail_in = 0;
+ ctx->zstream.next_out = Z_NULL;
+ ctx->zstream.avail_out = 0;
+
return NGX_OK;
}
--
Sergei Sitnikov
More information about the nginx-devel
mailing list