]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Fix handling of certain non-200 HTTP replies (Henrik)
authorwessels <>
Fri, 5 Dec 1997 06:07:51 +0000 (06:07 +0000)
committerwessels <>
Fri, 5 Dec 1997 06:07:51 +0000 (06:07 +0000)
src/client_side.cc
src/http.cc

index a0c3f1fdb8d7c653bb495003dbdcc707bf0a193d..7ab2051ba972d3d3390e7c74e27b4aa890ffaf5b 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.172 1997/12/04 00:07:33 wessels Exp $
+ * $Id: client_side.cc,v 1.173 1997/12/04 23:07:51 wessels Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -1822,40 +1822,68 @@ CheckQuickAbort(clientHttpRequest * http)
     storeAbort(entry, 1);
 }
 
+#define SENDING_BODY 0
+#define SENDING_HDRSONLY 1
 static int
 icpCheckTransferDone(clientHttpRequest * http)
 {
+    int sending = SENDING_BODY;
     StoreEntry *entry = http->entry;
-    MemObject *mem = NULL;
+    MemObject *mem;
+    http_reply *reply;
+    int sendlen;
     if (entry == NULL)
        return 0;
-    if (entry->store_status != STORE_PENDING)
+    /*
+     * Handle STORE_OK and STORE_ABORTED objects.
+     * entry->object_len will be set proprely.
+     */
+    if (entry->store_status != STORE_PENDING) {
        if (http->out.offset >= entry->object_len)
            return 1;
-    if ((mem = entry->mem_obj) == NULL)
-       return 0;
-    if (mem->reply->content_length < 0) {
-       /*
-        * for 200 replies, we MUST have a content length,
-        * or wait for EOF on the socket.
-        */
-       if (mem->reply->code == 200)
-           return 0;
-       /*
-        * reply->hdr_sz will be set by httpParseReplyHeaders()
-        * if we find the end of the headers.  If we find the end,
-        * and there is no content length, stick a fork in us. 
-        */
-       else if (mem->reply->hdr_sz == 0)
-           return 0;
-       else if (http->out.offset >= mem->reply->hdr_sz)
-           return 1;
        else
            return 0;
     }
-    if (http->out.offset >= mem->reply->content_length + mem->reply->hdr_sz)
-       return 1;
-    return 0;
+    /*
+     * Now, handle STORE_PENDING objects
+     */
+    mem = entry->mem_obj;
+    assert(mem != NULL);
+    assert(http->request != NULL);
+    reply = mem->reply;
+    if (reply->hdr_sz == 0)
+       return 0;       /* haven't found end of headers yet */
+    else if (reply->code == HTTP_OK)
+        sending = SENDING_BODY;
+    else if (reply->content_length < 0)
+       sending = SENDING_HDRSONLY;
+    else if (reply->code == HTTP_NO_CONTENT)
+        sending = SENDING_HDRSONLY;
+    else if (reply->code == HTTP_NOT_MODIFIED)
+        sending = SENDING_HDRSONLY;
+    else if (http->request->method == METHOD_HEAD)
+        sending = SENDING_HDRSONLY;
+    else
+       sending = SENDING_BODY;
+    /*
+     * Figure out how much data we are supposed to send.
+     * If we are sending a body and we don't have a content-length,
+     * then we must wait for the object to become STORE_OK or
+     * STORE_ABORTED.
+     */
+    if (sending == SENDING_HDRSONLY)
+       sendlen = reply->hdr_sz;
+    else if (reply->content_length < 0)
+       return 0;
+    else
+       sendlen = reply->content_length + reply->hdr_sz;
+    /*
+     * Now that we have the expected length, did we send it all?
+     */
+    if (http->out.offset < sendlen)
+       return 0;
+    else
+        return 1;
 }
 
 static char *
index 3dcc8a074534861124287c0f141568e1474c290e..a23659c7a88964edc5d56abd43a2951f56a2012a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.cc,v 1.227 1997/12/03 09:00:18 wessels Exp $
+ * $Id: http.cc,v 1.228 1997/12/04 23:07:52 wessels Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -570,33 +570,48 @@ httpPconnTransferDone(HttpStateData * httpState)
     MemObject *mem = httpState->entry->mem_obj;
     struct _http_reply *reply = mem->reply;
     debug(11, 3) ("httpPconnTransferDone: FD %d\n", httpState->fd);
+    /*
+     * If we didn't send a Keepalive request header, then this
+     * can not be a persistent connection.
+     */
     if (!EBIT_TEST(httpState->flags, HTTP_KEEPALIVE))
        return 0;
     debug(11, 5) ("httpPconnTransferDone: content_length=%d\n",
        reply->content_length);
     /*
-     * !200 replies maybe don't have content-length, so
-     * if we saw the end of the headers then try being persistent.
+     * Deal with gross HTTP stuff
+     *    - If we haven't seen the end of the reply headers, we can't
+     *      be persistent.
+     *    - For "200 OK" check the content-length in the next block.
+     *    - For other replies without a content-length, we're done.
+     *    - For "204 No Content" (even with content-length) we're done.
+     *    - For "304 Not Modified" (even with content-length) we're done.
+     *    - For HEAD requests with content-length we're done.
+     *    - For other replies with a content length, we continue...
      */
-    if (reply->code != 200)
-       if (reply->content_length < 0)
-           if (httpState->reply_hdr_state > 1)
-               return 1;
+    if (httpState->reply_hdr_state < 2)
+       return 0;
+    else if (reply->code == HTTP_OK)
+       (void) 0;               /* continue */
+    else if (reply->content_length < 0)
+       return 1;
+    else if (reply->code == HTTP_NO_CONTENT)
+       return 1;
+    else if (reply->code == HTTP_NOT_MODIFIED)
+       return 1;
+    else if (httpState->request->method == METHOD_HEAD)
+       return 1;
     /*
-     * If there is no content-length, then we probably can't be persistent
+     * If there is no content-length, then we probably can't be
+     * persistent.  If there is a content length, then we must
+     * wait until we've seen the end of the body.
      */
     if (reply->content_length < 0)
        return 0;
-    /*
-     * If there is a content_length, see if we've got all of it.  If so,
-     * then we can recycle this connection.
-     */
-    debug(11, 5) ("httpPconnTransferDone: hdr_sz=%d\n", reply->hdr_sz);
-    debug(11, 5) ("httpPconnTransferDone: inmem_hi=%d\n",
-       mem->inmem_hi);
-    if (mem->inmem_hi < reply->content_length + reply->hdr_sz)
+    else if (mem->inmem_hi < reply->content_length + reply->hdr_sz)
        return 0;
-    return 1;
+    else
+        return 1;
 }
 
 /* This will be called when data is ready to be read from fd.  Read until