1
0
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:
Yann Ylavic
2018-07-31 10:35:46 +00:00
parent 53ab92ab70
commit 352e0faebc
4 changed files with 18 additions and 4 deletions

View File

@@ -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]

View File

@@ -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) = {

View File

@@ -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;
}

View File

@@ -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;
}
}