From: Martin Kraemer Date: Mon, 15 Apr 2002 09:41:22 +0000 (+0000) Subject: Sometimes (when a read happened to end on a chunk boundary) the proxy X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f7e99d524f1d560d71c2a40965dcec0ec5128990;p=thirdparty%2Fapache%2Fhttpd.git Sometimes (when a read happened to end on a chunk boundary) the proxy would just hang trying to read a CRLF that did not come (remaining==0 because end-of-chunk, not because chunksize==0). Also, when it received its data from an upstream proxy which did not really support HTTP/1.1 but claimed it did (ICS, Squid, both using nonstandard Proxy-Connection: headers), Apache would not clear out the "Transfer-Enconding: chunked" header and failed to correctly serve the request. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@94658 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/modules/proxy/proxy_http.c b/src/modules/proxy/proxy_http.c index bb32db72ead..db2c057c01e 100644 --- a/src/modules/proxy/proxy_http.c +++ b/src/modules/proxy/proxy_http.c @@ -168,6 +168,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, char *destportstr = NULL; const char *urlptr = NULL; const char *datestr, *urlstr; + char *content_length; void *sconf = r->server->module_config; proxy_server_conf *conf = @@ -362,7 +363,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, * says we should strip these headers: */ || !strcasecmp(reqhdrs_elts[i].key, "Host") /* Already sent */ - ||!strcasecmp(reqhdrs_elts[i].key, "Keep-Alive") + || !strcasecmp(reqhdrs_elts[i].key, "Keep-Alive") || !strcasecmp(reqhdrs_elts[i].key, "TE") || !strcasecmp(reqhdrs_elts[i].key, "Trailer") || !strcasecmp(reqhdrs_elts[i].key, "Transfer-Encoding") @@ -486,6 +487,11 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, /* strip hop-by-hop headers defined by Connection and RFC2616 */ ap_proxy_clear_connection(p, resp_hdrs); + + content_length = ap_table_get(resp_hdrs, "Content-Length"); + if (content_length != NULL) + c->len = strtol(content_length, NULL, 10); + /* Now add out bound headers set by other modules */ resp_hdrs = ap_overlay_tables(r->pool, r->err_headers_out, resp_hdrs); } diff --git a/src/modules/proxy/proxy_util.c b/src/modules/proxy/proxy_util.c index 9cb255a7ced..712d62b7e65 100644 --- a/src/modules/proxy/proxy_util.c +++ b/src/modules/proxy/proxy_util.c @@ -449,7 +449,7 @@ table *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f) long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, int chunked, size_t recv_buffer_size) { - int ok; + int ok, end_of_chunk; char *buf; size_t buf_size; size_t remaining = 0; @@ -510,7 +510,7 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int * (after the client aborted) while we can successfully read and finish * the configured cache_completion. */ - for (ok = 1; ok;) { + for (end_of_chunk = ok = 1; ok;) { if (alternate_timeouts) ap_hard_timeout("proxy recv body from upstream server", r); @@ -521,7 +521,8 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int n = 0; /* start of a new chunk */ - if (remaining == 0) { + if (end_of_chunk) { + end_of_chunk = 0; /* get the chunk size from the stream */ chunk_start = ap_getline(buf, buf_size, f, 0); if ((chunk_start <= 0) || ((size_t)chunk_start + 1 >= buf_size) || !ap_isxdigit(*buf)) { @@ -546,11 +547,12 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int n = ap_bread(f, buf, MIN((int)buf_size, (int)remaining)); if (n > -1) { remaining -= n; + end_of_chunk = (remaining == 0); } } /* soak up trailing CRLF */ - if (0 == remaining) { + if (end_of_chunk) { int ch; /* int because it may hold an EOF */ /* * For EBCDIC, the proxy has configured the BUFF layer to @@ -583,7 +585,7 @@ long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int n = ap_bread(f, buf, buf_size); } else { - n = ap_bread(f, buf, MIN((int)buf_size, + n = ap_bread(f, buf, MIN((int)buf_size, (int)(len - total_bytes_rcvd))); } } @@ -1469,21 +1471,22 @@ void ap_proxy_clear_connection(pool *p, table *headers) const char *name; char *next = ap_pstrdup(p, ap_table_get(headers, "Connection")); + /* Some proxies (Squid, ICS) use the non-standard "Proxy-Connection" header. */ ap_table_unset(headers, "Proxy-Connection"); - if (!next) - return; - while (*next) { - name = next; - while (*next && !ap_isspace(*next) && (*next != ',')) - ++next; - while (*next && (ap_isspace(*next) || (*next == ','))) { - *next = '\0'; - ++next; + if (next != NULL) { + while (*next) { + name = next; + while (*next && !ap_isspace(*next) && (*next != ',')) + ++next; + while (*next && (ap_isspace(*next) || (*next == ','))) { + *next = '\0'; + ++next; + } + ap_table_unset(headers, name); } - ap_table_unset(headers, name); + ap_table_unset(headers, "Connection"); } - ap_table_unset(headers, "Connection"); /* unset hop-by-hop headers defined in RFC2616 13.5.1 */ ap_table_unset(headers,"Keep-Alive");