diff --git a/include/httpd.h b/include/httpd.h index c6f6d1da8f..fa57f98183 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -905,6 +905,14 @@ struct request_rec { struct ap_filter_t *output_filters; /** A list of input filters to be used for this request */ struct ap_filter_t *input_filters; + + /** A list of protocol level output filters to be used for this + * request */ + struct ap_filter_t *proto_output_filters; + /** A list of protocol level input filters to be used for this + * request */ + struct ap_filter_t *proto_input_filters; + /** A flag to determine if the eos bucket has been sent yet */ int eos_sent; diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 244c346cf1..b1763edbe9 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -391,8 +391,11 @@ static request_rec *internal_internal_redirect(const char *new_uri, new->read_length = r->read_length; /* We can only read it once */ new->vlist_validator = r->vlist_validator; - new->output_filters = r->connection->output_filters; - new->input_filters = r->connection->input_filters; + 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; ap_add_input_filter("HTTP_IN", NULL, new, new->connection); @@ -441,6 +444,9 @@ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r) r->err_headers_out); r->subprocess_env = apr_table_overlay(r->pool, rr->subprocess_env, r->subprocess_env); + + r->output_filters = rr->output_filters; + r->input_filters = rr->input_filters; } AP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r) diff --git a/server/protocol.c b/server/protocol.c index 923c6de854..a902d55a17 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -776,8 +776,10 @@ request_rec *ap_read_request(conn_rec *conn) r->request_config = ap_create_request_config(r->pool); /* Must be set before we run create request hook */ - r->output_filters = conn->output_filters; - r->input_filters = conn->input_filters; + r->proto_output_filters = conn->output_filters; + r->output_filters = r->proto_output_filters; + r->proto_input_filters = conn->input_filters; + r->input_filters = r->proto_input_filters; ap_run_create_request(r); r->per_dir_config = r->server->lookup_defaults; diff --git a/server/request.c b/server/request.c index 7d3cc6c22b..69d6df5954 100644 --- a/server/request.c +++ b/server/request.c @@ -1492,13 +1492,23 @@ static request_rec *make_sub_request(const request_rec *r, /* start with the same set of output filters */ if (next_filter) { + /* no input filters for a subrequest */ rnew->output_filters = next_filter; + ap_add_output_filter_handle(ap_subreq_core_filter_handle, + NULL, rnew, rnew->connection); } else { - rnew->output_filters = r->output_filters; + /* If NULL - we are expecting to be internal_fast_redirect'ed + * to this subrequest - or this request will never be invoked. + * Ignore the original request filter stack entirely, and + * drill the input and output stacks back to the connection. + */ + rnew->proto_input_filters = r->proto_input_filters; + rnew->proto_output_filters = r->proto_output_filters; + + rnew->input_filters = r->proto_input_filters; + rnew->output_filters = r->proto_output_filters; } - ap_add_output_filter_handle(ap_subreq_core_filter_handle, - NULL, rnew, rnew->connection); /* no input filters for a subrequest */ diff --git a/server/util_filter.c b/server/util_filter.c index afc0731de2..e457aaf9c9 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -294,7 +294,8 @@ AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name, static ap_filter_t *add_any_filter(const char *name, void *ctx, request_rec *r, conn_rec *c, const filter_trie_node *reg_filter_set, - ap_filter_t **r_filters, + ap_filter_t **r_filters, + ap_filter_t **p_filters, ap_filter_t **c_filters) { if (reg_filter_set) { @@ -329,7 +330,7 @@ static ap_filter_t *add_any_filter(const char *name, void *ctx, if (node && node->frec) { apr_pool_t* p = r ? r->pool : c->pool; ap_filter_t *f = apr_palloc(p, sizeof(*f)); - ap_filter_t **outf = r ? r_filters : c_filters; + ap_filter_t **outf = r ? (r_filters ? r_filters : p_filters) : c_filters; f->frec = node->frec; f->ctx = ctx; @@ -360,11 +361,12 @@ static ap_filter_t *add_any_filter(const char *name, void *ctx, static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx, request_rec *r, conn_rec *c, ap_filter_t **r_filters, + ap_filter_t **p_filters, ap_filter_t **c_filters) { apr_pool_t* p = r ? r->pool : c->pool; ap_filter_t *f = apr_palloc(p, sizeof(*f)); - ap_filter_t **outf = r ? r_filters : c_filters; + ap_filter_t **outf = r ? (r_filters ? r_filters : p_filters) : c_filters; f->frec = frec; f->ctx = ctx; @@ -390,7 +392,8 @@ AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c) { return add_any_filter(name, ctx, r, c, registered_input_filters, - r ? &r->input_filters : NULL, &c->input_filters); + r ? &r->input_filters : NULL, + r ? &r->proto_input_filters : NULL, &c->input_filters); } AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f, @@ -399,6 +402,7 @@ AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f, conn_rec *c) { return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL, + r ? &r->proto_input_filters : NULL, &c->input_filters); } @@ -406,7 +410,8 @@ AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx, request_rec *r, conn_rec *c) { return add_any_filter(name, ctx, r, c, registered_output_filters, - r ? &r->output_filters : NULL, &c->output_filters); + r ? &r->output_filters : NULL, + r ? &r->proto_output_filters : NULL, &c->output_filters); } AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f, @@ -415,6 +420,7 @@ AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f, conn_rec *c) { return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL, + r ? &r->proto_output_filters : NULL, &c->output_filters); }