System.Net.Cache.Rfc2616.Common.ComputeFreshness C# (CSharp) Method

ComputeFreshness() public static method

public static ComputeFreshness ( HttpRequestCacheValidator ctx ) : CacheFreshnessStatus
ctx HttpRequestCacheValidator
return CacheFreshnessStatus
            public static CacheFreshnessStatus ComputeFreshness(HttpRequestCacheValidator ctx) {

                if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_now_time, DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture)));

                /*
                     apparent_age = max(0, response_time - date_value);
                */

                DateTime nowDate = DateTime.UtcNow;

                TimeSpan age  = TimeSpan.MaxValue;
                DateTime date = ctx.CacheDate;

                if (date != DateTime.MinValue) {
                    age = (nowDate - date);
                    if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_age1_date_header, ((int)age.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo), ctx.CacheDate.ToString("r", CultureInfo.InvariantCulture)));
                }
                else if (ctx.CacheEntry.LastSynchronizedUtc != DateTime.MinValue) {
                    /*
                        Another way to compute cache age but only if Date header is absent.
                    */
                    age = nowDate - ctx.CacheEntry.LastSynchronizedUtc;
                    if (ctx.CacheAge != TimeSpan.MinValue) {
                        age += ctx.CacheAge;
                    }
                    if(Logging.On) {
                        if (ctx.CacheAge != TimeSpan.MinValue)
                            Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_age1_last_synchronized_age_header, ((int)age.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo), ctx.CacheEntry.LastSynchronizedUtc.ToString("r", CultureInfo.InvariantCulture), ((int)ctx.CacheAge.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo)));
                        else
                            Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_age1_last_synchronized, ((int)age.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo), ctx.CacheEntry.LastSynchronizedUtc.ToString("r", CultureInfo.InvariantCulture))); 
                    }
                }

                /*
                    corrected_received_age = max(apparent_age, age_value);
                */
                if (ctx.CacheAge != TimeSpan.MinValue) {
                    if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_age2, ((int)ctx.CacheAge.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo)));
                    if (ctx.CacheAge > age || age == TimeSpan.MaxValue) {
                        age = ctx.CacheAge;
                    }
                }

                // Updating CacheAge ...
                // Note we don't account on response "transit" delay
                // Also undefined cache entry Age is reported as TimeSpan.MaxValue (which is impossble to get from HTTP)
                // Also a negative age is reset to 0 as per RFC
                ctx.CacheAge = (age < TimeSpan.Zero? TimeSpan.Zero: age);

                // Now we start checking the server specified requirements

                /*
                The calculation to determine if a response has expired is quite simple:
                response_is_fresh = (freshness_lifetime > current_age)
                */

                // If we managed to compute the Cache Age
                if (ctx.CacheAge != TimeSpan.MinValue) {

                    /*
                        s-maxage
                        If a response includes an s-maxage directive, then for a shared
                        cache (but not for a private cache), the maximum age specified by
                        this directive overrides the maximum age specified by either the
                        max-age directive or the Expires header.
                    */
                    if (!ctx.CacheEntry.IsPrivateEntry && ctx.CacheCacheControl.SMaxAge != -1) {
                        ctx.CacheMaxAge = TimeSpan.FromSeconds(ctx.CacheCacheControl.SMaxAge);
                        if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_max_age_cache_s_max_age, ((int)ctx.CacheMaxAge.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo)));
                        if (ctx.CacheAge < ctx.CacheMaxAge) {
                            return CacheFreshnessStatus.Fresh;
                        }
                        return CacheFreshnessStatus.Stale;
                    }

                    /*
                    The max-age directive takes priority over Expires, so if max-age is
                    present in a response, the calculation is simply:
                            freshness_lifetime = max_age_value
                    */
                    if (ctx.CacheCacheControl.MaxAge != -1) {
                        ctx.CacheMaxAge = TimeSpan.FromSeconds(ctx.CacheCacheControl.MaxAge);
                        if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_max_age_cache_max_age, ((int)ctx.CacheMaxAge.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo)));
                        if (ctx.CacheAge < ctx.CacheMaxAge) {
                            return CacheFreshnessStatus.Fresh;
                        }
                        return CacheFreshnessStatus.Stale;
                    }
                }

                /*
                 Otherwise, if Expires is present in the response, the calculation is:
                        freshness_lifetime = expires_value - date_value
                */
                if (date == DateTime.MinValue) {
                    date = ctx.CacheEntry.LastSynchronizedUtc;
                }

                DateTime expiresDate = ctx.CacheEntry.ExpiresUtc;
                if (ctx.CacheExpires != DateTime.MinValue && ctx.CacheExpires < expiresDate) {
                    expiresDate = ctx.CacheExpires;
                }

                // If absolute Expires and Response Date and Cache Age can be recovered
                if (expiresDate != DateTime.MinValue && date != DateTime.MinValue && ctx.CacheAge != TimeSpan.MinValue) {
                    ctx.CacheMaxAge = expiresDate - date;
                    if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_max_age_expires_date, ((int)((expiresDate - date).TotalSeconds)).ToString(NumberFormatInfo.InvariantInfo), expiresDate.ToString("r", CultureInfo.InvariantCulture)));
                    if (ctx.CacheAge < ctx.CacheMaxAge) {
                        return CacheFreshnessStatus.Fresh;
                    }
                    return CacheFreshnessStatus.Stale;
                }

                // If absolute Expires can be recovered
                if (expiresDate != DateTime.MinValue) {
                    ctx.CacheMaxAge = expiresDate - DateTime.UtcNow;
                    //Take absolute Expires value
                    if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_max_age_absolute, expiresDate.ToString("r", CultureInfo.InvariantCulture)));
                    if (expiresDate < DateTime.UtcNow) {
                        return CacheFreshnessStatus.Fresh;
                    }
                    return CacheFreshnessStatus.Stale;
                }

                /*
                   If none of Expires, Cache-Control: max-age, or Cache-Control: s-
                   maxage (see section 14.9.3) appears in the response, and the response
                   does not include other restrictions on caching, the cache MAY compute
                   a freshness lifetime using a heuristic. The cache MUST attach Warning
                   113 to any response whose age is more than 24 hours if such warning
                   has not already been added.

                   Also, if the response does have a Last-Modified time, the heuristic
                   expiration value SHOULD be no more than some fraction of the interval
                   since that time. A typical setting of this fraction might be 10%.

                        response_is_fresh = (freshness_lifetime > current_age)
               */

                ctx.HeuristicExpiration = true;

                DateTime lastModifiedDate = ctx.CacheEntry.LastModifiedUtc;
                if (ctx.CacheLastModified > lastModifiedDate) {
                    lastModifiedDate = ctx.CacheLastModified;
                }                   ctx.CacheMaxAge = ctx.UnspecifiedMaxAge;

                if (lastModifiedDate != DateTime.MinValue) {
                    TimeSpan span = (nowDate - lastModifiedDate);
                    int maxAgeSeconds = (int)(span.TotalSeconds/10);
                    ctx.CacheMaxAge = TimeSpan.FromSeconds(maxAgeSeconds);
                    if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_max_age_use_10_percent, maxAgeSeconds.ToString(NumberFormatInfo.InvariantInfo), lastModifiedDate.ToString("r", CultureInfo.InvariantCulture)));
                    if (ctx.CacheAge.TotalSeconds < maxAgeSeconds) {
                        return CacheFreshnessStatus.Fresh;
                    }
                    return CacheFreshnessStatus.Stale;
                }

                // Else we can only rely on UnspecifiedMaxAge hint
                ctx.CacheMaxAge = ctx.UnspecifiedMaxAge;
                if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_max_age_use_default, ((int)(ctx.UnspecifiedMaxAge.TotalSeconds)).ToString(NumberFormatInfo.InvariantInfo)));
                if (ctx.CacheMaxAge >= ctx.CacheAge) {
                    return CacheFreshnessStatus.Fresh;
                }
                return CacheFreshnessStatus.Stale;
            }