Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 // ParseStatusLine adds a normalized status line to raw_headers_ | 383 // ParseStatusLine adds a normalized status line to raw_headers_ |
| 384 std::string::const_iterator line_begin = raw_input.begin(); | 384 std::string::const_iterator line_begin = raw_input.begin(); |
| 385 std::string::const_iterator line_end = | 385 std::string::const_iterator line_end = |
| 386 std::find(line_begin, raw_input.end(), '\0'); | 386 std::find(line_begin, raw_input.end(), '\0'); |
| 387 // has_headers = true, if there is any data following the status line. | 387 // has_headers = true, if there is any data following the status line. |
| 388 // Used by ParseStatusLine() to decide if a HTTP/0.9 is really a HTTP/1.0. | 388 // Used by ParseStatusLine() to decide if a HTTP/0.9 is really a HTTP/1.0. |
| 389 bool has_headers = (line_end != raw_input.end() && | 389 bool has_headers = (line_end != raw_input.end() && |
| 390 (line_end + 1) != raw_input.end() && | 390 (line_end + 1) != raw_input.end() && |
| 391 *(line_end + 1) != '\0'); | 391 *(line_end + 1) != '\0'); |
| 392 ParseStatusLine(line_begin, line_end, has_headers); | 392 ParseStatusLine(line_begin, line_end, has_headers); |
| 393 raw_headers_.push_back('\0'); // terminate status line with a null | |
|
rvargas (doing something else)
2011/11/30 22:53:09
Nit: Start with uppercase and end with period.
| |
| 393 | 394 |
| 394 if (line_end == raw_input.end()) { | 395 if (line_end == raw_input.end()) { |
| 395 raw_headers_.push_back('\0'); | 396 raw_headers_.push_back('\0'); // ensure the headers end with a double null |
|
rvargas (doing something else)
2011/11/30 22:53:09
ibid
| |
| 397 | |
| 398 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]); | |
| 399 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]); | |
| 396 return; | 400 return; |
| 397 } | 401 } |
| 398 | 402 |
| 399 // Including a terminating null byte. | 403 // Including a terminating null byte. |
| 400 size_t status_line_len = raw_headers_.size(); | 404 size_t status_line_len = raw_headers_.size(); |
| 401 | 405 |
| 402 // Now, we add the rest of the raw headers to raw_headers_, and begin parsing | 406 // Now, we add the rest of the raw headers to raw_headers_, and begin parsing |
| 403 // it (to populate our parsed_ vector). | 407 // it (to populate our parsed_ vector). |
| 404 raw_headers_.append(line_end + 1, raw_input.end()); | 408 raw_headers_.append(line_end + 1, raw_input.end()); |
| 405 | 409 |
| 406 // Adjust to point at the null byte following the status line | 410 // Adjust to point at the null byte following the status line |
| 407 line_end = raw_headers_.begin() + status_line_len - 1; | 411 line_end = raw_headers_.begin() + status_line_len - 1; |
| 408 | 412 |
| 409 HttpUtil::HeadersIterator headers(line_end + 1, raw_headers_.end(), | 413 HttpUtil::HeadersIterator headers(line_end + 1, raw_headers_.end(), |
| 410 std::string(1, '\0')); | 414 std::string(1, '\0')); |
| 411 while (headers.GetNext()) { | 415 while (headers.GetNext()) { |
| 412 AddHeader(headers.name_begin(), | 416 AddHeader(headers.name_begin(), |
| 413 headers.name_end(), | 417 headers.name_end(), |
| 414 headers.values_begin(), | 418 headers.values_begin(), |
| 415 headers.values_end()); | 419 headers.values_end()); |
| 416 } | 420 } |
| 421 | |
| 422 // Ensure the headers end with a double null. | |
| 423 while (raw_headers_.size() < 2 || | |
| 424 raw_headers_[raw_headers_.size() - 2] != '\0' || | |
| 425 raw_headers_[raw_headers_.size() - 1] != '\0') { | |
| 426 raw_headers_.push_back('\0'); | |
| 427 } | |
| 428 | |
| 429 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]); | |
| 430 DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]); | |
| 417 } | 431 } |
| 418 | 432 |
| 419 // Append all of our headers to the final output string. | 433 // Append all of our headers to the final output string. |
| 420 void HttpResponseHeaders::GetNormalizedHeaders(std::string* output) const { | 434 void HttpResponseHeaders::GetNormalizedHeaders(std::string* output) const { |
| 421 // copy up to the null byte. this just copies the status line. | 435 // copy up to the null byte. this just copies the status line. |
| 422 output->assign(raw_headers_.c_str()); | 436 output->assign(raw_headers_.c_str()); |
| 423 | 437 |
| 424 // headers may appear multiple times (not necessarily in succession) in the | 438 // headers may appear multiple times (not necessarily in succession) in the |
| 425 // header data, so we build a map from header name to generated header lines. | 439 // header data, so we build a map from header name to generated header lines. |
| 426 // to preserve the order of the original headers, the actual values are kept | 440 // to preserve the order of the original headers, the actual values are kept |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 DVLOG(1) << "assuming HTTP/" << http_version_.major_value() << "." | 670 DVLOG(1) << "assuming HTTP/" << http_version_.major_value() << "." |
| 657 << http_version_.minor_value(); | 671 << http_version_.minor_value(); |
| 658 } | 672 } |
| 659 | 673 |
| 660 // TODO(eroman): this doesn't make sense if ParseVersion failed. | 674 // TODO(eroman): this doesn't make sense if ParseVersion failed. |
| 661 std::string::const_iterator p = std::find(line_begin, line_end, ' '); | 675 std::string::const_iterator p = std::find(line_begin, line_end, ' '); |
| 662 | 676 |
| 663 if (p == line_end) { | 677 if (p == line_end) { |
| 664 DVLOG(1) << "missing response status; assuming 200 OK"; | 678 DVLOG(1) << "missing response status; assuming 200 OK"; |
| 665 raw_headers_.append(" 200 OK"); | 679 raw_headers_.append(" 200 OK"); |
| 666 raw_headers_.push_back('\0'); | |
| 667 response_code_ = 200; | 680 response_code_ = 200; |
| 668 return; | 681 return; |
| 669 } | 682 } |
| 670 | 683 |
| 671 // Skip whitespace. | 684 // Skip whitespace. |
| 672 while (*p == ' ') | 685 while (*p == ' ') |
| 673 ++p; | 686 ++p; |
| 674 | 687 |
| 675 std::string::const_iterator code = p; | 688 std::string::const_iterator code = p; |
| 676 while (*p >= '0' && *p <= '9') | 689 while (*p >= '0' && *p <= '9') |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 696 --line_end; | 709 --line_end; |
| 697 | 710 |
| 698 if (p == line_end) { | 711 if (p == line_end) { |
| 699 DVLOG(1) << "missing response status text; assuming OK"; | 712 DVLOG(1) << "missing response status text; assuming OK"; |
| 700 // Not super critical what we put here. Just use "OK" | 713 // Not super critical what we put here. Just use "OK" |
| 701 // even if it isn't descriptive of response_code_. | 714 // even if it isn't descriptive of response_code_. |
| 702 raw_headers_.append("OK"); | 715 raw_headers_.append("OK"); |
| 703 } else { | 716 } else { |
| 704 raw_headers_.append(p, line_end); | 717 raw_headers_.append(p, line_end); |
| 705 } | 718 } |
| 706 | |
| 707 raw_headers_.push_back('\0'); | |
| 708 } | 719 } |
| 709 | 720 |
| 710 size_t HttpResponseHeaders::FindHeader(size_t from, | 721 size_t HttpResponseHeaders::FindHeader(size_t from, |
| 711 const std::string& search) const { | 722 const std::string& search) const { |
| 712 for (size_t i = from; i < parsed_.size(); ++i) { | 723 for (size_t i = from; i < parsed_.size(); ++i) { |
| 713 if (parsed_[i].is_continuation()) | 724 if (parsed_[i].is_continuation()) |
| 714 continue; | 725 continue; |
| 715 const std::string::const_iterator& name_begin = parsed_[i].name_begin; | 726 const std::string::const_iterator& name_begin = parsed_[i].name_begin; |
| 716 const std::string::const_iterator& name_end = parsed_[i].name_end; | 727 const std::string::const_iterator& name_end = parsed_[i].name_end; |
| 717 if (static_cast<size_t>(name_end - name_begin) == search.size() && | 728 if (static_cast<size_t>(name_end - name_begin) == search.size() && |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1291 return true; | 1302 return true; |
| 1292 } | 1303 } |
| 1293 | 1304 |
| 1294 bool HttpResponseHeaders::IsChunkEncoded() const { | 1305 bool HttpResponseHeaders::IsChunkEncoded() const { |
| 1295 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1306 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
| 1296 return GetHttpVersion() >= HttpVersion(1, 1) && | 1307 return GetHttpVersion() >= HttpVersion(1, 1) && |
| 1297 HasHeaderValue("Transfer-Encoding", "chunked"); | 1308 HasHeaderValue("Transfer-Encoding", "chunked"); |
| 1298 } | 1309 } |
| 1299 | 1310 |
| 1300 } // namespace net | 1311 } // namespace net |
| OLD | NEW |