Chromium Code Reviews| Index: net/http/http_response_headers.cc |
| diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc |
| index 3a9f7e04fe0c4bad6a232ae52270e55427532d03..2620e2aede12d6d555f79b01ec24906b7056b915 100644 |
| --- a/net/http/http_response_headers.cc |
| +++ b/net/http/http_response_headers.cc |
| @@ -956,15 +956,28 @@ bool HttpResponseHeaders::IsRedirectResponseCode(int response_code) { |
| // Of course, there are other factors that can force a response to always be |
| // validated or re-fetched. |
| // |
| -bool HttpResponseHeaders::RequiresValidation(const Time& request_time, |
| - const Time& response_time, |
| - const Time& current_time) const { |
| - TimeDelta lifetime = |
| - GetFreshnessLifetime(response_time); |
| - if (lifetime == TimeDelta()) |
| - return true; |
| +// From RFC 5861 section 3, a stale response may be used while revalidation is |
| +// performed in the background if |
| +// |
| +// freshness_lifetime + stale_while_revalidate > current_age |
| +// |
| +ValidationType HttpResponseHeaders::RequiresValidation( |
| + const Time& request_time, |
| + const Time& response_time, |
| + const Time& current_time) const { |
| + FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time); |
| + if (lifetimes.fresh == TimeDelta() && lifetimes.stale == TimeDelta()) |
| + return VALIDATION_SYNCHRONOUS; |
| + |
| + TimeDelta age = GetCurrentAge(request_time, response_time, current_time); |
| + |
| + if (lifetimes.fresh > age) |
| + return VALIDATION_NONE; |
| + |
| + if (lifetimes.fresh + lifetimes.stale > age) |
| + return VALIDATION_ASYNCHRONOUS; |
| - return lifetime <= GetCurrentAge(request_time, response_time, current_time); |
| + return VALIDATION_SYNCHRONOUS; |
| } |
| // From RFC 2616 section 13.2.4: |
| @@ -987,25 +1000,31 @@ bool HttpResponseHeaders::RequiresValidation(const Time& request_time, |
| // |
| // freshness_lifetime = (date_value - last_modified_value) * 0.10 |
| // |
| -TimeDelta HttpResponseHeaders::GetFreshnessLifetime( |
| - const Time& response_time) const { |
| +// If the stale-while-revalidate directive is present, then it is used to set |
| +// the |stale| time, unless it overridden by another directive. |
| +// |
| +HttpResponseHeaders::FreshnessLifetimes |
| +HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const { |
| + FreshnessLifetimes lifetimes; |
| // Check for headers that force a response to never be fresh. For backwards |
| // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control: |
| // no-cache" even though RFC 2616 does not specify it. |
| if (HasHeaderValue("cache-control", "no-cache") || |
| HasHeaderValue("cache-control", "no-store") || |
| HasHeaderValue("pragma", "no-cache") || |
| - HasHeaderValue("vary", "*")) // see RFC 2616 section 13.6 |
| - return TimeDelta(); // not fresh |
| + HasHeaderValue("vary", "*")) { // see RFC 2616 section 13.6 |
|
rvargas (doing something else)
2014/09/12 18:33:12
nit: The comment location looks weird. Next line?
Adam Rice
2014/09/16 11:53:01
That didn't look right. I tried putting it above,
rvargas (doing something else)
2014/09/17 04:32:19
perfect
|
| + return lifetimes; |
| + } |
| + |
| + if (!GetStaleWhileRevalidateValue(&lifetimes.stale)) |
| + DCHECK(lifetimes.stale == TimeDelta()); |
| // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the |
| - // Expires header after checking for max-age in GetFreshnessLifetime. This |
| + // Expires header after checking for max-age in GetFreshnessLifetimes. This |
| // is important since "Expires: <date in the past>" means not fresh, but |
| // it should not trump a max-age value. |
| - |
| - TimeDelta max_age_value; |
| - if (GetMaxAgeValue(&max_age_value)) |
| - return max_age_value; |
| + if (GetMaxAgeValue(&lifetimes.fresh)) |
| + return lifetimes; |
| // If there is no Date header, then assume that the server response was |
| // generated at the time when we received the response. |
| @@ -1016,10 +1035,13 @@ TimeDelta HttpResponseHeaders::GetFreshnessLifetime( |
| Time expires_value; |
| if (GetExpiresValue(&expires_value)) { |
| // The expires value can be a date in the past! |
| - if (expires_value > date_value) |
| - return expires_value - date_value; |
| + if (expires_value > date_value) { |
| + lifetimes.fresh = expires_value - date_value; |
| + return lifetimes; |
| + } |
| - return TimeDelta(); // not fresh |
| + DCHECK(lifetimes.fresh == TimeDelta()); |
| + return lifetimes; |
| } |
| // From RFC 2616 section 13.4: |
| @@ -1046,25 +1068,37 @@ TimeDelta HttpResponseHeaders::GetFreshnessLifetime( |
| // https://datatracker.ietf.org/doc/draft-reschke-http-status-308/ is an |
| // experimental RFC that adds 308 permanent redirect as well, for which "any |
| // future references ... SHOULD use one of the returned URIs." |
| + // |
| + // TODO(ricea): RFC7234 adds extra cacheable status codes and stops |
| + // "must-revalidate" from influencing heuristic expiration. This code should |
| + // be changed to match once the RFC has had time to mature. |
| if ((response_code_ == 200 || response_code_ == 203 || |
| response_code_ == 206) && |
| !HasHeaderValue("cache-control", "must-revalidate")) { |
| // TODO(darin): Implement a smarter heuristic. |
| Time last_modified_value; |
| if (GetLastModifiedValue(&last_modified_value)) { |
| - // The last-modified value can be a date in the past! |
| - if (last_modified_value <= date_value) |
| - return (date_value - last_modified_value) / 10; |
| + // The last-modified value can be a date in the future! |
| + if (last_modified_value <= date_value) { |
| + lifetimes.fresh = (date_value - last_modified_value) / 10; |
| + return lifetimes; |
| + } |
| } |
| } |
| // These responses are implicitly fresh (unless otherwise overruled): |
| if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 || |
| response_code_ == 410) { |
| - return TimeDelta::Max(); |
| + lifetimes.fresh = TimeDelta::Max(); |
| + lifetimes.stale = TimeDelta(); // It should never be stale. |
| + return lifetimes; |
| } |
| - return TimeDelta(); // not fresh |
| + // Our heuristic freshness estimate for this resource is 0 seconds, in |
| + // accordance with common browser behaviour. However, stale-while-revalidate |
| + // may still apply. |
| + DCHECK(lifetimes.fresh == TimeDelta()); |
| + return lifetimes; |
| } |
| // From RFC 2616 section 13.2.3: |