diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-28 21:23:39 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-28 21:23:39 +0000 |
commit | fc48db85fecb5889fbfc5de5c9b8951dce547546 (patch) | |
tree | d7a0e01a06404219af4c05da4a2833ed9072859e /net/http/http_util.cc | |
parent | 4684b1223a711baa9b4e37996c797600060b6f2e (diff) | |
download | chromium_src-fc48db85fecb5889fbfc5de5c9b8951dce547546.zip chromium_src-fc48db85fecb5889fbfc5de5c9b8951dce547546.tar.gz chromium_src-fc48db85fecb5889fbfc5de5c9b8951dce547546.tar.bz2 |
Implement a parser that parses the "Range" HTTP header
Parses "Range" HTTP request header so this request information
can be used in URLRequestFileJob and HttpCache.
Review URL: http://codereview.chromium.org/92006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14784 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http/http_util.cc')
-rw-r--r-- | net/http/http_util.cc | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index 500222a..f3e0835 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc @@ -195,6 +195,99 @@ void HttpUtil::ParseContentType(const string& content_type_str, } // static +// Parse the Range header according to RFC 2616 14.35.1 +// ranges-specifier = byte-ranges-specifier +// byte-ranges-specifier = bytes-unit "=" byte-range-set +// byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec ) +// byte-range-spec = first-byte-pos "-" [last-byte-pos] +// first-byte-pos = 1*DIGIT +// last-byte-pos = 1*DIGIT +bool HttpUtil::ParseRanges(const std::string& headers, + std::vector<HttpByteRange>* ranges) { + std::string ranges_specifier; + HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); + + while (it.GetNext()) { + // Look for "Range" header. + if (!LowerCaseEqualsASCII(it.name(), "range")) + continue; + ranges_specifier = it.values(); + // We just care about the first "Range" header, so break here. + break; + } + + if (ranges_specifier.empty()) + return false; + + size_t equal_char_offset = ranges_specifier.find('='); + if (equal_char_offset == std::string::npos) + return false; + + // Try to extract bytes-unit part. + std::string::const_iterator bytes_unit_begin = ranges_specifier.begin(); + std::string::const_iterator bytes_unit_end = bytes_unit_begin + + equal_char_offset; + std::string::const_iterator byte_range_set_begin = bytes_unit_end + 1; + std::string::const_iterator byte_range_set_end = ranges_specifier.end(); + + TrimLWS(&bytes_unit_begin, &bytes_unit_end); + // "bytes" unit identifier is not found. + if (!LowerCaseEqualsASCII(bytes_unit_begin, bytes_unit_end, "bytes")) + return false; + + ValuesIterator byte_range_set_iterator(byte_range_set_begin, + byte_range_set_end, ','); + while (byte_range_set_iterator.GetNext()) { + size_t minus_char_offset = byte_range_set_iterator.value().find('-'); + // If '-' character is not found, reports failure. + if (minus_char_offset == std::string::npos) + return false; + + std::string::const_iterator first_byte_pos_begin = + byte_range_set_iterator.value_begin(); + std::string::const_iterator first_byte_pos_end = + first_byte_pos_begin + minus_char_offset; + TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); + std::string first_byte_pos(first_byte_pos_begin, first_byte_pos_end); + + HttpByteRange range; + // Try to obtain first-byte-pos. + if (!first_byte_pos.empty()) { + int64 first_byte_position = -1; + if (!StringToInt64(first_byte_pos, &first_byte_position)) + return false; + range.set_first_byte_position(first_byte_position); + } + + std::string::const_iterator last_byte_pos_begin = + byte_range_set_iterator.value_begin() + minus_char_offset + 1; + std::string::const_iterator last_byte_pos_end = + byte_range_set_iterator.value_end(); + TrimLWS(&last_byte_pos_begin, &last_byte_pos_end); + std::string last_byte_pos(last_byte_pos_begin, last_byte_pos_end); + + // We have last-byte-pos or suffix-byte-range-spec in this case. + if (!last_byte_pos.empty()) { + int64 last_byte_position; + if (!StringToInt64(last_byte_pos, &last_byte_position)) + return false; + if (range.HasFirstBytePosition()) + range.set_last_byte_position(last_byte_position); + else + range.set_suffix_length(last_byte_position); + } else if (!range.HasFirstBytePosition()) { + return false; + } + + // Do a final check on the HttpByteRange object. + if (!range.IsValid()) + return false; + ranges->push_back(range); + } + return ranges->size() > 0; +} + +// static bool HttpUtil::HasHeader(const std::string& headers, const char* name) { size_t name_len = strlen(name); string::const_iterator it = |