Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: net/http/http_response_headers.cc

Issue 665023002: Post-commit fixes for "stale-while-revalidate..." (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/http/http_response_headers.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // The rules for header parsing were borrowed from Firefox: 5 // The rules for header parsing were borrowed from Firefox:
6 // http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpRespo nseHead.cpp 6 // http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpRespo nseHead.cpp
7 // The rules for parsing content-types were also borrowed from Firefox: 7 // The rules for parsing content-types were also borrowed from Firefox:
8 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 8 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834
9 9
10 #include "net/http/http_response_headers.h" 10 #include "net/http/http_response_headers.h"
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 // From RFC 5861 section 3, a stale response may be used while revalidation is 959 // From RFC 5861 section 3, a stale response may be used while revalidation is
960 // performed in the background if 960 // performed in the background if
961 // 961 //
962 // freshness_lifetime + stale_while_revalidate > current_age 962 // freshness_lifetime + stale_while_revalidate > current_age
963 // 963 //
964 ValidationType HttpResponseHeaders::RequiresValidation( 964 ValidationType HttpResponseHeaders::RequiresValidation(
965 const Time& request_time, 965 const Time& request_time,
966 const Time& response_time, 966 const Time& response_time,
967 const Time& current_time) const { 967 const Time& current_time) const {
968 FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time); 968 FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time);
969 if (lifetimes.fresh == TimeDelta() && lifetimes.stale == TimeDelta()) 969 if (lifetimes.freshness == TimeDelta() && lifetimes.staleness == TimeDelta())
970 return VALIDATION_SYNCHRONOUS; 970 return VALIDATION_SYNCHRONOUS;
971 971
972 TimeDelta age = GetCurrentAge(request_time, response_time, current_time); 972 TimeDelta age = GetCurrentAge(request_time, response_time, current_time);
973 973
974 if (lifetimes.fresh > age) 974 if (lifetimes.freshness > age)
975 return VALIDATION_NONE; 975 return VALIDATION_NONE;
976 976
977 if (lifetimes.fresh + lifetimes.stale > age) 977 if (lifetimes.freshness + lifetimes.staleness > age)
978 return VALIDATION_ASYNCHRONOUS; 978 return VALIDATION_ASYNCHRONOUS;
979 979
980 return VALIDATION_SYNCHRONOUS; 980 return VALIDATION_SYNCHRONOUS;
981 } 981 }
982 982
983 // From RFC 2616 section 13.2.4: 983 // From RFC 2616 section 13.2.4:
984 // 984 //
985 // The max-age directive takes priority over Expires, so if max-age is present 985 // The max-age directive takes priority over Expires, so if max-age is present
986 // in a response, the calculation is simply: 986 // in a response, the calculation is simply:
987 // 987 //
988 // freshness_lifetime = max_age_value 988 // freshness_lifetime = max_age_value
989 // 989 //
990 // Otherwise, if Expires is present in the response, the calculation is: 990 // Otherwise, if Expires is present in the response, the calculation is:
991 // 991 //
992 // freshness_lifetime = expires_value - date_value 992 // freshness_lifetime = expires_value - date_value
993 // 993 //
994 // Note that neither of these calculations is vulnerable to clock skew, since 994 // Note that neither of these calculations is vulnerable to clock skew, since
995 // all of the information comes from the origin server. 995 // all of the information comes from the origin server.
996 // 996 //
997 // Also, if the response does have a Last-Modified time, the heuristic 997 // Also, if the response does have a Last-Modified time, the heuristic
998 // expiration value SHOULD be no more than some fraction of the interval since 998 // expiration value SHOULD be no more than some fraction of the interval since
999 // that time. A typical setting of this fraction might be 10%: 999 // that time. A typical setting of this fraction might be 10%:
1000 // 1000 //
1001 // freshness_lifetime = (date_value - last_modified_value) * 0.10 1001 // freshness_lifetime = (date_value - last_modified_value) * 0.10
1002 // 1002 //
1003 // If the stale-while-revalidate directive is present, then it is used to set 1003 // If the stale-while-revalidate directive is present, then it is used to set
1004 // the |stale| time, unless it overridden by another directive. 1004 // the |staleness| time, unless it overridden by another directive.
1005 // 1005 //
1006 HttpResponseHeaders::FreshnessLifetimes 1006 HttpResponseHeaders::FreshnessLifetimes
1007 HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const { 1007 HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const {
1008 FreshnessLifetimes lifetimes; 1008 FreshnessLifetimes lifetimes;
1009 // Check for headers that force a response to never be fresh. For backwards 1009 // Check for headers that force a response to never be fresh. For backwards
1010 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control: 1010 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control:
1011 // no-cache" even though RFC 2616 does not specify it. 1011 // no-cache" even though RFC 2616 does not specify it.
1012 if (HasHeaderValue("cache-control", "no-cache") || 1012 if (HasHeaderValue("cache-control", "no-cache") ||
1013 HasHeaderValue("cache-control", "no-store") || 1013 HasHeaderValue("cache-control", "no-store") ||
1014 HasHeaderValue("pragma", "no-cache") || 1014 HasHeaderValue("pragma", "no-cache") ||
1015 // Vary: * is never usable: see RFC 2616 section 13.6. 1015 // Vary: * is never usable: see RFC 2616 section 13.6.
1016 HasHeaderValue("vary", "*")) { 1016 HasHeaderValue("vary", "*")) {
1017 return lifetimes; 1017 return lifetimes;
1018 } 1018 }
1019 1019
1020 // Cache-Control directive must_revalidate overrides stale-while-revalidate. 1020 // Cache-Control directive must_revalidate overrides stale-while-revalidate.
1021 bool must_revalidate = HasHeaderValue("cache-control", "must-revalidate"); 1021 bool must_revalidate = HasHeaderValue("cache-control", "must-revalidate");
1022 1022
1023 if (must_revalidate || !GetStaleWhileRevalidateValue(&lifetimes.stale)) 1023 if (must_revalidate || !GetStaleWhileRevalidateValue(&lifetimes.staleness)) {
1024 DCHECK(lifetimes.stale == TimeDelta()); 1024 DCHECK(lifetimes.staleness == TimeDelta());
1025 }
1025 1026
1026 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the 1027 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the
1027 // Expires header after checking for max-age in GetFreshnessLifetimes. This 1028 // Expires header after checking for max-age in GetFreshnessLifetimes. This
1028 // is important since "Expires: <date in the past>" means not fresh, but 1029 // is important since "Expires: <date in the past>" means not fresh, but
1029 // it should not trump a max-age value. 1030 // it should not trump a max-age value.
1030 if (GetMaxAgeValue(&lifetimes.fresh)) 1031 if (GetMaxAgeValue(&lifetimes.freshness))
1031 return lifetimes; 1032 return lifetimes;
1032 1033
1033 // If there is no Date header, then assume that the server response was 1034 // If there is no Date header, then assume that the server response was
1034 // generated at the time when we received the response. 1035 // generated at the time when we received the response.
1035 Time date_value; 1036 Time date_value;
1036 if (!GetDateValue(&date_value)) 1037 if (!GetDateValue(&date_value))
1037 date_value = response_time; 1038 date_value = response_time;
1038 1039
1039 Time expires_value; 1040 Time expires_value;
1040 if (GetExpiresValue(&expires_value)) { 1041 if (GetExpiresValue(&expires_value)) {
1041 // The expires value can be a date in the past! 1042 // The expires value can be a date in the past!
1042 if (expires_value > date_value) { 1043 if (expires_value > date_value) {
1043 lifetimes.fresh = expires_value - date_value; 1044 lifetimes.freshness = expires_value - date_value;
1044 return lifetimes; 1045 return lifetimes;
1045 } 1046 }
1046 1047
1047 DCHECK(lifetimes.fresh == TimeDelta()); 1048 DCHECK(lifetimes.freshness == TimeDelta());
1048 return lifetimes; 1049 return lifetimes;
1049 } 1050 }
1050 1051
1051 // From RFC 2616 section 13.4: 1052 // From RFC 2616 section 13.4:
1052 // 1053 //
1053 // A response received with a status code of 200, 203, 206, 300, 301 or 410 1054 // A response received with a status code of 200, 203, 206, 300, 301 or 410
1054 // MAY be stored by a cache and used in reply to a subsequent request, 1055 // MAY be stored by a cache and used in reply to a subsequent request,
1055 // subject to the expiration mechanism, unless a cache-control directive 1056 // subject to the expiration mechanism, unless a cache-control directive
1056 // prohibits caching. 1057 // prohibits caching.
1057 // ... 1058 // ...
(...skipping 14 matching lines...) Expand all
1072 // https://datatracker.ietf.org/doc/draft-reschke-http-status-308/ is an 1073 // https://datatracker.ietf.org/doc/draft-reschke-http-status-308/ is an
1073 // experimental RFC that adds 308 permanent redirect as well, for which "any 1074 // experimental RFC that adds 308 permanent redirect as well, for which "any
1074 // future references ... SHOULD use one of the returned URIs." 1075 // future references ... SHOULD use one of the returned URIs."
1075 if ((response_code_ == 200 || response_code_ == 203 || 1076 if ((response_code_ == 200 || response_code_ == 203 ||
1076 response_code_ == 206) && !must_revalidate) { 1077 response_code_ == 206) && !must_revalidate) {
1077 // TODO(darin): Implement a smarter heuristic. 1078 // TODO(darin): Implement a smarter heuristic.
1078 Time last_modified_value; 1079 Time last_modified_value;
1079 if (GetLastModifiedValue(&last_modified_value)) { 1080 if (GetLastModifiedValue(&last_modified_value)) {
1080 // The last-modified value can be a date in the future! 1081 // The last-modified value can be a date in the future!
1081 if (last_modified_value <= date_value) { 1082 if (last_modified_value <= date_value) {
1082 lifetimes.fresh = (date_value - last_modified_value) / 10; 1083 lifetimes.freshness = (date_value - last_modified_value) / 10;
1083 return lifetimes; 1084 return lifetimes;
1084 } 1085 }
1085 } 1086 }
1086 } 1087 }
1087 1088
1088 // These responses are implicitly fresh (unless otherwise overruled): 1089 // These responses are implicitly fresh (unless otherwise overruled):
1089 if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 || 1090 if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 ||
1090 response_code_ == 410) { 1091 response_code_ == 410) {
1091 lifetimes.fresh = TimeDelta::Max(); 1092 lifetimes.freshness = TimeDelta::Max();
1092 lifetimes.stale = TimeDelta(); // It should never be stale. 1093 lifetimes.staleness = TimeDelta(); // It should never be stale.
1093 return lifetimes; 1094 return lifetimes;
1094 } 1095 }
1095 1096
1096 // Our heuristic freshness estimate for this resource is 0 seconds, in 1097 // Our heuristic freshness estimate for this resource is 0 seconds, in
1097 // accordance with common browser behaviour. However, stale-while-revalidate 1098 // accordance with common browser behaviour. However, stale-while-revalidate
1098 // may still apply. 1099 // may still apply.
1099 DCHECK(lifetimes.fresh == TimeDelta()); 1100 DCHECK(lifetimes.freshness == TimeDelta());
1100 return lifetimes; 1101 return lifetimes;
1101 } 1102 }
1102 1103
1103 // From RFC 2616 section 13.2.3: 1104 // From RFC 2616 section 13.2.3:
1104 // 1105 //
1105 // Summary of age calculation algorithm, when a cache receives a response: 1106 // Summary of age calculation algorithm, when a cache receives a response:
1106 // 1107 //
1107 // /* 1108 // /*
1108 // * age_value 1109 // * age_value
1109 // * is the value of Age: header received by the cache with 1110 // * is the value of Age: header received by the cache with
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1442 return true; 1443 return true;
1443 } 1444 }
1444 1445
1445 bool HttpResponseHeaders::IsChunkEncoded() const { 1446 bool HttpResponseHeaders::IsChunkEncoded() const {
1446 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. 1447 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies.
1447 return GetHttpVersion() >= HttpVersion(1, 1) && 1448 return GetHttpVersion() >= HttpVersion(1, 1) &&
1448 HasHeaderValue("Transfer-Encoding", "chunked"); 1449 HasHeaderValue("Transfer-Encoding", "chunked");
1449 } 1450 }
1450 1451
1451 } // namespace net 1452 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_response_headers.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698