]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Sometimes (when a read happened to end on a chunk boundary) the proxy
authorMartin Kraemer <martin@apache.org>
Mon, 15 Apr 2002 09:41:22 +0000 (09:41 +0000)
committerMartin Kraemer <martin@apache.org>
Mon, 15 Apr 2002 09:41:22 +0000 (09:41 +0000)
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

src/modules/proxy/proxy_http.c
src/modules/proxy/proxy_util.c

index bb32db72ead3dc1096d26fb1d43ee0ab851b3227..db2c057c01e5884c627f9a2c884560c18adb8ae0 100644 (file)
@@ -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);
     }
index 9cb255a7ced7735ce7ed2f27b4902f2fe83f697a..712d62b7e65552a06b8c50e89c06ff0030ab28aa 100644 (file)
@@ -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");