]> granicus.if.org Git - apache/commitdiff
* modules/http/http_request.c (internal_internal_redirect): For a
authorJoe Orton <jorton@apache.org>
Tue, 8 Jun 2010 21:17:48 +0000 (21:17 +0000)
committerJoe Orton <jorton@apache.org>
Tue, 8 Jun 2010 21:17:48 +0000 (21:17 +0000)
  subrequest, preserve any filters in the output filter chain which
  were not specific to the subrequest across the redirect (where
  f->r does not point to the subreq's request_rec).

PR: 17629

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

CHANGES
modules/http/http_request.c

diff --git a/CHANGES b/CHANGES
index f0d49ab819bdecb188cc4471cd483d0fc23d4710..8ed9b33242290a7f2a08061baff389ce0b7881aa 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -28,6 +28,10 @@ Changes with Apache 2.3.6
      processing is completed, avoiding orphaned callback pointers.
      [Brett Gervasoni <brettg senseofsecurity.com>, Jeff Trawick]
 
+  *) core: Adjust the output filter chain correctly in an internal
+     redirect from a subrequest, preserving filters from the main
+     request as necessary.  PR 17629.  [Joe Orton]
+
   *) mod_cache: Explicitly allow cache implementations to cache a 206 Partial
      Response if they so choose to do so. Previously an attempt to cache a 206
      was arbitrarily allowed if the response contained an Expires or
index d2f8ba44fe86b7d7bf7d240fa023e14140e2c81f..f17983303e4ee2a819992e208c2f662e84d42df6 100644 (file)
@@ -460,16 +460,46 @@ static request_rec *internal_internal_redirect(const char *new_uri,
     new->proto_output_filters  = r->proto_output_filters;
     new->proto_input_filters   = r->proto_input_filters;
 
-    new->output_filters  = new->proto_output_filters;
     new->input_filters   = new->proto_input_filters;
 
     if (new->main) {
-        /* Add back the subrequest filter, which we lost when
-         * we set output_filters to include only the protocol
-         * output filters from the original request.
-         */
-        ap_add_output_filter_handle(ap_subreq_core_filter_handle,
-                                    NULL, new, new->connection);
+        ap_filter_t *f, *nextf;
+
+        /* If this is a subrequest, the filter chain may contain a
+         * mixture of filters specific to the old request (r), and
+         * some inherited from r->main.  Here, inherit that filter
+         * chain, and remove all those which are specific to the old
+         * request; ensuring the subreq filter is left in place. */
+        new->output_filters = r->output_filters;
+
+        f = new->output_filters;
+        do {
+            nextf = f->next;
+
+            if (f->r == r && f->frec != ap_subreq_core_filter_handle) {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                              "dropping filter '%s' in internal redirect from %s to %s",
+                              f->frec->name, r->unparsed_uri, new_uri);
+
+                /* To remove the filter, first set f->r to the *new*
+                 * request_rec, so that ->output_filters on 'new' is
+                 * changed (if necessary) when removing the filter. */
+                f->r = new;
+                ap_remove_output_filter(f);
+            }
+
+            f = nextf;
+
+            /* Stop at the protocol filters.  If a protocol filter has
+             * been newly installed for this resource, better leave it
+             * in place, though it's probably a misconfiguration or
+             * filter bug to get into this state. */
+        } while (f && f != new->proto_output_filters);
+    }
+    else {
+        /* If this is not a subrequest, clear out all
+         * resource-specific filters. */
+        new->output_filters  = new->proto_output_filters;
     }
 
     update_r_in_filters(new->input_filters, r, new);