diff options
author | William A. Rowe Jr <wrowe@apache.org> | 2005-08-07 23:23:38 +0000 |
---|---|---|
committer | William A. Rowe Jr <wrowe@apache.org> | 2005-08-07 23:23:38 +0000 |
commit | fb1ece5da3bedbb2c10777cda247f8d0a09f632e (patch) | |
tree | d9c5e1e339bb7702fb86284df8e21847505ff6d2 | |
parent | a9a33d7a8181ab542dc747239fc94c476a66ed75 (diff) | |
download | httpd-fb1ece5da3bedbb2c10777cda247f8d0a09f632e.tar.gz |
Backport part of r216156 and very minor bits of r218978;
Collapse the handling of Content-Length / Transfer-Encoding header
values into the headers loop saving a bit of cpu and making the
results clearer, handle the (r->main) subrequest case a bit more
efficiently as well, cutting out some duplicate tests, and a mild
whitespace issue in the If-Unmodified-Since test line.
Fixes a subrequest bug where subrequests *still* would attempt to
read Transfer-Encoding: chunked request bodies.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/proxy-reqbody-2.0.x@230711 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | modules/proxy/proxy_http.c | 65 |
1 files changed, 35 insertions, 30 deletions
diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c index 3e9c044df7..4ca0d6d19c 100644 --- a/modules/proxy/proxy_http.c +++ b/modules/proxy/proxy_http.c @@ -786,7 +786,8 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, apr_status_t status; enum rb_methods {RB_INIT, RB_STREAM_CL, RB_STREAM_CHUNKED, RB_SPOOL_CL}; enum rb_methods rb_method = RB_INIT; - const char *old_cl_val, *te_val; + const char *old_cl_val = NULL; + const char *old_te_val = NULL; int cl_zero; /* client sent "Content-Length: 0", which we forward on to server */ int force10; @@ -928,7 +929,7 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, for (counter = 0; counter < headers_in_array->nelts; counter++) { if (headers_in[counter].key == NULL || headers_in[counter].val == NULL - + /* Already sent */ || !strcasecmp(headers_in[counter].key, "Host") @@ -938,13 +939,8 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, || !strcasecmp(headers_in[counter].key, "Keep-Alive") || !strcasecmp(headers_in[counter].key, "TE") || !strcasecmp(headers_in[counter].key, "Trailer") - || !strcasecmp(headers_in[counter].key, "Transfer-Encoding") || !strcasecmp(headers_in[counter].key, "Upgrade") - /* We'll add appropriate Content-Length later, if appropriate. - */ - || !strcasecmp(headers_in[counter].key, "Content-Length") - /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be * suppressed if THIS server requested the authentication, * not when a frontend proxy requested it! @@ -958,33 +954,27 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, || !strcasecmp(headers_in[counter].key,"Proxy-Authenticate")) { continue; } + + /* Skip Transfer-Encoding and Content-Length for now. + */ + if (!strcasecmp(headers_in[counter].key, "Transfer-Encoding")) { + old_te_val = headers_in[counter].val; + continue; + } + if (!strcasecmp(headers_in[counter].key, "Content-Length")) { + old_cl_val = headers_in[counter].val; + continue; + } + /* for sub-requests, ignore freshness/expiry headers */ if (r->main) { - if (headers_in[counter].key == NULL || headers_in[counter].val == NULL - || !strcasecmp(headers_in[counter].key, "If-Match") + if ( !strcasecmp(headers_in[counter].key, "If-Match") || !strcasecmp(headers_in[counter].key, "If-Modified-Since") || !strcasecmp(headers_in[counter].key, "If-Range") - || !strcasecmp(headers_in[counter].key, "If-Unmodified-Since") + || !strcasecmp(headers_in[counter].key, "If-Unmodified-Since") || !strcasecmp(headers_in[counter].key, "If-None-Match")) { continue; } - - /* 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 - && !strcasecmp(headers_in[counter].key, "Content-Length")) { - continue; - } } buf = apr_pstrcat(p, headers_in[counter].key, ": ", @@ -995,6 +985,23 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, APR_BRIGADE_INSERT_TAIL(bb, e); } + /* sub-requests never use keepalives, and mustn't pass request bodies. + * Because the new logic looks at input_brigade, we must 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) { + 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"); + } + } + /* send CL or use chunked encoding? * * . CL is the most friendly to the origin server since it is the @@ -1023,7 +1030,6 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, * . proxy-sendunchangedcl * use C-L from client and spool the request body */ - old_cl_val = apr_table_get(r->headers_in, "Content-Length"); cl_zero = old_cl_val && !strcmp(old_cl_val, "0"); if (!force10 @@ -1045,8 +1051,7 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r, else if (force10) { rb_method = RB_SPOOL_CL; } - else if ((te_val = apr_table_get(r->headers_in, "Transfer-Encoding")) - && !strcasecmp(te_val, "chunked")) { + else if (!strcasecmp(old_te_val, "chunked")) { rb_method = RB_STREAM_CHUNKED; } else { |