You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Stuart Children <st...@terminus.co.uk> on 2005/10/19 17:42:59 UTC
POST subrequests
Hi all
Whilst testing 2.0.55 we found that some of the changes to mod_proxy has
prevented one of our custom modules from working correctly. The problem
is not with the main purpose of the CL/TE security fixes, but a related
behaviour change that's happened along the way. Specifically, in
proxy_http.c:ap_proxy_http_request(), this:
if (r->main) {
[some lines snipped]
/* If you POST to a page that gets server-side parsed
* by mod_include, and the parsing results in a reverse
* proxy call, the proxied request will be a GET, but
* its request_rec will have inherited the Content-Length
* of the original request (the POST for the enclosing
* page). We can't send the original POST's request body
* as part of the proxied subrequest, so we need to avoid
* sending the corresponding content length. Otherwise,
* the server to which we're proxying will sit there
* forever, waiting for a request body that will never
* arrive.
*/
if ((r->method_number == M_GET) && headers_in[counter].key &&
!apr_strnatcasecmp(headers_in[counter].key,
"Content-Length")) {
continue;
}
has been replaced with:
/* sub-requests never use keepalives, and mustn't pass request bodies.
* Because the new logic looks at input_brigade, we will self-terminate
* input_brigade and jump past all of the request body logic...
* Reading anything with ap_get_brigade is likely to consume the
* main request's body or read beyond EOS - which would be unplesant.
*/
if (r->main) {
p_conn->close++;
if (old_cl_val) {
old_cl_val = NULL;
apr_table_unset(r->headers_in, "Content-Length");
}
if (old_te_val) {
old_te_val = NULL;
apr_table_unset(r->headers_in, "Transfer-Encoding");
}
rb_method = RB_STREAM_CL;
e = apr_bucket_eos_create(input_brigade->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(input_brigade, e);
goto skip_body;
}
So in <=2.0.54 the CL header was not passed on for subrequests if it was
set and the request is a GET. Now both CL and TE are removed for *all*
subrequests, regardless of the HTTP method.
As you've probably guessed, in our module we turn [some] subrequests
into POSTs. (We then set an appropriate CL header and add an input
filter to the subrequest which generates the request body.) I've written
a simple patch which adds a check on the request method again (simply
skipping most of the above lines if it's a POST). However, the comment
"sub-requests ... mustn't pass request bodies" made me think perhaps
some discussion is required before I stick that in bugzilla. Is there a
reason behind the "musn't"? Ie: are POST subrequests a problem (assuming
there's a valid input_brigade to read and a corresponding CL)?
Some googling turns up a previous thread which touches on this issue:
http://marc.theaimsgroup.com/?l=apache-httpd-dev&m=111099194601082&w=2
As a side comment, the original check wouldn't be necessary if we knew
that the subrequest was well formed. The 2.0.54 code is there because
mod_include creates the subrequests as GETs, but leaves an invalid CL
header (in fact, it's using the main request's headers table - not a
copy). This probably applies to the other headers that mod_proxy ignores
as well.
TIA
--
Stuart Children
http://terminus.co.uk/
Re: POST subrequests
Posted by Joe Schaefer <jo...@sunstarsys.com>.
Stuart Children <st...@terminus.co.uk> writes:
> As you've probably guessed, in our module we turn [some] subrequests
> into POSTs. (We then set an appropriate CL header and add an input
> filter to the subrequest which generates the request body.) I've written
> a simple patch which adds a check on the request method again (simply
> skipping most of the above lines if it's a POST). However, the comment
> "sub-requests ... mustn't pass request bodies" made me think perhaps
> some discussion is required before I stick that in bugzilla.
Good question. In apreq I focused on the case where the main request
was issued a POST, and the subrequest was a GET. In that case the
subrequest doesn't get access to the parsed body via apreq. OTOH,
I do think it should be possible to do a POST subrequest in httpd,
especially when you're being very careful about the state of the input
filter chain.
> Is there a reason behind the "musn't"? Ie: are POST subrequests a
> problem (assuming there's a valid input_brigade to read and a
> corresponding CL)?
I'm not sure what the rationale is behind forbidding it within httpd,
other than it being a complex situation that wasn't really possible
in 1.3.
--
Joe Schaefer