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

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

Issue 2763393002: Remove stale-while-revalidate from net (Closed)
Patch Set: fixes Created 3 years, 9 months 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') | net/http/http_response_headers_unittest.cc » ('j') | 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 899 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 910
911 // From RFC 2616 section 13.2.4: 911 // From RFC 2616 section 13.2.4:
912 // 912 //
913 // The calculation to determine if a response has expired is quite simple: 913 // The calculation to determine if a response has expired is quite simple:
914 // 914 //
915 // response_is_fresh = (freshness_lifetime > current_age) 915 // response_is_fresh = (freshness_lifetime > current_age)
916 // 916 //
917 // Of course, there are other factors that can force a response to always be 917 // Of course, there are other factors that can force a response to always be
918 // validated or re-fetched. 918 // validated or re-fetched.
919 // 919 //
920 // From RFC 5861 section 3, a stale response may be used while revalidation is 920 bool HttpResponseHeaders::RequiresValidation(const Time& request_time,
921 // performed in the background if 921 const Time& response_time,
922 // 922 const Time& current_time) const {
923 // freshness_lifetime + stale_while_revalidate > current_age
924 //
925 ValidationType HttpResponseHeaders::RequiresValidation(
926 const Time& request_time,
927 const Time& response_time,
928 const Time& current_time) const {
929 FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time); 923 FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time);
930 if (lifetimes.freshness.is_zero() && lifetimes.staleness.is_zero()) 924 if (lifetimes.freshness.is_zero())
931 return VALIDATION_SYNCHRONOUS; 925 return true;
932 926 return lifetimes.freshness <=
933 TimeDelta age = GetCurrentAge(request_time, response_time, current_time); 927 GetCurrentAge(request_time, response_time, current_time);
934
935 if (lifetimes.freshness > age)
936 return VALIDATION_NONE;
937
938 if (lifetimes.freshness + lifetimes.staleness > age)
939 return VALIDATION_ASYNCHRONOUS;
940
941 return VALIDATION_SYNCHRONOUS;
942 } 928 }
943 929
944 // From RFC 2616 section 13.2.4: 930 // From RFC 2616 section 13.2.4:
945 // 931 //
946 // The max-age directive takes priority over Expires, so if max-age is present 932 // The max-age directive takes priority over Expires, so if max-age is present
947 // in a response, the calculation is simply: 933 // in a response, the calculation is simply:
948 // 934 //
949 // freshness_lifetime = max_age_value 935 // freshness_lifetime = max_age_value
950 // 936 //
951 // Otherwise, if Expires is present in the response, the calculation is: 937 // Otherwise, if Expires is present in the response, the calculation is:
952 // 938 //
953 // freshness_lifetime = expires_value - date_value 939 // freshness_lifetime = expires_value - date_value
954 // 940 //
955 // Note that neither of these calculations is vulnerable to clock skew, since 941 // Note that neither of these calculations is vulnerable to clock skew, since
956 // all of the information comes from the origin server. 942 // all of the information comes from the origin server.
957 // 943 //
958 // Also, if the response does have a Last-Modified time, the heuristic 944 // Also, if the response does have a Last-Modified time, the heuristic
959 // expiration value SHOULD be no more than some fraction of the interval since 945 // expiration value SHOULD be no more than some fraction of the interval since
960 // that time. A typical setting of this fraction might be 10%: 946 // that time. A typical setting of this fraction might be 10%:
961 // 947 //
962 // freshness_lifetime = (date_value - last_modified_value) * 0.10 948 // freshness_lifetime = (date_value - last_modified_value) * 0.10
963 // 949 //
964 // If the stale-while-revalidate directive is present, then it is used to set
965 // the |staleness| time, unless it overridden by another directive.
966 //
967 HttpResponseHeaders::FreshnessLifetimes 950 HttpResponseHeaders::FreshnessLifetimes
968 HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const { 951 HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const {
969 FreshnessLifetimes lifetimes; 952 FreshnessLifetimes lifetimes;
970 // Check for headers that force a response to never be fresh. For backwards 953 // Check for headers that force a response to never be fresh. For backwards
971 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control: 954 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control:
972 // no-cache" even though RFC 2616 does not specify it. 955 // no-cache" even though RFC 2616 does not specify it.
973 if (HasHeaderValue("cache-control", "no-cache") || 956 if (HasHeaderValue("cache-control", "no-cache") ||
974 HasHeaderValue("cache-control", "no-store") || 957 HasHeaderValue("cache-control", "no-store") ||
975 HasHeaderValue("pragma", "no-cache") || 958 HasHeaderValue("pragma", "no-cache") ||
976 // Vary: * is never usable: see RFC 2616 section 13.6. 959 // Vary: * is never usable: see RFC 2616 section 13.6.
977 HasHeaderValue("vary", "*")) { 960 HasHeaderValue("vary", "*")) {
978 return lifetimes; 961 return lifetimes;
979 } 962 }
980 963
981 // Cache-Control directive must_revalidate overrides stale-while-revalidate.
982 bool must_revalidate = HasHeaderValue("cache-control", "must-revalidate");
983
984 if (must_revalidate || !GetStaleWhileRevalidateValue(&lifetimes.staleness)) {
985 DCHECK_EQ(TimeDelta(), lifetimes.staleness);
986 }
987
988 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the 964 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the
989 // Expires header after checking for max-age in GetFreshnessLifetimes. This 965 // Expires header after checking for max-age in GetFreshnessLifetimes. This
990 // is important since "Expires: <date in the past>" means not fresh, but 966 // is important since "Expires: <date in the past>" means not fresh, but
991 // it should not trump a max-age value. 967 // it should not trump a max-age value.
992 if (GetMaxAgeValue(&lifetimes.freshness)) 968 if (GetMaxAgeValue(&lifetimes.freshness))
993 return lifetimes; 969 return lifetimes;
994 970
995 // If there is no Date header, then assume that the server response was 971 // If there is no Date header, then assume that the server response was
996 // generated at the time when we received the response. 972 // generated at the time when we received the response.
997 Time date_value; 973 Time date_value;
(...skipping 30 matching lines...) Expand all
1028 // a cache, that cache MUST NOT use the entry after it becomes stale to 1004 // a cache, that cache MUST NOT use the entry after it becomes stale to
1029 // respond to a subsequent request without first revalidating it with the 1005 // respond to a subsequent request without first revalidating it with the
1030 // origin server. (I.e., the cache MUST do an end-to-end revalidation every 1006 // origin server. (I.e., the cache MUST do an end-to-end revalidation every
1031 // time, if, based solely on the origin server's Expires or max-age value, 1007 // time, if, based solely on the origin server's Expires or max-age value,
1032 // the cached response is stale.) 1008 // the cached response is stale.)
1033 // 1009 //
1034 // https://datatracker.ietf.org/doc/draft-reschke-http-status-308/ is an 1010 // https://datatracker.ietf.org/doc/draft-reschke-http-status-308/ is an
1035 // experimental RFC that adds 308 permanent redirect as well, for which "any 1011 // experimental RFC that adds 308 permanent redirect as well, for which "any
1036 // future references ... SHOULD use one of the returned URIs." 1012 // future references ... SHOULD use one of the returned URIs."
1037 if ((response_code_ == 200 || response_code_ == 203 || 1013 if ((response_code_ == 200 || response_code_ == 203 ||
1038 response_code_ == 206) && !must_revalidate) { 1014 response_code_ == 206) &&
1015 !HasHeaderValue("cache-control", "must-revalidate")) {
1039 // TODO(darin): Implement a smarter heuristic. 1016 // TODO(darin): Implement a smarter heuristic.
1040 Time last_modified_value; 1017 Time last_modified_value;
1041 if (GetLastModifiedValue(&last_modified_value)) { 1018 if (GetLastModifiedValue(&last_modified_value)) {
1042 // The last-modified value can be a date in the future! 1019 // The last-modified value can be a date in the future!
1043 if (last_modified_value <= date_value) { 1020 if (last_modified_value <= date_value) {
1044 lifetimes.freshness = (date_value - last_modified_value) / 10; 1021 lifetimes.freshness = (date_value - last_modified_value) / 10;
1045 return lifetimes; 1022 return lifetimes;
1046 } 1023 }
1047 } 1024 }
1048 } 1025 }
1049 1026
1050 // These responses are implicitly fresh (unless otherwise overruled): 1027 // These responses are implicitly fresh (unless otherwise overruled):
1051 if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 || 1028 if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 ||
1052 response_code_ == 410) { 1029 response_code_ == 410) {
1053 lifetimes.freshness = TimeDelta::Max(); 1030 lifetimes.freshness = TimeDelta::Max();
1054 lifetimes.staleness = TimeDelta(); // It should never be stale.
1055 return lifetimes; 1031 return lifetimes;
1056 } 1032 }
1057 1033
1058 // Our heuristic freshness estimate for this resource is 0 seconds, in 1034 // Our heuristic freshness estimate for this resource is 0 seconds, in
1059 // accordance with common browser behaviour. However, stale-while-revalidate 1035 // accordance with common browser behaviour.
1060 // may still apply.
1061 DCHECK_EQ(TimeDelta(), lifetimes.freshness); 1036 DCHECK_EQ(TimeDelta(), lifetimes.freshness);
1062 return lifetimes; 1037 return lifetimes;
1063 } 1038 }
1064 1039
1065 // From RFC 7234 section 4.2.3: 1040 // From RFC 7234 section 4.2.3:
1066 // 1041 //
1067 // The following data is used for the age calculation: 1042 // The following data is used for the age calculation:
1068 // 1043 //
1069 // age_value 1044 // age_value
1070 // 1045 //
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 } 1136 }
1162 1137
1163 bool HttpResponseHeaders::GetLastModifiedValue(Time* result) const { 1138 bool HttpResponseHeaders::GetLastModifiedValue(Time* result) const {
1164 return GetTimeValuedHeader("Last-Modified", result); 1139 return GetTimeValuedHeader("Last-Modified", result);
1165 } 1140 }
1166 1141
1167 bool HttpResponseHeaders::GetExpiresValue(Time* result) const { 1142 bool HttpResponseHeaders::GetExpiresValue(Time* result) const {
1168 return GetTimeValuedHeader("Expires", result); 1143 return GetTimeValuedHeader("Expires", result);
1169 } 1144 }
1170 1145
1171 bool HttpResponseHeaders::GetStaleWhileRevalidateValue(
1172 TimeDelta* result) const {
1173 return GetCacheControlDirective("stale-while-revalidate", result);
1174 }
1175
1176 bool HttpResponseHeaders::GetTimeValuedHeader(const std::string& name, 1146 bool HttpResponseHeaders::GetTimeValuedHeader(const std::string& name,
1177 Time* result) const { 1147 Time* result) const {
1178 std::string value; 1148 std::string value;
1179 if (!EnumerateHeader(nullptr, name, &value)) 1149 if (!EnumerateHeader(nullptr, name, &value))
1180 return false; 1150 return false;
1181 1151
1182 // When parsing HTTP dates it's beneficial to default to GMT because: 1152 // When parsing HTTP dates it's beneficial to default to GMT because:
1183 // 1. RFC2616 3.3.1 says times should always be specified in GMT 1153 // 1. RFC2616 3.3.1 says times should always be specified in GMT
1184 // 2. Only counter-example incorrectly appended "UTC" (crbug.com/153759) 1154 // 2. Only counter-example incorrectly appended "UTC" (crbug.com/153759)
1185 // 3. When adjusting cookie expiration times for clock skew 1155 // 3. When adjusting cookie expiration times for clock skew
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 return true; 1316 return true;
1347 } 1317 }
1348 1318
1349 bool HttpResponseHeaders::IsChunkEncoded() const { 1319 bool HttpResponseHeaders::IsChunkEncoded() const {
1350 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. 1320 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies.
1351 return GetHttpVersion() >= HttpVersion(1, 1) && 1321 return GetHttpVersion() >= HttpVersion(1, 1) &&
1352 HasHeaderValue("Transfer-Encoding", "chunked"); 1322 HasHeaderValue("Transfer-Encoding", "chunked");
1353 } 1323 }
1354 1324
1355 } // namespace net 1325 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_response_headers.h ('k') | net/http/http_response_headers_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698