OLD | NEW |
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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 // this list: | 91 // this list: |
92 const char* const kNonUpdatedHeaderPrefixes[] = { | 92 const char* const kNonUpdatedHeaderPrefixes[] = { |
93 "content-", | 93 "content-", |
94 "x-content-", | 94 "x-content-", |
95 "x-webkit-" | 95 "x-webkit-" |
96 }; | 96 }; |
97 | 97 |
98 bool ShouldUpdateHeader(const std::string::const_iterator& name_begin, | 98 bool ShouldUpdateHeader(const std::string::const_iterator& name_begin, |
99 const std::string::const_iterator& name_end) { | 99 const std::string::const_iterator& name_end) { |
100 for (size_t i = 0; i < arraysize(kNonUpdatedHeaders); ++i) { | 100 for (size_t i = 0; i < arraysize(kNonUpdatedHeaders); ++i) { |
101 if (LowerCaseEqualsASCII(name_begin, name_end, kNonUpdatedHeaders[i])) | 101 if (base::LowerCaseEqualsASCII(name_begin, name_end, |
| 102 kNonUpdatedHeaders[i])) |
102 return false; | 103 return false; |
103 } | 104 } |
104 for (size_t i = 0; i < arraysize(kNonUpdatedHeaderPrefixes); ++i) { | 105 for (size_t i = 0; i < arraysize(kNonUpdatedHeaderPrefixes); ++i) { |
105 if (StartsWithASCII(std::string(name_begin, name_end), | 106 if (StartsWithASCII(std::string(name_begin, name_end), |
106 kNonUpdatedHeaderPrefixes[i], false)) | 107 kNonUpdatedHeaderPrefixes[i], false)) |
107 return false; | 108 return false; |
108 } | 109 } |
109 return true; | 110 return true; |
110 } | 111 } |
111 | 112 |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 // static | 626 // static |
626 HttpVersion HttpResponseHeaders::ParseVersion( | 627 HttpVersion HttpResponseHeaders::ParseVersion( |
627 std::string::const_iterator line_begin, | 628 std::string::const_iterator line_begin, |
628 std::string::const_iterator line_end) { | 629 std::string::const_iterator line_end) { |
629 std::string::const_iterator p = line_begin; | 630 std::string::const_iterator p = line_begin; |
630 | 631 |
631 // RFC2616 sec 3.1: HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT | 632 // RFC2616 sec 3.1: HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT |
632 // TODO: (1*DIGIT apparently means one or more digits, but we only handle 1). | 633 // TODO: (1*DIGIT apparently means one or more digits, but we only handle 1). |
633 // TODO: handle leading zeros, which is allowed by the rfc1616 sec 3.1. | 634 // TODO: handle leading zeros, which is allowed by the rfc1616 sec 3.1. |
634 | 635 |
635 if ((line_end - p < 4) || !LowerCaseEqualsASCII(p, p + 4, "http")) { | 636 if ((line_end - p < 4) || !base::LowerCaseEqualsASCII(p, p + 4, "http")) { |
636 DVLOG(1) << "missing status line"; | 637 DVLOG(1) << "missing status line"; |
637 return HttpVersion(); | 638 return HttpVersion(); |
638 } | 639 } |
639 | 640 |
640 p += 4; | 641 p += 4; |
641 | 642 |
642 if (p >= line_end || *p != '/') { | 643 if (p >= line_end || *p != '/') { |
643 DVLOG(1) << "missing version"; | 644 DVLOG(1) << "missing version"; |
644 return HttpVersion(); | 645 return HttpVersion(); |
645 } | 646 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 bool HttpResponseHeaders::GetCacheControlDirective(const StringPiece& directive, | 757 bool HttpResponseHeaders::GetCacheControlDirective(const StringPiece& directive, |
757 TimeDelta* result) const { | 758 TimeDelta* result) const { |
758 StringPiece name("cache-control"); | 759 StringPiece name("cache-control"); |
759 std::string value; | 760 std::string value; |
760 | 761 |
761 size_t directive_size = directive.size(); | 762 size_t directive_size = directive.size(); |
762 | 763 |
763 void* iter = NULL; | 764 void* iter = NULL; |
764 while (EnumerateHeader(&iter, name, &value)) { | 765 while (EnumerateHeader(&iter, name, &value)) { |
765 if (value.size() > directive_size + 1 && | 766 if (value.size() > directive_size + 1 && |
766 LowerCaseEqualsASCII(value.begin(), | 767 base::LowerCaseEqualsASCII(value.begin(), |
767 value.begin() + directive_size, | 768 value.begin() + directive_size, |
768 directive.begin()) && | 769 directive.begin()) && |
769 value[directive_size] == '=') { | 770 value[directive_size] == '=') { |
770 int64 seconds; | 771 int64 seconds; |
771 base::StringToInt64( | 772 base::StringToInt64( |
772 StringPiece(value.begin() + directive_size + 1, value.end()), | 773 StringPiece(value.begin() + directive_size + 1, value.end()), |
773 &seconds); | 774 &seconds); |
774 *result = TimeDelta::FromSeconds(seconds); | 775 *result = TimeDelta::FromSeconds(seconds); |
775 return true; | 776 return true; |
776 } | 777 } |
777 } | 778 } |
778 | 779 |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 // meaningful when we don't know that this response was from a proxy, but | 1178 // meaningful when we don't know that this response was from a proxy, but |
1178 // Mozilla also does this, so we'll do the same. | 1179 // Mozilla also does this, so we'll do the same. |
1179 std::string connection_val; | 1180 std::string connection_val; |
1180 if (!EnumerateHeader(NULL, "connection", &connection_val)) | 1181 if (!EnumerateHeader(NULL, "connection", &connection_val)) |
1181 EnumerateHeader(NULL, "proxy-connection", &connection_val); | 1182 EnumerateHeader(NULL, "proxy-connection", &connection_val); |
1182 | 1183 |
1183 bool keep_alive; | 1184 bool keep_alive; |
1184 | 1185 |
1185 if (http_version_ == HttpVersion(1, 0)) { | 1186 if (http_version_ == HttpVersion(1, 0)) { |
1186 // HTTP/1.0 responses default to NOT keep-alive | 1187 // HTTP/1.0 responses default to NOT keep-alive |
1187 keep_alive = LowerCaseEqualsASCII(connection_val, "keep-alive"); | 1188 keep_alive = base::LowerCaseEqualsASCII(connection_val, "keep-alive"); |
1188 } else { | 1189 } else { |
1189 // HTTP/1.1 responses default to keep-alive | 1190 // HTTP/1.1 responses default to keep-alive |
1190 keep_alive = !LowerCaseEqualsASCII(connection_val, "close"); | 1191 keep_alive = !base::LowerCaseEqualsASCII(connection_val, "close"); |
1191 } | 1192 } |
1192 | 1193 |
1193 return keep_alive; | 1194 return keep_alive; |
1194 } | 1195 } |
1195 | 1196 |
1196 bool HttpResponseHeaders::HasStrongValidators() const { | 1197 bool HttpResponseHeaders::HasStrongValidators() const { |
1197 std::string etag_header; | 1198 std::string etag_header; |
1198 EnumerateHeader(NULL, "etag", &etag_header); | 1199 EnumerateHeader(NULL, "etag", &etag_header); |
1199 std::string last_modified_header; | 1200 std::string last_modified_header; |
1200 EnumerateHeader(NULL, "Last-Modified", &last_modified_header); | 1201 EnumerateHeader(NULL, "Last-Modified", &last_modified_header); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1255 size_t space_position = content_range_spec.find(' '); | 1256 size_t space_position = content_range_spec.find(' '); |
1256 if (space_position == std::string::npos) | 1257 if (space_position == std::string::npos) |
1257 return false; | 1258 return false; |
1258 | 1259 |
1259 // Invalid header if it doesn't contain "bytes-unit". | 1260 // Invalid header if it doesn't contain "bytes-unit". |
1260 std::string::const_iterator content_range_spec_begin = | 1261 std::string::const_iterator content_range_spec_begin = |
1261 content_range_spec.begin(); | 1262 content_range_spec.begin(); |
1262 std::string::const_iterator content_range_spec_end = | 1263 std::string::const_iterator content_range_spec_end = |
1263 content_range_spec.begin() + space_position; | 1264 content_range_spec.begin() + space_position; |
1264 HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end); | 1265 HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end); |
1265 if (!LowerCaseEqualsASCII(content_range_spec_begin, | 1266 if (!base::LowerCaseEqualsASCII(content_range_spec_begin, |
1266 content_range_spec_end, | 1267 content_range_spec_end, |
1267 "bytes")) { | 1268 "bytes")) { |
1268 return false; | 1269 return false; |
1269 } | 1270 } |
1270 | 1271 |
1271 size_t slash_position = content_range_spec.find('/', space_position + 1); | 1272 size_t slash_position = content_range_spec.find('/', space_position + 1); |
1272 if (slash_position == std::string::npos) | 1273 if (slash_position == std::string::npos) |
1273 return false; | 1274 return false; |
1274 | 1275 |
1275 // Obtain the part behind the space and before slash. | 1276 // Obtain the part behind the space and before slash. |
1276 std::string::const_iterator byte_range_resp_spec_begin = | 1277 std::string::const_iterator byte_range_resp_spec_begin = |
1277 content_range_spec.begin() + space_position + 1; | 1278 content_range_spec.begin() + space_position + 1; |
1278 std::string::const_iterator byte_range_resp_spec_end = | 1279 std::string::const_iterator byte_range_resp_spec_end = |
1279 content_range_spec.begin() + slash_position; | 1280 content_range_spec.begin() + slash_position; |
1280 HttpUtil::TrimLWS(&byte_range_resp_spec_begin, &byte_range_resp_spec_end); | 1281 HttpUtil::TrimLWS(&byte_range_resp_spec_begin, &byte_range_resp_spec_end); |
1281 | 1282 |
1282 // Parse the byte-range-resp-spec part. | 1283 // Parse the byte-range-resp-spec part. |
1283 std::string byte_range_resp_spec(byte_range_resp_spec_begin, | 1284 std::string byte_range_resp_spec(byte_range_resp_spec_begin, |
1284 byte_range_resp_spec_end); | 1285 byte_range_resp_spec_end); |
1285 // If byte-range-resp-spec != "*". | 1286 // If byte-range-resp-spec != "*". |
1286 if (!LowerCaseEqualsASCII(byte_range_resp_spec, "*")) { | 1287 if (!base::LowerCaseEqualsASCII(byte_range_resp_spec, "*")) { |
1287 size_t minus_position = byte_range_resp_spec.find('-'); | 1288 size_t minus_position = byte_range_resp_spec.find('-'); |
1288 if (minus_position != std::string::npos) { | 1289 if (minus_position != std::string::npos) { |
1289 // Obtain first-byte-pos. | 1290 // Obtain first-byte-pos. |
1290 std::string::const_iterator first_byte_pos_begin = | 1291 std::string::const_iterator first_byte_pos_begin = |
1291 byte_range_resp_spec.begin(); | 1292 byte_range_resp_spec.begin(); |
1292 std::string::const_iterator first_byte_pos_end = | 1293 std::string::const_iterator first_byte_pos_end = |
1293 byte_range_resp_spec.begin() + minus_position; | 1294 byte_range_resp_spec.begin() + minus_position; |
1294 HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); | 1295 HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); |
1295 | 1296 |
1296 bool ok = base::StringToInt64(StringPiece(first_byte_pos_begin, | 1297 bool ok = base::StringToInt64(StringPiece(first_byte_pos_begin, |
(...skipping 23 matching lines...) Expand all Loading... |
1320 } | 1321 } |
1321 | 1322 |
1322 // Parse the instance-length part. | 1323 // Parse the instance-length part. |
1323 // If instance-length == "*". | 1324 // If instance-length == "*". |
1324 std::string::const_iterator instance_length_begin = | 1325 std::string::const_iterator instance_length_begin = |
1325 content_range_spec.begin() + slash_position + 1; | 1326 content_range_spec.begin() + slash_position + 1; |
1326 std::string::const_iterator instance_length_end = | 1327 std::string::const_iterator instance_length_end = |
1327 content_range_spec.end(); | 1328 content_range_spec.end(); |
1328 HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end); | 1329 HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end); |
1329 | 1330 |
1330 if (LowerCaseEqualsASCII(instance_length_begin, instance_length_end, "*")) { | 1331 if (base::LowerCaseEqualsASCII(instance_length_begin, instance_length_end, |
| 1332 "*")) { |
1331 return false; | 1333 return false; |
1332 } else if (!base::StringToInt64(StringPiece(instance_length_begin, | 1334 } else if (!base::StringToInt64(StringPiece(instance_length_begin, |
1333 instance_length_end), | 1335 instance_length_end), |
1334 instance_length)) { | 1336 instance_length)) { |
1335 *instance_length = -1; | 1337 *instance_length = -1; |
1336 return false; | 1338 return false; |
1337 } | 1339 } |
1338 | 1340 |
1339 // We have all the values; let's verify that they make sense for a 206 | 1341 // We have all the values; let's verify that they make sense for a 206 |
1340 // response. | 1342 // response. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 return true; | 1399 return true; |
1398 } | 1400 } |
1399 | 1401 |
1400 bool HttpResponseHeaders::IsChunkEncoded() const { | 1402 bool HttpResponseHeaders::IsChunkEncoded() const { |
1401 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1403 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
1402 return GetHttpVersion() >= HttpVersion(1, 1) && | 1404 return GetHttpVersion() >= HttpVersion(1, 1) && |
1403 HasHeaderValue("Transfer-Encoding", "chunked"); | 1405 HasHeaderValue("Transfer-Encoding", "chunked"); |
1404 } | 1406 } |
1405 | 1407 |
1406 } // namespace net | 1408 } // namespace net |
OLD | NEW |