mirror of
https://github.com/apache/httpd.git
synced 2026-01-06 09:01:14 +03:00
mod_ratelimit: Don't interfere with "chunked" encoding.
By the time ap_http_header_filter() sends the header brigade and adds the "CHUNK" filter, we need to garantee that the header went through all the filters' stack, and more specifically above ap_http_chunk_filter() which assumes that all it receives is content data. Since rate_limit_filter() may retain the header brigade, make it run after ap_http_chunk_filter(), just before AP_FTYPE_CONNECTION filters. Also, ap_http_header_filter() shouldn't eat the EOS for HEAD/no-body responses. For instance mod_ratelimit depends on it since r1835168, but any next request filter may as well to flush and/or bail out approprietely. This fixes the regression introduced in 2.4.34 (r1835168). PR 62568. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1837130 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,6 +1,9 @@
|
||||
-*- coding: utf-8 -*-
|
||||
Changes with Apache 2.5.1
|
||||
|
||||
*) mod_ratelimit: Don't interfere with "chunked" encoding, fixing regression
|
||||
introduced in 2.4.34. PR 62568. [Yann Ylavic]
|
||||
|
||||
*) http: Enforce consistently no response body with both 204 and 304
|
||||
statuses. [Yann Ylavic]
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@ rate_limit_filter(ap_filter_t *f, apr_bucket_brigade *bb)
|
||||
|
||||
/* Set up our rl_ctx_t on first use */
|
||||
if (ctx == NULL) {
|
||||
|
||||
const char *rl = NULL;
|
||||
int ratelimit;
|
||||
int burst = 0;
|
||||
@@ -327,7 +326,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) = {
|
||||
|
||||
@@ -67,6 +67,7 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
|
||||
{
|
||||
if (APR_BUCKET_IS_EOS(e)) {
|
||||
/* there shouldn't be anything after the eos */
|
||||
ap_remove_output_filter(f);
|
||||
eos = e;
|
||||
break;
|
||||
}
|
||||
@@ -184,11 +185,11 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
|
||||
|
||||
/* pass the brigade to the next filter. */
|
||||
rv = ap_pass_brigade(f->next, b);
|
||||
apr_brigade_cleanup(b);
|
||||
if (rv != APR_SUCCESS || eos != NULL) {
|
||||
return rv;
|
||||
}
|
||||
tmp = b;
|
||||
apr_brigade_cleanup(tmp);
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1252,8 +1252,19 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
|
||||
else if (ctx->headers_sent) {
|
||||
/* Eat body if response must not have one. */
|
||||
if (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user