On Tue, 2016-11-29 at 15:42 -0700, Alex Rousskov wrote:
> On 11/29/2016 02:23 PM, Amos Jeffries wrote:
> >
> > On 30/11/2016 1:47 a.m., Garri Djavadyan wrote:
> > >
> > > On Tue, 2016-11-29 at 14:51 +0500, Garri Djavadyan wrote:
> > > >
> > > > Hello,
> > > >
> > > > Please review the attached patch prepared for r14958, it fixes
> > > > the
> > > > If-
> > > > None-Match processing (incorrect logging [1]) and the bug [2]
> > > > report
> > > > 4169 depending on the incorrect (IMO) behavior.
> > > >
> > > > An If-None-Match request for a non-matched (ETag) but cached
> > > > object
> > > > should be processed as normal HIT.
> > > >
> > > > [1] http://lists.squid-cache.org/pipermail/squid-users/2016-Nov
> > > > ember/013483.html
> > > > [2] http://bugs.squid-cache.org/show_bug.cgi?id=4169
>
> >
> > >
> > > In the first version I
> > > removed strings (not related to the fix) which mark a request as
> > > non-
> > > IMS, because I thought the same request could not
> > > enter processConditional twice and the removed actions are
> > > redundant.
>
> I agree that the second version is better: Unless you are absolutely
> sure, it is best to stay focused on the problem and leave the IMS
> deletion code "as is" even if it may not be necessary. If you still
> suspect it is not necessary, add a TODO comment to investigate
> separately.
>
>
> >
> > Checking this whole processConditional() sequence for compliance
> > with
> > RFC 7232 and 7234 the rest of the logic seems to be fine except
> > this case:
> >
> > <https://tools.ietf.org/html/rfc7234#section-4.3.2>
> > "
> > If the field-value is "*", or if the
> > field-value is a list of entity-tags and at least one of them
> > matches
> > the entity-tag of the selected stored response,
>
> >
> > [ e->hasIfNoneMatchEtag(r) == false --> !N == true ]
>
> I am not sure I am interpreting your [...] mnemonic correctly, but
> AFAICT, the patched code works when the RFC conditions quoted above
> are
> _not_ meant:
>
> >
> > if (r.header.has(Http::HdrType::IF_NONE_MATCH)) {
> > if (!e->hasIfNoneMatchEtag(r)) {
> > // RFC 2616: ignore IMS if If-None-Match did not match
> > r.flags.ims = false;
> > r.ims = -1;
> > r.imslen = 0;
> > r.header.delById(Http::HdrType::IF_MODIFIED_SINCE);
> > http->logType = LOG_TCP_MISS;
> > sendMoreData(result);
> > return true;
> > }
>
>
> In other words, hasIfNoneMatchEtag() returns false and, hence, the
> quoted code is executed when _none_ of the requested ETags matches
> the
> cached ETag. The "if If-None-Match did not match" comment inside that
> code agrees with this interpretation.
>
> Thus, the recommended RFC action that you found does _not_ apply to
> the
> fixed code:
>
> >
> > a cache recipient
> > SHOULD generate a 304 (Not Modified) response (using the
> > metadata of
> > the selected stored response) instead of sending that stored
> > response.
> > "
>
>
> If you were talking about processConditional() code outside the if
> statement fixed by Garri (i.e., when hasIfNoneMatchEtag() returns
> true),
> then it appears to match the quoted requirement only if there is no
> IMS
> header:
>
> >
> > if (!r.flags.ims) {
> > // RFC 2616: if If-None-Match matched and there is no IMS,
> > // reply with 304 Not Modified or 412 Precondition Failed
> > sendNotModifiedOrPreconditionFailedError();
> > return true;
> > }
> >
> > // otherwise check IMS below to decide if we reply with 304 or 412
> > matchedIfNoneMatch = true;
>
>
> If there is an IMS header, then Squid violates the following RFC 7232
> MUST:
>
> >
> > A recipient MUST ignore If-Modified-Since if the request contains
> > an
> > If-None-Match header field
>
> The HTTP requirements changed here since RFC 2616, and we probably
> should adjust the code to delete IMS header/flags after discovering
> the
> If-None-Match header:
>
> if (r.header.has(Http::HdrType::IF_NONE_MATCH)) {
> // RFC 7232: If-None-Match recipient MUST ignore IMS
> r.flags.ims = false;
> r.ims = -1;
> r.imslen = 0;
> r.header.delById(Http::HdrType::IF_MODIFIED_SINCE);
>
> if (e->hasIfNoneMatchEtag(r)) {
> sendNotModifiedOrPreconditionFailedError();
> return true;
> }
>
> // If-None-Match did not match; treat as an unconditional hit
> return false;
> }
>
> If the above sketch is correct, then the matchedIfNoneMatch variable
> may
> become unnecessary.
Alex, Amos thanks for comments! I've attached third version of the
patch. It is based on the proposal by Alex. The patch introduces
following changes:
* Matched If-None-Match requests are logged as TCP_INM_HIT (proposed by
Amos)
* If-Modified-Since requests for modified cached objects are processed
as normal HITs
* Not matched If-None-Match requests for cached objects are processed
as normal HITs
* If-Modified-Since header is ignored if If-None-Match header exists
(RFC7232 compliance)
I've tested different conditional requests (including 'If-None-Match:
*' and 'If-None-Match: "matched-tag", "not-matched-tag"') and found no
problems. Thanks.
Garri
=== modified file 'src/LogTags.cc'
--- src/LogTags.cc 2016-10-08 22:19:44 +0000
+++ src/LogTags.cc 2016-11-30 09:46:54 +0000
@@ -21,6 +21,7 @@
"TCP_REFRESH",
"TCP_CLIENT_REFRESH_MISS",
"TCP_IMS_HIT",
+ "TCP_INM_HIT",
"TCP_SWAPFAIL_MISS",
"TCP_NEGATIVE_HIT",
"TCP_MEM_HIT",
@@ -73,6 +74,7 @@
return
(oldType == LOG_TCP_HIT) ||
(oldType == LOG_TCP_IMS_HIT) ||
+ (oldType == LOG_TCP_INM_HIT) ||
(oldType == LOG_TCP_REFRESH_FAIL_OLD) ||
(oldType == LOG_TCP_REFRESH_UNMODIFIED) ||
(oldType == LOG_TCP_NEGATIVE_HIT) ||
=== modified file 'src/LogTags.h'
--- src/LogTags.h 2016-10-08 22:19:44 +0000
+++ src/LogTags.h 2016-11-30 07:11:46 +0000
@@ -28,6 +28,7 @@
LOG_TCP_REFRESH, // refresh from origin started, but still pending
LOG_TCP_CLIENT_REFRESH_MISS,
LOG_TCP_IMS_HIT,
+ LOG_TCP_INM_HIT,
LOG_TCP_SWAPFAIL_MISS,
LOG_TCP_NEGATIVE_HIT,
LOG_TCP_MEM_HIT,
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2016-11-18 18:08:30 +0000
+++ src/client_side.cc 2016-11-30 07:13:38 +0000
@@ -233,6 +233,10 @@
statCounter.client_http.nearMissSvcTime.count(svc_time);
break;
+ case LOG_TCP_INM_HIT:
+ statCounter.client_http.nearMissSvcTime.count(svc_time);
+ break;
+
case LOG_TCP_HIT:
case LOG_TCP_MEM_HIT:
=== modified file 'src/client_side_reply.cc'
--- src/client_side_reply.cc 2016-11-11 04:28:06 +0000
+++ src/client_side_reply.cc 2016-11-30 11:40:07 +0000
@@ -796,40 +796,27 @@
return true;
}
- bool matchedIfNoneMatch = false;
if (r.header.has(Http::HdrType::IF_NONE_MATCH)) {
- if (!e->hasIfNoneMatchEtag(r)) {
- // RFC 2616: ignore IMS if If-None-Match did not match
+ if (e->hasIfNoneMatchEtag(r)) {
+ // RFC 7232: If-None-Match recipient MUST ignore IMS
r.flags.ims = false;
r.ims = -1;
r.imslen = 0;
r.header.delById(Http::HdrType::IF_MODIFIED_SINCE);
- http->logType = LOG_TCP_MISS;
- sendMoreData(result);
- return true;
- }
- if (!r.flags.ims) {
- // RFC 2616: if If-None-Match matched and there is no IMS,
- // reply with 304 Not Modified or 412 Precondition Failed
sendNotModifiedOrPreconditionFailedError();
return true;
}
- // otherwise check IMS below to decide if we reply with 304 or 412
- matchedIfNoneMatch = true;
+ // If-None-Match did not match; treat as an unconditional hit
+ return false;
}
if (r.flags.ims) {
// handle If-Modified-Since requests from the client
if (e->modifiedSince(r.ims, r.imslen)) {
- http->logType = LOG_TCP_IMS_HIT;
- sendMoreData(result);
-
- } else if (matchedIfNoneMatch) {
- // If-None-Match matched, reply with 304 Not Modified or
- // 412 Precondition Failed
- sendNotModifiedOrPreconditionFailedError();
+ // object modified; treat as an unconditional hit
+ return false;
} else {
// otherwise reply with 304 Not Modified
@@ -1989,7 +1976,12 @@
StoreEntry *e = http->storeEntry();
const time_t timestamp = e->timestamp;
HttpReply *const temprep = e->getReply()->make304();
- http->logType = LOG_TCP_IMS_HIT;
+ // log as TCP_INM_HIT if code 304 generated for
+ // If-None-Match request
+ if (!http->request->flags.ims)
+ http->logType = LOG_TCP_INM_HIT;
+ else
+ http->logType = LOG_TCP_IMS_HIT;
removeClientStoreReference(&sc, http);
createStoreEntry(http->request->method, RequestFlags());
e = http->storeEntry();
_______________________________________________
squid-dev mailing list
[email protected]
http://lists.squid-cache.org/listinfo/squid-dev