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

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: Make DCHECK_EQ work for TimeDelta objects. Created 6 years, 2 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
« base/time/time_logging.cc ('K') | « 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"
11 11
12 #include <algorithm> 12 #include <algorithm>
13 13
14 #include "base/format_macros.h" 14 #include "base/format_macros.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/pickle.h" 17 #include "base/pickle.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_piece.h" 19 #include "base/strings/string_piece.h"
20 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h" 21 #include "base/strings/stringprintf.h"
22 #include "base/time/time.h" 22 #include "base/time/time.h"
23 #include "base/time/time_logging.h"
mmenke 2014/10/21 14:22:00 I wonder about requiring this include - I don't th
Adam Rice 2014/10/23 01:13:02 True. I got rid of the separate include file.
23 #include "base/values.h" 24 #include "base/values.h"
24 #include "net/base/escape.h" 25 #include "net/base/escape.h"
25 #include "net/http/http_byte_range.h" 26 #include "net/http/http_byte_range.h"
26 #include "net/http/http_log_util.h" 27 #include "net/http/http_log_util.h"
27 #include "net/http/http_util.h" 28 #include "net/http/http_util.h"
28 29
29 using base::StringPiece; 30 using base::StringPiece;
30 using base::Time; 31 using base::Time;
31 using base::TimeDelta; 32 using base::TimeDelta;
32 33
(...skipping 926 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 960 // From RFC 5861 section 3, a stale response may be used while revalidation is
960 // performed in the background if 961 // performed in the background if
961 // 962 //
962 // freshness_lifetime + stale_while_revalidate > current_age 963 // freshness_lifetime + stale_while_revalidate > current_age
963 // 964 //
964 ValidationType HttpResponseHeaders::RequiresValidation( 965 ValidationType HttpResponseHeaders::RequiresValidation(
965 const Time& request_time, 966 const Time& request_time,
966 const Time& response_time, 967 const Time& response_time,
967 const Time& current_time) const { 968 const Time& current_time) const {
968 FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time); 969 FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time);
969 if (lifetimes.fresh == TimeDelta() && lifetimes.stale == TimeDelta()) 970 if (lifetimes.freshness == TimeDelta() && lifetimes.staleness == TimeDelta())
970 return VALIDATION_SYNCHRONOUS; 971 return VALIDATION_SYNCHRONOUS;
971 972
972 TimeDelta age = GetCurrentAge(request_time, response_time, current_time); 973 TimeDelta age = GetCurrentAge(request_time, response_time, current_time);
973 974
974 if (lifetimes.fresh > age) 975 if (lifetimes.freshness > age)
975 return VALIDATION_NONE; 976 return VALIDATION_NONE;
976 977
977 if (lifetimes.fresh + lifetimes.stale > age) 978 if (lifetimes.freshness + lifetimes.staleness > age)
978 return VALIDATION_ASYNCHRONOUS; 979 return VALIDATION_ASYNCHRONOUS;
979 980
980 return VALIDATION_SYNCHRONOUS; 981 return VALIDATION_SYNCHRONOUS;
981 } 982 }
982 983
983 // From RFC 2616 section 13.2.4: 984 // From RFC 2616 section 13.2.4:
984 // 985 //
985 // The max-age directive takes priority over Expires, so if max-age is present 986 // The max-age directive takes priority over Expires, so if max-age is present
986 // in a response, the calculation is simply: 987 // in a response, the calculation is simply:
987 // 988 //
988 // freshness_lifetime = max_age_value 989 // freshness_lifetime = max_age_value
989 // 990 //
990 // Otherwise, if Expires is present in the response, the calculation is: 991 // Otherwise, if Expires is present in the response, the calculation is:
991 // 992 //
992 // freshness_lifetime = expires_value - date_value 993 // freshness_lifetime = expires_value - date_value
993 // 994 //
994 // Note that neither of these calculations is vulnerable to clock skew, since 995 // Note that neither of these calculations is vulnerable to clock skew, since
995 // all of the information comes from the origin server. 996 // all of the information comes from the origin server.
996 // 997 //
997 // Also, if the response does have a Last-Modified time, the heuristic 998 // 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 999 // 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%: 1000 // that time. A typical setting of this fraction might be 10%:
1000 // 1001 //
1001 // freshness_lifetime = (date_value - last_modified_value) * 0.10 1002 // freshness_lifetime = (date_value - last_modified_value) * 0.10
1002 // 1003 //
1003 // If the stale-while-revalidate directive is present, then it is used to set 1004 // If the stale-while-revalidate directive is present, then it is used to set
1004 // the |stale| time, unless it overridden by another directive. 1005 // the |staleness| time, unless it overridden by another directive.
1005 // 1006 //
1006 HttpResponseHeaders::FreshnessLifetimes 1007 HttpResponseHeaders::FreshnessLifetimes
1007 HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const { 1008 HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const {
1008 FreshnessLifetimes lifetimes; 1009 FreshnessLifetimes lifetimes;
1009 // Check for headers that force a response to never be fresh. For backwards 1010 // 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: 1011 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control:
1011 // no-cache" even though RFC 2616 does not specify it. 1012 // no-cache" even though RFC 2616 does not specify it.
1012 if (HasHeaderValue("cache-control", "no-cache") || 1013 if (HasHeaderValue("cache-control", "no-cache") ||
1013 HasHeaderValue("cache-control", "no-store") || 1014 HasHeaderValue("cache-control", "no-store") ||
1014 HasHeaderValue("pragma", "no-cache") || 1015 HasHeaderValue("pragma", "no-cache") ||
1015 // Vary: * is never usable: see RFC 2616 section 13.6. 1016 // Vary: * is never usable: see RFC 2616 section 13.6.
1016 HasHeaderValue("vary", "*")) { 1017 HasHeaderValue("vary", "*")) {
1017 return lifetimes; 1018 return lifetimes;
1018 } 1019 }
1019 1020
1020 // Cache-Control directive must_revalidate overrides stale-while-revalidate. 1021 // Cache-Control directive must_revalidate overrides stale-while-revalidate.
1021 bool must_revalidate = HasHeaderValue("cache-control", "must-revalidate"); 1022 bool must_revalidate = HasHeaderValue("cache-control", "must-revalidate");
1022 1023
1023 if (must_revalidate || !GetStaleWhileRevalidateValue(&lifetimes.stale)) 1024 if (must_revalidate || !GetStaleWhileRevalidateValue(&lifetimes.staleness)) {
1024 DCHECK(lifetimes.stale == TimeDelta()); 1025 DCHECK_EQ(TimeDelta(), lifetimes.staleness);
1026 }
1025 1027
1026 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the 1028 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the
1027 // Expires header after checking for max-age in GetFreshnessLifetimes. This 1029 // Expires header after checking for max-age in GetFreshnessLifetimes. This
1028 // is important since "Expires: <date in the past>" means not fresh, but 1030 // is important since "Expires: <date in the past>" means not fresh, but
1029 // it should not trump a max-age value. 1031 // it should not trump a max-age value.
1030 if (GetMaxAgeValue(&lifetimes.fresh)) 1032 if (GetMaxAgeValue(&lifetimes.freshness))
1031 return lifetimes; 1033 return lifetimes;
1032 1034
1033 // If there is no Date header, then assume that the server response was 1035 // If there is no Date header, then assume that the server response was
1034 // generated at the time when we received the response. 1036 // generated at the time when we received the response.
1035 Time date_value; 1037 Time date_value;
1036 if (!GetDateValue(&date_value)) 1038 if (!GetDateValue(&date_value))
1037 date_value = response_time; 1039 date_value = response_time;
1038 1040
1039 Time expires_value; 1041 Time expires_value;
1040 if (GetExpiresValue(&expires_value)) { 1042 if (GetExpiresValue(&expires_value)) {
1041 // The expires value can be a date in the past! 1043 // The expires value can be a date in the past!
1042 if (expires_value > date_value) { 1044 if (expires_value > date_value) {
1043 lifetimes.fresh = expires_value - date_value; 1045 lifetimes.freshness = expires_value - date_value;
1044 return lifetimes; 1046 return lifetimes;
1045 } 1047 }
1046 1048
1047 DCHECK(lifetimes.fresh == TimeDelta()); 1049 DCHECK_EQ(TimeDelta(), lifetimes.freshness);
1048 return lifetimes; 1050 return lifetimes;
1049 } 1051 }
1050 1052
1051 // From RFC 2616 section 13.4: 1053 // From RFC 2616 section 13.4:
1052 // 1054 //
1053 // A response received with a status code of 200, 203, 206, 300, 301 or 410 1055 // 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, 1056 // 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 1057 // subject to the expiration mechanism, unless a cache-control directive
1056 // prohibits caching. 1058 // prohibits caching.
1057 // ... 1059 // ...
(...skipping 14 matching lines...) Expand all
1072 // https://datatracker.ietf.org/doc/draft-reschke-http-status-308/ is an 1074 // 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 1075 // experimental RFC that adds 308 permanent redirect as well, for which "any
1074 // future references ... SHOULD use one of the returned URIs." 1076 // future references ... SHOULD use one of the returned URIs."
1075 if ((response_code_ == 200 || response_code_ == 203 || 1077 if ((response_code_ == 200 || response_code_ == 203 ||
1076 response_code_ == 206) && !must_revalidate) { 1078 response_code_ == 206) && !must_revalidate) {
1077 // TODO(darin): Implement a smarter heuristic. 1079 // TODO(darin): Implement a smarter heuristic.
1078 Time last_modified_value; 1080 Time last_modified_value;
1079 if (GetLastModifiedValue(&last_modified_value)) { 1081 if (GetLastModifiedValue(&last_modified_value)) {
1080 // The last-modified value can be a date in the future! 1082 // The last-modified value can be a date in the future!
1081 if (last_modified_value <= date_value) { 1083 if (last_modified_value <= date_value) {
1082 lifetimes.fresh = (date_value - last_modified_value) / 10; 1084 lifetimes.freshness = (date_value - last_modified_value) / 10;
1083 return lifetimes; 1085 return lifetimes;
1084 } 1086 }
1085 } 1087 }
1086 } 1088 }
1087 1089
1088 // These responses are implicitly fresh (unless otherwise overruled): 1090 // These responses are implicitly fresh (unless otherwise overruled):
1089 if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 || 1091 if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 ||
1090 response_code_ == 410) { 1092 response_code_ == 410) {
1091 lifetimes.fresh = TimeDelta::Max(); 1093 lifetimes.freshness = TimeDelta::Max();
1092 lifetimes.stale = TimeDelta(); // It should never be stale. 1094 lifetimes.staleness = TimeDelta(); // It should never be stale.
1093 return lifetimes; 1095 return lifetimes;
1094 } 1096 }
1095 1097
1096 // Our heuristic freshness estimate for this resource is 0 seconds, in 1098 // Our heuristic freshness estimate for this resource is 0 seconds, in
1097 // accordance with common browser behaviour. However, stale-while-revalidate 1099 // accordance with common browser behaviour. However, stale-while-revalidate
1098 // may still apply. 1100 // may still apply.
1099 DCHECK(lifetimes.fresh == TimeDelta()); 1101 DCHECK_EQ(TimeDelta(), lifetimes.freshness);
1100 return lifetimes; 1102 return lifetimes;
1101 } 1103 }
1102 1104
1103 // From RFC 2616 section 13.2.3: 1105 // From RFC 2616 section 13.2.3:
1104 // 1106 //
1105 // Summary of age calculation algorithm, when a cache receives a response: 1107 // Summary of age calculation algorithm, when a cache receives a response:
1106 // 1108 //
1107 // /* 1109 // /*
1108 // * age_value 1110 // * age_value
1109 // * is the value of Age: header received by the cache with 1111 // * 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; 1444 return true;
1443 } 1445 }
1444 1446
1445 bool HttpResponseHeaders::IsChunkEncoded() const { 1447 bool HttpResponseHeaders::IsChunkEncoded() const {
1446 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. 1448 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies.
1447 return GetHttpVersion() >= HttpVersion(1, 1) && 1449 return GetHttpVersion() >= HttpVersion(1, 1) &&
1448 HasHeaderValue("Transfer-Encoding", "chunked"); 1450 HasHeaderValue("Transfer-Encoding", "chunked");
1449 } 1451 }
1450 1452
1451 } // namespace net 1453 } // namespace net
OLDNEW
« base/time/time_logging.cc ('K') | « net/http/http_response_headers.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698