--------------------- PatchSet 2432 Date: 2001/05/31 15:02:43 Author: hno Branch: etag Tag: (none) Log: Client-side If-Match and If-None-Match Members: src/client_side.c:1.29.2.6->1.29.2.7 Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.29.2.6 retrieving revision 1.29.2.7 diff -u -r1.29.2.6 -r1.29.2.7 --- squid/src/client_side.c 30 May 2001 23:17:30 -0000 1.29.2.6 +++ squid/src/client_side.c 31 May 2001 15:02:43 -0000 1.29.2.7 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.29.2.6 2001/05/30 23:17:30 hno Exp $ + * $Id: client_side.c,v 1.29.2.7 2001/05/31 15:02:43 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -1569,6 +1569,7 @@ StoreEntry *e = http->entry; MemObject *mem; request_t *r = http->request; + int is_modified = -1; debug(33, 3) ("clientCacheHit: %s, %d bytes\n", http->uri, (int) size); if (http->entry == NULL) { memFree(buf, MEM_CLIENT_SOCK_BUF); @@ -1668,7 +1669,10 @@ if (checkNegativeHit(e)) { http->log_type = LOG_TCP_NEGATIVE_HIT; clientSendMoreData(data, buf, size); - } else if (r->method == METHOD_HEAD) { + return; + } +#if THIS_IS_FALSE + if (r->method == METHOD_HEAD) { /* * RFC 2068 seems to indicate there is no "conditional HEAD" * request. We cannot validate a cached object for a HEAD @@ -1677,7 +1681,36 @@ if (e->mem_status == IN_MEMORY) http->log_type = LOG_TCP_MEM_HIT; clientSendMoreData(data, buf, size); - } else if (refreshCheckHTTP(e, r) && !http->flags.internal) { + return; + } +#endif + if (httpHeaderHas(&r->header, HDR_IF_MATCH)) { + String req_etags; + const char *rep_etag = httpHeaderGetStr(&r->header, HDR_ETAG); + int has_etag; + if (!rep_etag) { + /* The cached object does not have a entity tag. This cannot + * be a hit for the requested object. + */ + http->log_type = LOG_TCP_MISS; + memFree(buf, MEM_CLIENT_SOCK_BUF); + clientProcessMiss(http); + return; + } + req_etags = httpHeaderGetList(&http->request->header, HDR_IF_MATCH); + has_etag = strListIsMember(&req_etags, rep_etag, ','); + stringClean(&req_etags); + if (!has_etag) { + /* The entity tags does not match. This cannot be a + * hit for this object. Qyery the origin. + */ + http->log_type = LOG_TCP_MISS; + memFree(buf, MEM_CLIENT_SOCK_BUF); + clientProcessMiss(http); + return; + } + } + if (refreshCheckHTTP(e, r) && !http->flags.internal) { debug(33, 5) ("clientCacheHit: in refreshCheck() block\n"); /* * We hold a stale copy; it needs to be validated @@ -1720,7 +1753,38 @@ clientProcessMiss(http); } memFree(buf, MEM_CLIENT_SOCK_BUF); - } else if (r->flags.ims) { + return; + } + if (httpHeaderHas(&r->header, HDR_IF_NONE_MATCH)) { + String req_etags; + const char *rep_etag = httpHeaderGetStr(&r->header, HDR_ETAG); + int has_etag; + if (mem->reply->sline.status != HTTP_OK) { + debug(33, 4) ("clientCacheHit: Reply code %d != 200\n", + mem->reply->sline.status); + memFree(buf, MEM_CLIENT_SOCK_BUF); + http->log_type = LOG_TCP_MISS; + clientProcessMiss(http); + return; + } + if (!rep_etag) { + /* The cached object does not have a entity tag, but the client + * obviously thinks there should be one... Query the origin to + * be on the safe side. + */ + http->log_type = LOG_TCP_MISS; + memFree(buf, MEM_CLIENT_SOCK_BUF); + clientProcessMiss(http); + return; + } + req_etags = httpHeaderGetList(&http->request->header, HDR_IF_NONE_MATCH); + has_etag = strListIsMember(&req_etags, rep_etag, ','); + stringClean(&req_etags); + if (has_etag) { + http->log_type = LOG_TCP_IMS_HIT; + } + } + if (r->flags.ims) { /* * Handle If-Modified-Since requests from the client */ @@ -1730,39 +1794,43 @@ memFree(buf, MEM_CLIENT_SOCK_BUF); http->log_type = LOG_TCP_MISS; clientProcessMiss(http); + return; } else if (modifiedSince(e, http->request)) { http->log_type = LOG_TCP_IMS_HIT; clientSendMoreData(data, buf, size); - } else { - time_t timestamp = e->timestamp; - MemBuf mb = httpPacked304Reply(e->mem_obj->reply); - http->log_type = LOG_TCP_IMS_HIT; - memFree(buf, MEM_CLIENT_SOCK_BUF); - storeUnregister(http->sc, e, http); - http->sc = NULL; - storeUnlockObject(e); - e = clientCreateStoreEntry(http, http->request->method, null_request_flags); - /* - * Copy timestamp from the original entry so the 304 - * reply has a meaningful Age: header. - */ - e->timestamp = timestamp; - http->entry = e; - httpReplyParse(e->mem_obj->reply, mb.buf, mb.size); - storeAppend(e, mb.buf, mb.size); - memBufClean(&mb); - storeComplete(e); + return; } - } else { + is_modified = 0; + } + if (is_modified == 0) { + time_t timestamp = e->timestamp; + MemBuf mb = httpPacked304Reply(e->mem_obj->reply); + http->log_type = LOG_TCP_IMS_HIT; + memFree(buf, MEM_CLIENT_SOCK_BUF); + storeUnregister(http->sc, e, http); + http->sc = NULL; + storeUnlockObject(e); + e = clientCreateStoreEntry(http, http->request->method, null_request_flags); /* - * plain ol' cache hit + * Copy timestamp from the original entry so the 304 + * reply has a meaningful Age: header. */ - if (e->mem_status == IN_MEMORY) - http->log_type = LOG_TCP_MEM_HIT; - else if (Config.onoff.offline) - http->log_type = LOG_TCP_OFFLINE_HIT; - clientSendMoreData(data, buf, size); + e->timestamp = timestamp; + http->entry = e; + httpReplyParse(e->mem_obj->reply, mb.buf, mb.size); + storeAppend(e, mb.buf, mb.size); + memBufClean(&mb); + storeComplete(e); + return; } + /* + * plain ol' cache hit + */ + if (e->mem_status == IN_MEMORY) + http->log_type = LOG_TCP_MEM_HIT; + else if (Config.onoff.offline) + http->log_type = LOG_TCP_OFFLINE_HIT; + clientSendMoreData(data, buf, size); } /* put terminating boundary for multiparts */