From: wessels <> Date: Fri, 5 Dec 1997 06:07:51 +0000 (+0000) Subject: Fix handling of certain non-200 HTTP replies (Henrik) X-Git-Tag: SQUID_3_0_PRE1~4390 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=978e455f59717d938688208d356b8f12ad5e0630;p=thirdparty%2Fsquid.git Fix handling of certain non-200 HTTP replies (Henrik) --- diff --git a/src/client_side.cc b/src/client_side.cc index a0c3f1fdb8..7ab2051ba9 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -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 * diff --git a/src/http.cc b/src/http.cc index 3dcc8a0745..a23659c7a8 100644 --- a/src/http.cc +++ b/src/http.cc @@ -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