summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-10 07:28:58 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-10 07:28:58 +0000
commit3d47dac962de7dd8ec9224d9c11a969259f3e0c7 (patch)
treea5aeeb8b42e24bea2e14cb67adf68e25c9e0d857
parentdf157d9d2ef8720c6cdb54cf98634e84915eec9d (diff)
downloadchromium_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.cc28
-rw-r--r--net/http/http_response_headers.h11
-rw-r--r--net/http/http_response_headers_unittest.cc53
-rw-r--r--net/http/partial_data.cc36
-rw-r--r--webkit/browser/appcache/appcache_url_request_job.cc19
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) {