| 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 |