Skip to content

Commit 968022e

Browse files
committed
* modules/filters/mod_sed.c (sed_request_filter): Fix handling of the
Content-Length request header; unset it after reading from the next filter. * test/pyhttpd/mod_aptest/mod_aptest.c (aptest_getline_echo): Buffer the body, and return the Content-Length request header left after reading it in an AP-Test-Content-Length response header. * test/modules/filters/test_003_sed.py (test_filters_003_34): New test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> GitHub: PR #791 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1938964 13f79535-47bb-0310-9956-ffa450edef68
1 parent f16faef commit 968022e

3 files changed

Lines changed: 48 additions & 8 deletions

File tree

‎modules/filters/mod_sed.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,11 @@ static apr_status_t sed_request_filter(ap_filter_t *f,
516516
if (status != APR_SUCCESS) {
517517
return status;
518518
}
519+
/* The body passed on is not the length the request gave. Only
520+
* drop the header after this read: HTTP_IN takes the length from
521+
* it on the first.
522+
*/
523+
apr_table_unset(f->r->headers_in, "Content-Length");
519524
for (b = APR_BRIGADE_FIRST(bbinp); b != APR_BRIGADE_SENTINEL(bbinp);
520525
b = APR_BUCKET_NEXT(b)) {
521526
const char *buf = NULL;

‎test/modules/filters/test_003_sed.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,27 @@ def test_filters_003_33(self, env):
386386
assert r.response["status"] == 200
387387
assert r.response["body"] == b"one MON two\nMON MON\n"
388388

389+
# The request Content-Length is the length of the body before it was
390+
# filtered, so once mod_sed has started reading the body it is removed:
391+
# a handler must not find the original length.
392+
def test_filters_003_34(self, env):
393+
self.configure(env, "s/monday/MONDAYMONDAY/g", input_sed=True,
394+
extra="""
395+
<Location "/getline">
396+
SetHandler aptest-getline-echo
397+
SetInputFilter SED
398+
</Location>
399+
""")
400+
data = "one monday two\nmonday monday\n"
401+
r = env.curl_post_data(env.mkurl("http", "test1", "/getline"),
402+
data=data)
403+
assert r.response, "no response"
404+
assert r.response["status"] == 200
405+
assert r.response["body"] == \
406+
data.replace("monday", "MONDAYMONDAY").encode()
407+
assert "ap-test-content-length" not in r.response["header"], \
408+
r.response["header"]
409+
389410
# --- interval expressions ---------------------------------------------
390411

391412
# \{m,n\} repeats a character or a bracket expression.

‎test/pyhttpd/mod_aptest/mod_aptest.c‎

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,26 @@ static int aptest_allow_methods(request_rec *r)
7676

7777
/*
7878
* Handler "aptest-getline-echo": echo the request body back, reading it
79-
* with AP_MODE_GETLINE rather than AP_MODE_READBYTES.
79+
* with AP_MODE_GETLINE rather than AP_MODE_READBYTES. The Content-Length
80+
* request header left once the body has been read, if any, is returned in
81+
* an "AP-Test-Content-Length" response header.
8082
*/
8183
static int aptest_getline_echo(request_rec *r)
8284
{
83-
apr_bucket_brigade *bb;
85+
apr_bucket_brigade *bb, *body;
86+
const char *clen;
87+
char *data;
88+
apr_size_t len;
8489
apr_status_t rv;
8590
int seen_eos = 0;
8691

8792
if (strcmp(r->handler, "aptest-getline-echo")) {
8893
return DECLINED;
8994
}
9095

91-
ap_set_content_type(r, "text/plain");
9296
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
97+
body = apr_brigade_create(r->pool, r->connection->bucket_alloc);
9398
while (!seen_eos) {
94-
char *line;
95-
apr_size_t len;
96-
9799
rv = ap_get_brigade(r->input_filters, bb, AP_MODE_GETLINE,
98100
APR_BLOCK_READ, HUGE_STRING_LEN);
99101
if (rv != APR_SUCCESS) {
@@ -105,14 +107,26 @@ static int aptest_getline_echo(request_rec *r)
105107
&& APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
106108
seen_eos = 1;
107109
}
108-
rv = apr_brigade_pflatten(bb, &line, &len, r->pool);
110+
rv = apr_brigade_pflatten(bb, &data, &len, r->pool);
111+
if (rv == APR_SUCCESS) {
112+
rv = apr_brigade_write(body, NULL, NULL, data, len);
113+
}
109114
if (rv != APR_SUCCESS) {
110115
return HTTP_INTERNAL_SERVER_ERROR;
111116
}
112-
ap_rwrite(line, len, r);
113117
apr_brigade_cleanup(bb);
114118
}
115119

120+
clen = apr_table_get(r->headers_in, "Content-Length");
121+
if (clen) {
122+
apr_table_setn(r->headers_out, "AP-Test-Content-Length", clen);
123+
}
124+
ap_set_content_type(r, "text/plain");
125+
if (apr_brigade_pflatten(body, &data, &len, r->pool) != APR_SUCCESS) {
126+
return HTTP_INTERNAL_SERVER_ERROR;
127+
}
128+
ap_rwrite(data, len, r);
129+
116130
return OK;
117131
}
118132

0 commit comments

Comments
 (0)