]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
HTTP: initial support for Cache-Control:immutable
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 28 Oct 2016 07:56:00 +0000 (20:56 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 28 Oct 2016 07:56:00 +0000 (20:56 +1300)
The 'immutable' cache control is a proposed standardization of
behaviour equivalent to the refresh_pattern 'ignore-reload' option.
Reducing latency delays from revalidation when an object is known not
to be updated until it expires.

When a server emits it on responses a recipient cache is expected to
treat the response as not requiring any revalidation until it becomes
stale. For the duration of its freshness period it may be used as-is
to respond to client requests - including reload (CC:max-age=0)
requests.

This initial code does not yet support preventing IMS conditional
requests behaviour when the 'immutable' signal is received.

Note that CC:no-cache in requests, and If-None-Match ETag based
conditionals can still make an 'immutable' response be irrelevant to
a particular client request. So server contact is not completely
prevented.

Use 'immutable' option in preference over the refresh_pattern
'ignore-reload' in order to track whether that override is still
relevant.

src/HttpHdrCc.cc
src/HttpHdrCc.h
src/refresh.cc

index d4d2090c0a259b30fa323d8caceb0616732a4430..b3c65ba48759deded6e37e2476295c1bdcb035b4 100644 (file)
@@ -40,6 +40,7 @@ static LookupTable<HttpHdrCcType>::Record CcAttrs[] = {
     {"min-fresh", HttpHdrCcType::CC_MIN_FRESH},
     {"only-if-cached", HttpHdrCcType::CC_ONLY_IF_CACHED},
     {"stale-if-error", HttpHdrCcType::CC_STALE_IF_ERROR},
+    {"immutable", HttpHdrCcType::CC_IMMUTABLE},
     {"Other,", HttpHdrCcType::CC_OTHER}, /* ',' will protect from matches */
     {nullptr, HttpHdrCcType::CC_ENUM_END}
 };
@@ -202,6 +203,9 @@ HttpHdrCc::parse(const String & str)
         case HttpHdrCcType::CC_ONLY_IF_CACHED:
             onlyIfCached(true);
             break;
+        case HttpHdrCcType::CC_IMMUTABLE:
+            Immutable(true);
+            break;
 
         case HttpHdrCcType::CC_OTHER:
             if (other.size())
@@ -277,6 +281,8 @@ HttpHdrCc::packInto(Packable * p) const
             case HttpHdrCcType::CC_STALE_IF_ERROR:
                 p->appendf("=%d", staleIfError());
                 break;
+            case HttpHdrCcType::CC_IMMUTABLE:
+                break;
             case HttpHdrCcType::CC_OTHER:
             case HttpHdrCcType::CC_ENUM_END:
                 // done below after the loop
index f2b25af8f9985552ac6a11e752e8070f5edf928a..337130c444ef3fbfe588bed70a8cbd8c6d6d6a85 100644 (file)
@@ -30,6 +30,7 @@ enum HttpHdrCcType : unsigned char {
     CC_MIN_FRESH,
     CC_ONLY_IF_CACHED,
     CC_STALE_IF_ERROR,
+    CC_IMMUTABLE, /* draft-mcmanus-immutable-00 */
     CC_OTHER,
     CC_ENUM_END /* also used to mean "invalid" */
 };
@@ -160,6 +161,11 @@ public:
     void staleIfError(int32_t v) {setValue(stale_if_error,v,HttpHdrCcType::CC_STALE_IF_ERROR); }
     void clearStaleIfError() {setValue(stale_if_error,STALE_IF_ERROR_UNKNOWN,HttpHdrCcType::CC_STALE_IF_ERROR,false);}
 
+    //manipulation for Cache-Control: immutable header
+    bool Immutable() const {return isSet(HttpHdrCcType::CC_IMMUTABLE);}
+    void Immutable(bool v) {setMask(HttpHdrCcType::CC_IMMUTABLE,v);}
+    void clearImmutable() {setMask(HttpHdrCcType::CC_IMMUTABLE,false);}
+
     /// check whether the attribute value supplied by id is set
     _SQUID_INLINE_ bool isSet(HttpHdrCcType id) const;
 
index e82a912031bbab379cdd1312f31aff89a3a27d14..6a56547ccf968aab123319945bd4281b32823c01 100644 (file)
@@ -327,10 +327,12 @@ refreshCheck(const StoreEntry * entry, HttpRequest * request, time_t delta)
 
     debugs(22, 3, "Staleness = " << staleness);
 
+    const auto *reply = (entry->mem_obj && entry->mem_obj->getReply() ? entry->mem_obj->getReply() : nullptr);
+
     // stale-if-error requires any failure be passed thru when its period is over.
-    if (request && entry->mem_obj && entry->mem_obj->getReply() && entry->mem_obj->getReply()->cache_control &&
-            entry->mem_obj->getReply()->cache_control->hasStaleIfError() &&
-            entry->mem_obj->getReply()->cache_control->staleIfError() < staleness) {
+    if (request && reply && reply->cache_control &&
+            reply->cache_control->hasStaleIfError() &&
+            reply->cache_control->staleIfError() < staleness) {
 
         debugs(22, 3, "stale-if-error period expired. Will produce error if validation fails.");
         request->flags.failOnValidationError = true;
@@ -415,18 +417,21 @@ refreshCheck(const StoreEntry * entry, HttpRequest * request, time_t delta)
 
             // max-age directive
             if (cc->hasMaxAge()) {
+
+                // draft-mcmanus-immutable-00: reply contains CC:immutable then ignore client CC:max-age=N
+                if (reply && reply->cache_control && reply->cache_control->Immutable()) {
+                    debugs(22, 3, "MAYBE: Ignoring client CC:max-age=" << cc->maxAge() << " request - 'Cache-Control: immutable'");
+
 #if USE_HTTP_VIOLATIONS
-                // Ignore client "Cache-Control: max-age=0" header
-                if (R->flags.ignore_reload && cc->maxAge() == 0) {
+                // Ignore of client "Cache-Control: max-age=0" header
+                } else if (R->flags.ignore_reload && cc->maxAge() == 0) {
                     debugs(22, 3, "MAYBE: Ignoring client reload request - trying to serve from cache (ignore-reload option)");
-                } else
 #endif
-                {
-                    // Honour client "Cache-Control: max-age=x" header
-                    if (age > cc->maxAge() || cc->maxAge() == 0) {
-                        debugs(22, 3, "YES: Revalidating object - client 'Cache-Control: max-age=" << cc->maxAge() << "'");
-                        return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
-                    }
+
+                // Honour client "Cache-Control: max-age=x" header
+                } else if (age > cc->maxAge() || cc->maxAge() == 0) {
+                    debugs(22, 3, "YES: Revalidating object - client 'Cache-Control: max-age=" << cc->maxAge() << "'");
+                    return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE;
                 }
             }