https://issues.apache.org/bugzilla/show_bug.cgi?id=17629
Here's an attempt at fixing the dreaded PR 17629. This is a bug in the handling of the output filter chain at the point where an internal redirect is applied to a subrequest. Complications: a) a subrequest's filter chain may start at an arbitrary point in r->main's filter chain -- for an SSI include, the output from the include must continue from the next filter along from the INCLUDES filter b) that point where the filter chains join cannot be lost by the subrequest doing an internal redirect -- obvious breakage as per the PR is losing the DEFLATE filter for the output of the redirect from the subreq c) the subrequest's filter chain cannot be preserved as-is, since it may contain filters which should not be applied to the destination URI The approach I've used is to distinguish inherited filters from subreq-specific filters by seeing what f->r points to, and nuking all but the inherited filters. Here's the patch - test case in the test suite: Index: modules/http/http_request.c =================================================================== --- modules/http/http_request.c (revision 952555) +++ modules/http/http_request.c (working copy) @@ -460,17 +460,47 @@ 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); update_r_in_filters(new->output_filters, r, new);