From: Amos Jeffries Date: Sat, 4 Dec 2010 13:11:43 +0000 (-0700) Subject: Author: Dmitry Kurochkin X-Git-Tag: take1~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a2bd457d68c341b0a5562fb67c916c061e7641c3;p=thirdparty%2Fsquid.git Author: Dmitry Kurochkin Bug 3099: Incorrect 412 on If-None-Match and If-Modified-Since --- diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc index afcaafaa4f..5e1f7ca3d4 100644 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@ -683,7 +683,7 @@ clientReplyContext::processOnlyIfCachedMiss() void clientReplyContext::processConditional(StoreIOBuffer &result) { - StoreEntry *e = http->storeEntry(); + StoreEntry *const e = http->storeEntry(); if (e->getReply()->sline.status != HTTP_OK) { debugs(88, 4, "clientReplyContext::processConditional: Reply code " << @@ -716,12 +716,12 @@ clientReplyContext::processConditional(StoreIOBuffer &result) if (!r.flags.ims) { // RFC 2616: if If-None-Match matched and there is no IMS, - // reply with 412 Precondition Failed - sendPreconditionFailedError(); + // reply with 304 Not Modified or 412 Precondition Failed + sendNotModifiedOrPreconditionFailedError(); return; } - // otherwise check IMS below to decide if we reply with 412 + // otherwise check IMS below to decide if we reply with 304 or 412 matchedIfNoneMatch = true; } @@ -734,29 +734,14 @@ clientReplyContext::processConditional(StoreIOBuffer &result) } if (matchedIfNoneMatch) { - // If-None-Match matched, reply with 412 Precondition Failed - sendPreconditionFailedError(); + // If-None-Match matched, reply with 304 Not Modified or + // 412 Precondition Failed + sendNotModifiedOrPreconditionFailedError(); return; } // otherwise reply with 304 Not Modified - const time_t timestamp = e->timestamp; - HttpReply *const temprep = e->getReply()->make304(); - http->logType = LOG_TCP_IMS_HIT; - removeClientStoreReference(&sc, http); - createStoreEntry(http->request->method, request_flags()); - e = http->storeEntry(); - // Copy timestamp from the original entry so the 304 - // reply has a meaningful Age: header. - e->timestamp = timestamp; - e->replaceHttpReply(temprep); - e->complete(); - /* - * TODO: why put this in the store and then serialise it and - * then parse it again. Simply mark the request complete in - * our context and write the reply struct to the client side. - */ - triggerInitialStoreRead(); + sendNotModified(); } } @@ -1865,6 +1850,42 @@ clientReplyContext::sendPreconditionFailedError() startError(err); } +/// send 304 (Not Modified) to client +void +clientReplyContext::sendNotModified() +{ + StoreEntry *e = http->storeEntry(); + const time_t timestamp = e->timestamp; + HttpReply *const temprep = e->getReply()->make304(); + http->logType = LOG_TCP_IMS_HIT; + removeClientStoreReference(&sc, http); + createStoreEntry(http->request->method, request_flags()); + e = http->storeEntry(); + // Copy timestamp from the original entry so the 304 + // reply has a meaningful Age: header. + e->timestamp = timestamp; + e->replaceHttpReply(temprep); + e->complete(); + /* + * TODO: why put this in the store and then serialise it and + * then parse it again. Simply mark the request complete in + * our context and write the reply struct to the client side. + */ + triggerInitialStoreRead(); +} + +/// send 304 (Not Modified) or 412 (Precondition Failed) to client +/// depending on request method +void +clientReplyContext::sendNotModifiedOrPreconditionFailedError() +{ + if (http->request->method == METHOD_GET || + http->request->method == METHOD_HEAD) + sendNotModified(); + else + sendPreconditionFailedError(); +} + void clientReplyContext::processReplyAccess () { diff --git a/src/client_side_reply.h b/src/client_side_reply.h index c1787f736d..77c023fb3f 100644 --- a/src/client_side_reply.h +++ b/src/client_side_reply.h @@ -138,6 +138,8 @@ private: void sendBodyTooLargeError(); void sendPreconditionFailedError(); + void sendNotModified(); + void sendNotModifiedOrPreconditionFailedError(); StoreEntry *old_entry; store_client *old_sc; /* ... for entry to be validated */