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 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 AddHeader(headers.name_begin(), | 453 AddHeader(headers.name_begin(), |
454 headers.name_end(), | 454 headers.name_end(), |
455 headers.values_begin(), | 455 headers.values_begin(), |
456 headers.values_end()); | 456 headers.values_end()); |
457 } | 457 } |
458 | 458 |
459 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]); | 459 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]); |
460 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]); | 460 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]); |
461 } | 461 } |
462 | 462 |
463 // Append all of our headers to the final output string. | |
464 void HttpResponseHeaders::GetNormalizedHeaders(std::string* output) const { | |
465 // copy up to the null byte. this just copies the status line. | |
466 output->assign(raw_headers_.c_str()); | |
467 | |
468 // headers may appear multiple times (not necessarily in succession) in the | |
469 // header data, so we build a map from header name to generated header lines. | |
470 // to preserve the order of the original headers, the actual values are kept | |
471 // in a separate list. finally, the list of headers is flattened to form | |
472 // the normalized block of headers. | |
473 // | |
474 // NOTE: We take special care to preserve the whitespace around any commas | |
475 // that may occur in the original response headers. Because our consumer may | |
476 // be a web app, we cannot be certain of the semantics of commas despite the | |
477 // fact that RFC 2616 says that they should be regarded as value separators. | |
478 // | |
479 using HeadersMap = std::unordered_map<std::string, size_t>; | |
480 HeadersMap headers_map; | |
481 HeadersMap::iterator iter = headers_map.end(); | |
482 | |
483 std::vector<std::string> headers; | |
484 | |
485 for (size_t i = 0; i < parsed_.size(); ++i) { | |
486 DCHECK(!parsed_[i].is_continuation()); | |
487 | |
488 std::string name(parsed_[i].name_begin, parsed_[i].name_end); | |
489 std::string lower_name = base::ToLowerASCII(name); | |
490 | |
491 iter = headers_map.find(lower_name); | |
492 if (iter == headers_map.end()) { | |
493 iter = headers_map.insert( | |
494 HeadersMap::value_type(lower_name, headers.size())).first; | |
495 headers.push_back(name + ": "); | |
496 } else { | |
497 headers[iter->second].append(", "); | |
498 } | |
499 | |
500 std::string::const_iterator value_begin = parsed_[i].value_begin; | |
501 std::string::const_iterator value_end = parsed_[i].value_end; | |
502 while (++i < parsed_.size() && parsed_[i].is_continuation()) | |
503 value_end = parsed_[i].value_end; | |
504 --i; | |
505 | |
506 headers[iter->second].append(value_begin, value_end); | |
507 } | |
508 | |
509 for (size_t i = 0; i < headers.size(); ++i) { | |
510 output->push_back('\n'); | |
511 output->append(headers[i]); | |
512 } | |
513 | |
514 output->push_back('\n'); | |
515 } | |
516 | |
517 bool HttpResponseHeaders::GetNormalizedHeader(const std::string& name, | 463 bool HttpResponseHeaders::GetNormalizedHeader(const std::string& name, |
518 std::string* value) const { | 464 std::string* value) const { |
519 // If you hit this assertion, please use EnumerateHeader instead! | 465 // If you hit this assertion, please use EnumerateHeader instead! |
520 DCHECK(!HttpUtil::IsNonCoalescingHeader(name)); | 466 DCHECK(!HttpUtil::IsNonCoalescingHeader(name)); |
521 | 467 |
522 value->clear(); | 468 value->clear(); |
523 | 469 |
524 bool found = false; | 470 bool found = false; |
525 size_t i = 0; | 471 size_t i = 0; |
526 while (i < parsed_.size()) { | 472 while (i < parsed_.size()) { |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1400 return true; | 1346 return true; |
1401 } | 1347 } |
1402 | 1348 |
1403 bool HttpResponseHeaders::IsChunkEncoded() const { | 1349 bool HttpResponseHeaders::IsChunkEncoded() const { |
1404 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1350 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
1405 return GetHttpVersion() >= HttpVersion(1, 1) && | 1351 return GetHttpVersion() >= HttpVersion(1, 1) && |
1406 HasHeaderValue("Transfer-Encoding", "chunked"); | 1352 HasHeaderValue("Transfer-Encoding", "chunked"); |
1407 } | 1353 } |
1408 | 1354 |
1409 } // namespace net | 1355 } // namespace net |
OLD | NEW |