Index: modules/filters/mod_ratelimit.c =================================================================== --- modules/filters/mod_ratelimit.c (revision 1836838) +++ modules/filters/mod_ratelimit.c (working copy) @@ -327,7 +327,7 @@ static void register_hooks(apr_pool_t *p) { /* run after mod_deflate etc etc, but not at connection level, ie, mod_ssl. */ ap_register_output_filter(RATE_LIMIT_FILTER_NAME, rate_limit_filter, - NULL, AP_FTYPE_PROTOCOL + 3); + NULL, AP_FTYPE_CONNECTION - 1); } AP_DECLARE_MODULE(ratelimit) = { Index: modules/http/chunk_filter.c =================================================================== --- modules/http/chunk_filter.c (revision 1836838) +++ modules/http/chunk_filter.c (working copy) @@ -30,6 +30,7 @@ #include "http_core.h" #include "http_protocol.h" /* For index_of_response(). Grump. */ #include "http_request.h" +#include "http_log.h" #include "util_filter.h" #include "util_ebcdic.h" @@ -53,6 +54,9 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket *e; apr_status_t rv; + ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, f->r, + "ap_http_chunk_filter()"); + for (more = tmp = NULL; b; b = more, more = NULL) { apr_off_t bytes = 0; apr_bucket *eos = NULL; @@ -69,6 +73,7 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, { if (APR_BUCKET_IS_EOS(e)) { /* there shouldn't be anything after the eos */ + /*ap_remove_output_filter(f);*/ eos = e; break; } Index: modules/http/http_filters.c =================================================================== --- modules/http/http_filters.c (revision 1836838) +++ modules/http/http_filters.c (working copy) @@ -1308,8 +1308,19 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_heade else if (ctx->headers_sent) { /* Eat body if response must not have one. */ if (r->header_only || r->status == HTTP_NO_CONTENT) { + /* Still next filters may be waiting for EOS, so pass it (alone) + * when encountered and be done with this filter. + */ + e = APR_BRIGADE_LAST(b); + if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { + APR_BUCKET_REMOVE(e); + apr_brigade_cleanup(b); + APR_BRIGADE_INSERT_HEAD(b, e); + ap_remove_output_filter(f); + rv = ap_pass_brigade(f->next, b); + } apr_brigade_cleanup(b); - return APR_SUCCESS; + return rv; } }