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. |
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. |
| 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 |
| 410 // Ensure the headers end with a double null. |
| 411 while (raw_headers_.size() < 2 || |
| 412 raw_headers_[raw_headers_.size() - 2] != '\0' || |
| 413 raw_headers_[raw_headers_.size() - 1] != '\0') { |
| 414 raw_headers_.push_back('\0'); |
| 415 } |
| 416 |
406 // Adjust to point at the null byte following the status line | 417 // Adjust to point at the null byte following the status line |
407 line_end = raw_headers_.begin() + status_line_len - 1; | 418 line_end = raw_headers_.begin() + status_line_len - 1; |
408 | 419 |
409 HttpUtil::HeadersIterator headers(line_end + 1, raw_headers_.end(), | 420 HttpUtil::HeadersIterator headers(line_end + 1, raw_headers_.end(), |
410 std::string(1, '\0')); | 421 std::string(1, '\0')); |
411 while (headers.GetNext()) { | 422 while (headers.GetNext()) { |
412 AddHeader(headers.name_begin(), | 423 AddHeader(headers.name_begin(), |
413 headers.name_end(), | 424 headers.name_end(), |
414 headers.values_begin(), | 425 headers.values_begin(), |
415 headers.values_end()); | 426 headers.values_end()); |
416 } | 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 |