]> granicus.if.org Git - apache/commitdiff
Fix 'Content-Encoding: gzip' missing if the first brigade passed to
authorStefan Fritsch <sf@apache.org>
Tue, 13 Sep 2011 20:17:18 +0000 (20:17 +0000)
committerStefan Fritsch <sf@apache.org>
Tue, 13 Sep 2011 20:17:18 +0000 (20:17 +0000)
deflate_out_buffer contained zero data bytes but no EOS bucket.

Don't compress if the added headers and checksums are larger than
the data to compress (and we know the size of the data in advance).

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1170330 13f79535-47bb-0310-9956-ffa450edef68

modules/filters/mod_deflate.c

index 60256a1031f3eca04d7f23b624aa15cbb75468c3..7687a53f3f9ec6319308c6af684f50349496278f 100644 (file)
@@ -426,7 +426,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
     request_rec *r = f->r;
     deflate_ctx *ctx = f->ctx;
     int zRC;
-    apr_size_t len;
+    apr_size_t len = 0, blen;
     const char *data;
     deflate_filter_config *c;
 
@@ -448,28 +448,41 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
         char *token;
         const char *encoding;
 
-        /* Delay initialization until we have seen some data */
-        e = APR_BRIGADE_FIRST(bb);
-        while (1) {
-            apr_status_t rc;
-            if (e == APR_BRIGADE_SENTINEL(bb))
-                return ap_pass_brigade(f->next, bb);
-            if (APR_BUCKET_IS_EOS(e)) {
-                ap_remove_output_filter(f);
-                return ap_pass_brigade(f->next, bb);
-            }
-            if (APR_BUCKET_IS_METADATA(e)) {
-                e = APR_BUCKET_NEXT(e);
-                continue;
-            }
+        e = APR_BRIGADE_LAST(bb);
+        if (APR_BUCKET_IS_EOS(e)) {
+            /*
+             * If we already know the size of the response, we can skip
+             * compression on responses smaller than the compression overhead.
+             * However, if we compress, we must initialize deflate_out before
+             * calling ap_pass_brigade() for the first time.  Otherwise the
+             * headers will be sent to the client without
+             * "Content-Encoding: gzip".
+             */
+            e = APR_BRIGADE_FIRST(bb);
+            while (1) {
+                apr_status_t rc;
+                if (APR_BUCKET_IS_EOS(e)) {
+                    ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r,
+                                  "Not compressing very small response of %"
+                                  APR_SIZE_T_FMT " bytes", len);
+                    ap_remove_output_filter(f);
+                    return ap_pass_brigade(f->next, bb);
+                }
+                if (APR_BUCKET_IS_METADATA(e)) {
+                    e = APR_BUCKET_NEXT(e);
+                    continue;
+                }
 
-            rc = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
-            if (rc != APR_SUCCESS)
-                return rc;
-            if (len > 0)
-                break;
+                rc = apr_bucket_read(e, &data, &blen, APR_BLOCK_READ);
+                if (rc != APR_SUCCESS)
+                    return rc;
+                len += blen;
+                /* 50 is for Content-Encoding and Vary headers and ETag suffix */
+                if (len > sizeof(gzip_header) + VALIDATION_SIZE + 50)
+                    break;
 
-            e = APR_BUCKET_NEXT(e);
+                e = APR_BUCKET_NEXT(e);
+            }
         }
 
         ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));