]> granicus.if.org Git - apache/commitdiff
Adjust content metadata on deflate/inflate response before bailing out
authorRoy T. Fielding <fielding@apache.org>
Thu, 12 Feb 2009 17:43:39 +0000 (17:43 +0000)
committerRoy T. Fielding <fielding@apache.org>
Thu, 12 Feb 2009 17:43:39 +0000 (17:43 +0000)
on a 304 response so that the metadata does not differ from 200 response.

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

CHANGES
modules/filters/mod_deflate.c

diff --git a/CHANGES b/CHANGES
index b1a3eacacd5c236126e26a011ec32438a2577058..fbddfd82e8840d9554b9ed6c49383adde26c2910 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,9 +1,13 @@
                                                         -*- coding: utf-8 -*-
 Changes with Apache 2.3.2
 
+  *) mod_deflate: Adjust content metadata before bailing out on 304
+     responses so that the metadata does not differ from 200 response.
+     [Roy T. Fielding]
+
   *) mod_deflate: Fix creation of invalid Etag headers. We now make sure
      that the Etag value is properly quoted when adding the gzip marker.
-     PR 39727. [Lars Eilebrecht]
+     PR 39727, 45023. [Lars Eilebrecht, Roy T. Fielding]
 
   *) Added 20x22 icons for ODF, SVG, and XML documents.  PR 37185.
      [Peter Harlow]
index 2dbadfe006ef75db706860cb06993701de049907..4451d77a205e20f15a0c331ddcd887b91701d9b7 100644 (file)
@@ -445,22 +445,16 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
         char *token;
         const char *encoding;
 
-        /* only work on main request/no subrequests */
-        if (r->main != NULL) {
-            ap_remove_output_filter(f);
-            return ap_pass_brigade(f->next, bb);
-        }
-
-        /* some browsers might have problems, so set no-gzip
-         * (with browsermatch) for them
+        /*
+         * Only work on main request, not subrequests,
+         * that are not a 204 response with no content
+         * and are not tagged with the no-gzip env variable
+         * and not a partial response to a Range request.
          */
-        if (apr_table_get(r->subprocess_env, "no-gzip")) {
-            ap_remove_output_filter(f);
-            return ap_pass_brigade(f->next, bb);
-        }
-
-        /* We can't operate on Content-Ranges */
-        if (apr_table_get(r->headers_out, "Content-Range") != NULL) {
+        if ((r->main != NULL) || (r->status == HTTP_NO_CONTENT) ||
+            apr_table_get(r->subprocess_env, "no-gzip") ||
+            apr_table_get(r->headers_out, "Content-Range")
+           ) {
             ap_remove_output_filter(f);
             return ap_pass_brigade(f->next, bb);
         }
@@ -563,14 +557,32 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
             }
         }
 
-        /* For a 304 or 204 response there is no entity included in
-         * the response and hence nothing to deflate. */
-        if (r->status == HTTP_NOT_MODIFIED || r->status == HTTP_NO_CONTENT) {
+        /* At this point we have decided to filter the content, so change
+         * important content metadata before sending any response out.
+         */
+
+        /* If the entire Content-Encoding is "identity", we can replace it. */
+        if (!encoding || !strcasecmp(encoding, "identity")) {
+            apr_table_setn(r->headers_out, "Content-Encoding", "gzip");
+        }
+        else {
+            apr_table_mergen(r->headers_out, "Content-Encoding", "gzip");
+        }
+        /* Fix r->content_encoding if it was set before */
+        if (r->content_encoding) {
+            r->content_encoding = apr_table_get(r->headers_out,
+                                                "Content-Encoding");
+        }
+        apr_table_unset(r->headers_out, "Content-Length");
+        apr_table_unset(r->headers_out, "Content-MD5");
+        deflate_check_etag(r, "gzip");
+
+        /* For a 304 response, only change the headers */
+        if (r->status == HTTP_NOT_MODIFIED) {
             ap_remove_output_filter(f);
             return ap_pass_brigade(f->next, bb);
         }
 
-        /* We're cool with filtering this. */
         ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
         ctx->bb = apr_brigade_create(r->pool, f->c->bucket_alloc);
         ctx->buffer = apr_palloc(r->pool, c->bufferSize);
@@ -606,22 +618,6 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
                                        f->c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
 
-        /* If the entire Content-Encoding is "identity", we can replace it. */
-        if (!encoding || !strcasecmp(encoding, "identity")) {
-            apr_table_setn(r->headers_out, "Content-Encoding", "gzip");
-        }
-        else {
-            apr_table_mergen(r->headers_out, "Content-Encoding", "gzip");
-        }
-        /* Fix r->content_encoding if it was set before */
-        if (r->content_encoding) {
-            r->content_encoding = apr_table_get(r->headers_out,
-                                                "Content-Encoding");
-        }
-        apr_table_unset(r->headers_out, "Content-Length");
-        apr_table_unset(r->headers_out, "Content-MD5");
-        deflate_check_etag(r, "gzip");
-
         /* initialize deflate output buffer */
         ctx->stream.next_out = ctx->buffer;
         ctx->stream.avail_out = c->bufferSize;
@@ -1051,29 +1047,31 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
 
     if (!ctx) {
 
-        /* only work on main request/no subrequests */
-        if (!ap_is_initial_req(r)) {
-            ap_remove_output_filter(f);
-            return ap_pass_brigade(f->next, bb);
-        }
-
-        /* We can't operate on Content-Ranges */
-        if (apr_table_get(r->headers_out, "Content-Range") != NULL) {
+        /*
+         * Only work on main request, not subrequests,
+         * that are not a 204 response with no content
+         * and not a partial response to a Range request,
+         * and only when Content-Encoding ends in gzip.
+         */
+        if (!ap_is_initial_req(r) || (r->status == HTTP_NO_CONTENT) ||
+            (apr_table_get(r->headers_out, "Content-Range") != NULL) ||
+            (check_gzip(r, r->headers_out, r->err_headers_out) == 0)
+           ) {
             ap_remove_output_filter(f);
             return ap_pass_brigade(f->next, bb);
         }
 
         /*
-         * Let's see what our current Content-Encoding is.
-         * Only inflate if gzipped.
+         * At this point we have decided to filter the content, so change
+         * important content metadata before sending any response out.
+         * Content-Encoding was already reset by the check_gzip() call.
          */
-        if (check_gzip(r, r->headers_out, r->err_headers_out) == 0) {
-            ap_remove_output_filter(f);
-            return ap_pass_brigade(f->next, bb);
-        }
+        apr_table_unset(r->headers_out, "Content-Length");
+        apr_table_unset(r->headers_out, "Content-MD5");
+        deflate_check_etag(r, "gunzip");
 
-        /* No need to inflate HEAD or 204/304 */
-        if (APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(bb))) {
+        /* For a 304 response, only change the headers */
+        if (r->status == HTTP_NOT_MODIFIED) {
             ap_remove_output_filter(f);
             return ap_pass_brigade(f->next, bb);
         }
@@ -1110,11 +1108,6 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
         apr_pool_cleanup_register(r->pool, ctx, deflate_ctx_cleanup,
                                   apr_pool_cleanup_null);
 
-        /* these are unlikely to be set anyway, but ... */
-        apr_table_unset(r->headers_out, "Content-Length");
-        apr_table_unset(r->headers_out, "Content-MD5");
-        deflate_check_etag(r, "gunzip");
-
         /* initialize inflate output buffer */
         ctx->stream.next_out = ctx->buffer;
         ctx->stream.avail_out = c->bufferSize;