diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-10 07:28:58 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-10 07:28:58 +0000 |
commit | 3d47dac962de7dd8ec9224d9c11a969259f3e0c7 (patch) | |
tree | a5aeeb8b42e24bea2e14cb67adf68e25c9e0d857 | |
parent | df157d9d2ef8720c6cdb54cf98634e84915eec9d (diff) | |
download | chromium_src-3d47dac962de7dd8ec9224d9c11a969259f3e0c7.zip chromium_src-3d47dac962de7dd8ec9224d9c11a969259f3e0c7.tar.gz chromium_src-3d47dac962de7dd8ec9224d9c11a969259f3e0c7.tar.bz2 |
Cleanup: have common HttpResponseHeaders routine to update with range
Currently we do this header-fixup in two places: PartialData and AppCache,
and I'm planning to do the very same header-fixup in yet another module,
ServiceWorker. I want to have a common utility in net/http/http_util
to do this so that all 3 modules can share it.
BUG=349319
TEST=HttpResponseHeadersTest.UpdateWithNewRange
Review URL: https://codereview.chromium.org/187583002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@255905 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/http/http_response_headers.cc | 28 | ||||
-rw-r--r-- | net/http/http_response_headers.h | 11 | ||||
-rw-r--r-- | net/http/http_response_headers_unittest.cc | 53 | ||||
-rw-r--r-- | net/http/partial_data.cc | 36 | ||||
-rw-r--r-- | webkit/browser/appcache/appcache_url_request_job.cc | 19 |
5 files changed, 106 insertions, 41 deletions
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index 2d74b38..dbe09a6 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc @@ -11,6 +11,7 @@ #include <algorithm> +#include "base/format_macros.h" #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/pickle.h" @@ -21,6 +22,7 @@ #include "base/time/time.h" #include "base/values.h" #include "net/base/escape.h" +#include "net/http/http_byte_range.h" #include "net/http/http_util.h" using base::StringPiece; @@ -374,6 +376,32 @@ void HttpResponseHeaders::ReplaceStatusLine(const std::string& new_status) { MergeWithHeaders(new_raw_headers, empty_to_remove); } +void HttpResponseHeaders::UpdateWithNewRange( + const HttpByteRange& byte_range, + int64 resource_size, + bool replace_status_line) { + DCHECK(byte_range.IsValid()); + DCHECK(byte_range.HasFirstBytePosition()); + DCHECK(byte_range.HasLastBytePosition()); + + const char kLengthHeader[] = "Content-Length"; + const char kRangeHeader[] = "Content-Range"; + + RemoveHeader(kLengthHeader); + RemoveHeader(kRangeHeader); + + int64 start = byte_range.first_byte_position(); + int64 end = byte_range.last_byte_position(); + int64 range_len = end - start + 1; + + if (replace_status_line) + ReplaceStatusLine("HTTP/1.1 206 Partial Content"); + + AddHeader(base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64, + kRangeHeader, start, end, resource_size)); + AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, range_len)); +} + void HttpResponseHeaders::Parse(const std::string& raw_input) { raw_headers_.reserve(raw_input.size()); diff --git a/net/http/http_response_headers.h b/net/http/http_response_headers.h index deba3b6..2eb0c67 100644 --- a/net/http/http_response_headers.h +++ b/net/http/http_response_headers.h @@ -26,6 +26,8 @@ class TimeDelta; namespace net { +class HttpByteRange; + // HttpResponseHeaders: parses and holds HTTP response headers. class NET_EXPORT HttpResponseHeaders : public base::RefCountedThreadSafe<HttpResponseHeaders> { @@ -83,6 +85,15 @@ class NET_EXPORT HttpResponseHeaders // not have any EOL). void ReplaceStatusLine(const std::string& new_status); + // Updates headers (Content-Length and Content-Range) in the |headers| to + // include the right content length and range for |byte_range|. This also + // updates HTTP status line if |replace_status_line| is true. + // |byte_range| must have a valid, bounded range (i.e. coming from a valid + // response or should be usable for a response). + void UpdateWithNewRange(const HttpByteRange& byte_range, + int64 resource_size, + bool replace_status_line); + // Creates a normalized header string. The output will be formatted exactly // like so: // HTTP/<version> <status_code> <status_text>\n diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc index c433e1d..0b17b8f 100644 --- a/net/http/http_response_headers_unittest.cc +++ b/net/http/http_response_headers_unittest.cc @@ -9,6 +9,7 @@ #include "base/pickle.h" #include "base/time/time.h" #include "base/values.h" +#include "net/http/http_byte_range.h" #include "net/http/http_response_headers.h" #include "testing/gtest/include/gtest/gtest.h" @@ -1851,6 +1852,58 @@ TEST(HttpResponseHeadersTest, ReplaceStatus) { } } +TEST(HttpResponseHeadersTest, UpdateWithNewRange) { + const struct { + const char* orig_headers; + const char* expected_headers; + const char* expected_headers_with_replaced_status; + } tests[] = { + { "HTTP/1.1 200 OK\n" + "Content-Length: 450\n", + + "HTTP/1.1 200 OK\n" + "Content-Range: bytes 3-5/450\n" + "Content-Length: 3\n", + + "HTTP/1.1 206 Partial Content\n" + "Content-Range: bytes 3-5/450\n" + "Content-Length: 3\n", + }, + { "HTTP/1.1 200 OK\n" + "Content-Length: 5\n", + + "HTTP/1.1 200 OK\n" + "Content-Range: bytes 3-5/5\n" + "Content-Length: 3\n", + + "HTTP/1.1 206 Partial Content\n" + "Content-Range: bytes 3-5/5\n" + "Content-Length: 3\n", + }, + }; + const net::HttpByteRange range = net::HttpByteRange::Bounded(3, 5); + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + std::string orig_headers(tests[i].orig_headers); + std::replace(orig_headers.begin(), orig_headers.end(), '\n', '\0'); + scoped_refptr<net::HttpResponseHeaders> parsed( + new net::HttpResponseHeaders(orig_headers + '\0')); + int64 content_size = parsed->GetContentLength(); + std::string resulting_headers; + + // Update headers without replacing status line. + parsed->UpdateWithNewRange(range, content_size, false); + parsed->GetNormalizedHeaders(&resulting_headers); + EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers); + + // Replace status line too. + parsed->UpdateWithNewRange(range, content_size, true); + parsed->GetNormalizedHeaders(&resulting_headers); + EXPECT_EQ(std::string(tests[i].expected_headers_with_replaced_status), + resulting_headers); + } +} + TEST(HttpResponseHeadersTest, ToNetLogParamAndBackAgain) { std::string headers("HTTP/1.1 404\n" "Content-Length: 450\n" diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc index ee3678b..a05c218 100644 --- a/net/http/partial_data.cc +++ b/net/http/partial_data.cc @@ -382,40 +382,26 @@ void PartialData::FixResponseHeaders(HttpResponseHeaders* headers, if (truncated_) return; + if (byte_range_.IsValid() && success) { + headers->UpdateWithNewRange(byte_range_, resource_size_, !sparse_entry_); + return; + } + headers->RemoveHeader(kLengthHeader); headers->RemoveHeader(kRangeHeader); - int64 range_len, start, end; if (byte_range_.IsValid()) { - if (success) { - if (!sparse_entry_) - headers->ReplaceStatusLine("HTTP/1.1 206 Partial Content"); - - DCHECK(byte_range_.HasFirstBytePosition()); - DCHECK(byte_range_.HasLastBytePosition()); - start = byte_range_.first_byte_position(); - end = byte_range_.last_byte_position(); - range_len = end - start + 1; - } else { - headers->ReplaceStatusLine( - "HTTP/1.1 416 Requested Range Not Satisfiable"); - start = 0; - end = 0; - range_len = 0; - } - - headers->AddHeader( - base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64, - kRangeHeader, start, end, resource_size_)); + headers->ReplaceStatusLine("HTTP/1.1 416 Requested Range Not Satisfiable"); + headers->AddHeader(base::StringPrintf("%s: bytes 0-0/%" PRId64, + kRangeHeader, resource_size_)); + headers->AddHeader(base::StringPrintf("%s: 0", kLengthHeader)); } else { // TODO(rvargas): Is it safe to change the protocol version? headers->ReplaceStatusLine("HTTP/1.1 200 OK"); DCHECK_NE(resource_size_, 0); - range_len = resource_size_; + headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, + resource_size_)); } - - headers->AddHeader(base::StringPrintf("%s: %" PRId64, kLengthHeader, - range_len)); } void PartialData::FixContentLength(HttpResponseHeaders* headers) { diff --git a/webkit/browser/appcache/appcache_url_request_job.cc b/webkit/browser/appcache/appcache_url_request_job.cc index 759d757..30f1c1f 100644 --- a/webkit/browser/appcache/appcache_url_request_job.cc +++ b/webkit/browser/appcache/appcache_url_request_job.cc @@ -310,8 +310,7 @@ void AppCacheURLRequestJob::SetupRangeResponse() { return; } - DCHECK(range_requested_.HasFirstBytePosition() && - range_requested_.HasLastBytePosition()); + DCHECK(range_requested_.IsValid()); int offset = static_cast<int>(range_requested_.first_byte_position()); int length = static_cast<int>(range_requested_.last_byte_position() - range_requested_.first_byte_position() + 1); @@ -321,23 +320,11 @@ void AppCacheURLRequestJob::SetupRangeResponse() { // Make a copy of the full response headers and fix them up // for the range we'll be returning. - const char kLengthHeader[] = "Content-Length"; - const char kRangeHeader[] = "Content-Range"; - const char kPartialStatusLine[] = "HTTP/1.1 206 Partial Content"; range_response_info_.reset( new net::HttpResponseInfo(*info_->http_response_info())); net::HttpResponseHeaders* headers = range_response_info_->headers.get(); - headers->RemoveHeader(kLengthHeader); - headers->RemoveHeader(kRangeHeader); - headers->ReplaceStatusLine(kPartialStatusLine); - headers->AddHeader( - base::StringPrintf("%s: %d", kLengthHeader, length)); - headers->AddHeader( - base::StringPrintf("%s: bytes %d-%d/%d", - kRangeHeader, - offset, - offset + length - 1, - resource_size)); + headers->UpdateWithNewRange( + range_requested_, resource_size, true /* replace status line */); } void AppCacheURLRequestJob::OnReadComplete(int result) { |