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

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

Issue 154243006: Add GetExpirationTimes() to HttpResponseHeader. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remediate to review Created 6 years, 10 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 | Annotate | Revision Log
« 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 887 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 response_code == 303 || 898 response_code == 303 ||
899 response_code == 307); 899 response_code == 307);
900 } 900 }
901 901
902 // From RFC 2616 section 13.2.4: 902 // From RFC 2616 section 13.2.4:
903 // 903 //
904 // The calculation to determine if a response has expired is quite simple: 904 // The calculation to determine if a response has expired is quite simple:
905 // 905 //
906 // response_is_fresh = (freshness_lifetime > current_age) 906 // response_is_fresh = (freshness_lifetime > current_age)
907 // 907 //
908 // Into this equation, we substitute |current_age = now - freshness_origin|,
909 // giving:
910 //
911 // response_is_fresh = (freshness_lifetime > now - freshness_origin)
912 //
913 // response_is_fresh = (freshness_lifetime + freshness_origin > now)
914 //
915 // And we call this quantity |freshness_lifetime + freshness_origin| the
916 // freshness_expiry.
917 //
908 // Of course, there are other factors that can force a response to always be 918 // Of course, there are other factors that can force a response to always be
909 // validated or re-fetched. 919 // validated or re-fetched.
910 // 920 //
911 bool HttpResponseHeaders::RequiresValidation(const Time& request_time, 921 Time HttpResponseHeaders::GetFreshnessExpiry(Time request_time,
912 const Time& response_time, 922 Time response_time) const {
913 const Time& current_time) const { 923 TimeDelta lifetime;
914 TimeDelta lifetime = 924 bool finite_lifetime;
915 GetFreshnessLifetime(response_time); 925 GetFreshnessLifetime(response_time, &lifetime, &finite_lifetime);
916 if (lifetime == TimeDelta()) 926 if (!finite_lifetime)
917 return true; 927 return Time::Max();
928 Time origin = GetFreshnessOrigin(request_time, response_time);
929 return origin + lifetime;
930 }
918 931
919 return lifetime <= GetCurrentAge(request_time, response_time, current_time); 932 bool HttpResponseHeaders::RequiresValidation(base::Time request_time,
933 base::Time response_time,
934 base::Time current_time) const {
935 return GetFreshnessExpiry(request_time, response_time) <= current_time;
920 } 936 }
921 937
938
922 // From RFC 2616 section 13.2.4: 939 // From RFC 2616 section 13.2.4:
923 // 940 //
924 // The max-age directive takes priority over Expires, so if max-age is present 941 // The max-age directive takes priority over Expires, so if max-age is present
925 // in a response, the calculation is simply: 942 // in a response, the calculation is simply:
926 // 943 //
927 // freshness_lifetime = max_age_value 944 // freshness_lifetime = max_age_value
928 // 945 //
929 // Otherwise, if Expires is present in the response, the calculation is: 946 // Otherwise, if Expires is present in the response, the calculation is:
930 // 947 //
931 // freshness_lifetime = expires_value - date_value 948 // freshness_lifetime = expires_value - date_value
932 // 949 //
933 // Note that neither of these calculations is vulnerable to clock skew, since 950 // Note that neither of these calculations is vulnerable to clock skew, since
934 // all of the information comes from the origin server. 951 // all of the information comes from the origin server.
935 // 952 //
936 // Also, if the response does have a Last-Modified time, the heuristic 953 // Also, if the response does have a Last-Modified time, the heuristic
937 // expiration value SHOULD be no more than some fraction of the interval since 954 // expiration value SHOULD be no more than some fraction of the interval since
938 // that time. A typical setting of this fraction might be 10%: 955 // that time. A typical setting of this fraction might be 10%:
939 // 956 //
940 // freshness_lifetime = (date_value - last_modified_value) * 0.10 957 // freshness_lifetime = (date_value - last_modified_value) * 0.10
941 // 958 //
942 TimeDelta HttpResponseHeaders::GetFreshnessLifetime( 959 void HttpResponseHeaders::GetFreshnessLifetime(
943 const Time& response_time) const { 960 Time response_time,
961 TimeDelta* finite_freshness_lifetime,
962 bool* was_finite) const {
963 *finite_freshness_lifetime = TimeDelta();
964 *was_finite = true;
965
944 // Check for headers that force a response to never be fresh. For backwards 966 // Check for headers that force a response to never be fresh. For backwards
945 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control: 967 // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control:
946 // no-cache" even though RFC 2616 does not specify it. 968 // no-cache" even though RFC 2616 does not specify it.
947 if (HasHeaderValue("cache-control", "no-cache") || 969 if (HasHeaderValue("cache-control", "no-cache") ||
948 HasHeaderValue("cache-control", "no-store") || 970 HasHeaderValue("cache-control", "no-store") ||
949 HasHeaderValue("pragma", "no-cache") || 971 HasHeaderValue("pragma", "no-cache") ||
950 HasHeaderValue("vary", "*")) // see RFC 2616 section 13.6 972 HasHeaderValue("vary", "*")) // see RFC 2616 section 13.6
951 return TimeDelta(); // not fresh 973 return; // not fresh
952 974
953 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the 975 // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the
954 // Expires header after checking for max-age in GetFreshnessLifetime. This 976 // Expires header after checking for max-age in GetFreshnessLifetime. This
955 // is important since "Expires: <date in the past>" means not fresh, but 977 // is important since "Expires: <date in the past>" means not fresh, but
956 // it should not trump a max-age value. 978 // it should not trump a max-age value.
957 979
958 TimeDelta max_age_value; 980 if (GetMaxAgeValue(finite_freshness_lifetime))
959 if (GetMaxAgeValue(&max_age_value)) 981 return;
960 return max_age_value;
961 982
962 // If there is no Date header, then assume that the server response was 983 // If there is no Date header, then assume that the server response was
963 // generated at the time when we received the response. 984 // generated at the time when we received the response.
964 Time date_value; 985 Time date_value;
965 if (!GetDateValue(&date_value)) 986 if (!GetDateValue(&date_value))
966 date_value = response_time; 987 date_value = response_time;
967 988
968 Time expires_value; 989 Time expires_value;
969 if (GetExpiresValue(&expires_value)) { 990 if (GetExpiresValue(&expires_value)) {
970 // The expires value can be a date in the past! 991 // The expires value can be a date in the past!
971 if (expires_value > date_value) 992 if (expires_value > date_value)
972 return expires_value - date_value; 993 *finite_freshness_lifetime = expires_value - date_value;
973 994 return;
974 return TimeDelta(); // not fresh
975 } 995 }
976 996
977 // From RFC 2616 section 13.4: 997 // From RFC 2616 section 13.4:
978 // 998 //
979 // A response received with a status code of 200, 203, 206, 300, 301 or 410 999 // A response received with a status code of 200, 203, 206, 300, 301 or 410
980 // MAY be stored by a cache and used in reply to a subsequent request, 1000 // MAY be stored by a cache and used in reply to a subsequent request,
981 // subject to the expiration mechanism, unless a cache-control directive 1001 // subject to the expiration mechanism, unless a cache-control directive
982 // prohibits caching. 1002 // prohibits caching.
983 // ... 1003 // ...
984 // A response received with any other status code (e.g. status codes 302 1004 // A response received with any other status code (e.g. status codes 302
(...skipping 11 matching lines...) Expand all
996 // the cached response is stale.) 1016 // the cached response is stale.)
997 // 1017 //
998 if ((response_code_ == 200 || response_code_ == 203 || 1018 if ((response_code_ == 200 || response_code_ == 203 ||
999 response_code_ == 206) && 1019 response_code_ == 206) &&
1000 !HasHeaderValue("cache-control", "must-revalidate")) { 1020 !HasHeaderValue("cache-control", "must-revalidate")) {
1001 // TODO(darin): Implement a smarter heuristic. 1021 // TODO(darin): Implement a smarter heuristic.
1002 Time last_modified_value; 1022 Time last_modified_value;
1003 if (GetLastModifiedValue(&last_modified_value)) { 1023 if (GetLastModifiedValue(&last_modified_value)) {
1004 // The last-modified value can be a date in the past! 1024 // The last-modified value can be a date in the past!
1005 if (last_modified_value <= date_value) 1025 if (last_modified_value <= date_value)
1006 return (date_value - last_modified_value) / 10; 1026 *finite_freshness_lifetime = (date_value - last_modified_value) / 10;
1027 return;
1007 } 1028 }
1008 } 1029 }
1009 1030
1010 // These responses are implicitly fresh (unless otherwise overruled): 1031 // These responses are implicitly fresh (unless otherwise overruled):
1011 if (response_code_ == 300 || response_code_ == 301 || response_code_ == 410) 1032 if (response_code_ == 300 || response_code_ == 301 || response_code_ == 410) {
1012 return TimeDelta::FromMicroseconds(kint64max); 1033 *was_finite = false;
gavinp 2014/02/13 17:37:59 This line is an abstraction violation that skates
1034 return;
1035 }
1013 1036
1014 return TimeDelta(); // not fresh 1037 return; // not fresh.
1015 } 1038 }
1016 1039
1017 // From RFC 2616 section 13.2.3: 1040 // From RFC 2616 section 13.2.3:
1018 // 1041 //
1019 // Summary of age calculation algorithm, when a cache receives a response: 1042 // Summary of age calculation algorithm, when a cache receives a response:
1020 // 1043 //
1021 // /* 1044 // /*
1022 // * age_value 1045 // * age_value
1023 // * is the value of Age: header received by the cache with 1046 // * is the value of Age: header received by the cache with
1024 // * this response. 1047 // * this response.
1025 // * date_value 1048 // * date_value
1026 // * is the value of the origin server's Date: header 1049 // * is the value of the origin server's Date: header
1027 // * request_time 1050 // * request_time
1028 // * is the (local) time when the cache made the request 1051 // * is the (local) time when the cache made the request
1029 // * that resulted in this cached response 1052 // * that resulted in this cached response
1030 // * response_time 1053 // * response_time
1031 // * is the (local) time when the cache received the 1054 // * is the (local) time when the cache received the
1032 // * response 1055 // * response
1033 // * now 1056 // * now
1034 // * is the current (local) time 1057 // * is the current (local) time
1035 // */ 1058 // */
1036 // apparent_age = max(0, response_time - date_value); 1059 // apparent_age = max(0, response_time - date_value);
1037 // corrected_received_age = max(apparent_age, age_value); 1060 // corrected_received_age = max(apparent_age, age_value);
1038 // response_delay = response_time - request_time; 1061 // response_delay = response_time - request_time;
1039 // corrected_initial_age = corrected_received_age + response_delay; 1062 // corrected_initial_age = corrected_received_age + response_delay;
1040 // resident_time = now - response_time; 1063 // resident_time = now - response_time;
1041 // current_age = corrected_initial_age + resident_time; 1064 // current_age = corrected_initial_age + resident_time;
1042 // 1065 //
1043 TimeDelta HttpResponseHeaders::GetCurrentAge(const Time& request_time, 1066 // From this, we can derive the freshness origin, the time at which the
1044 const Time& response_time, 1067 // current_age = 0 and solve for now (aka freshness_origin):
1045 const Time& current_time) const { 1068 //
1069 // corrected_initial_age + resident_time = 0
1070 // corrected_initial_age + freshness_origin - response_time = 0
1071 // freshness_origin = response_time - corrected_initial_age
1072 //
1073 Time HttpResponseHeaders::GetFreshnessOrigin(Time request_time,
1074 Time response_time) const {
1046 // If there is no Date header, then assume that the server response was 1075 // If there is no Date header, then assume that the server response was
1047 // generated at the time when we received the response. 1076 // generated at the time when we received the response.
1048 Time date_value; 1077 Time date_value;
1049 if (!GetDateValue(&date_value)) 1078 if (!GetDateValue(&date_value))
1050 date_value = response_time; 1079 date_value = response_time;
1051 1080
1052 // If there is no Age header, then assume age is zero. GetAgeValue does not 1081 // If there is no Age header, then assume age is zero. GetAgeValue does not
1053 // modify its out param if the value does not exist. 1082 // modify its out param if the value does not exist.
1054 TimeDelta age_value; 1083 TimeDelta age_value;
1055 GetAgeValue(&age_value); 1084 GetAgeValue(&age_value);
1056 1085
1057 TimeDelta apparent_age = std::max(TimeDelta(), response_time - date_value); 1086 TimeDelta apparent_age = std::max(TimeDelta(), response_time - date_value);
1058 TimeDelta corrected_received_age = std::max(apparent_age, age_value); 1087 TimeDelta corrected_received_age = std::max(apparent_age, age_value);
1059 TimeDelta response_delay = response_time - request_time; 1088 TimeDelta response_delay = response_time - request_time;
1060 TimeDelta corrected_initial_age = corrected_received_age + response_delay; 1089 TimeDelta corrected_initial_age = corrected_received_age + response_delay;
1061 TimeDelta resident_time = current_time - response_time;
1062 TimeDelta current_age = corrected_initial_age + resident_time;
1063 1090
1064 return current_age; 1091 return response_time - corrected_initial_age;
1065 } 1092 }
1066 1093
1067 bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const { 1094 bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const {
1068 std::string name = "cache-control"; 1095 std::string name = "cache-control";
1069 std::string value; 1096 std::string value;
1070 1097
1071 const char kMaxAgePrefix[] = "max-age="; 1098 const char kMaxAgePrefix[] = "max-age=";
1072 const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1; 1099 const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1;
1073 1100
1074 void* iter = NULL; 1101 void* iter = NULL;
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 1442
1416 // Next, look for 'bypass'. 1443 // Next, look for 'bypass'.
1417 if (GetChromeProxyBypassDuration("bypass=", &proxy_info->bypass_duration)) 1444 if (GetChromeProxyBypassDuration("bypass=", &proxy_info->bypass_duration))
1418 return true; 1445 return true;
1419 1446
1420 return false; 1447 return false;
1421 } 1448 }
1422 #endif // defined(SPDY_PROXY_AUTH_ORIGIN) 1449 #endif // defined(SPDY_PROXY_AUTH_ORIGIN)
1423 1450
1424 } // namespace net 1451 } // 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