From: Joe Orton Date: Tue, 8 Jun 2010 21:17:48 +0000 (+0000) Subject: * modules/http/http_request.c (internal_internal_redirect): For a X-Git-Tag: 2.3.6~13 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e446077b99758a271ec8ba8bffdcb671b20d8714;p=apache * modules/http/http_request.c (internal_internal_redirect): For a 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 --- diff --git a/CHANGES b/CHANGES index f0d49ab819..8ed9b33242 100644 --- a/CHANGES +++ b/CHANGES @@ -28,6 +28,10 @@ Changes with Apache 2.3.6 processing is completed, avoiding orphaned callback pointers. [Brett Gervasoni , 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 diff --git a/modules/http/http_request.c b/modules/http/http_request.c index d2f8ba44fe..f17983303e 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -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);