summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/http/http_cache_transaction.cc37
-rw-r--r--net/http/http_cache_transaction.h7
-rw-r--r--net/http/http_cache_unittest.cc31
-rw-r--r--net/http/partial_data.cc46
-rw-r--r--net/http/partial_data.h4
5 files changed, 98 insertions, 27 deletions
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index a6ef5e0..96b1fff 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -672,7 +672,8 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
return OK;
}
- if (!ValidatePartialResponse(new_response->headers, &server_responded_206_) &&
+ new_response_ = new_response;
+ if (!ValidatePartialResponse(&server_responded_206_) &&
!auth_response_.headers) {
// Something went wrong with this request and we have to restart it.
// If we have an authentication response, we are exposed to weird things
@@ -680,6 +681,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
// the new response.
response_ = HttpResponseInfo();
network_trans_.reset();
+ new_response_ = NULL;
next_state_ = STATE_SEND_REQUEST;
return OK;
}
@@ -690,9 +692,14 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
DoneWritingToEntry(false);
}
+ if (enable_range_support_ && new_response_->headers->response_code() == 416) {
+ DCHECK_EQ(NONE, mode_);
+ response_ = *new_response_;
+ return OK;
+ }
+
HistogramHeaders(new_response->headers);
- new_response_ = new_response;
// Are we expecting a response to a conditional query?
if (mode_ == READ_WRITE || mode_ == UPDATE) {
if (new_response->headers->response_code() == 304 ||
@@ -1044,7 +1051,7 @@ int HttpCache::Transaction::DoPartialHeadersReceived() {
} else if (mode_ != NONE) {
// We are about to return the headers for a byte-range request to the user,
// so let's fix them.
- partial_->FixResponseHeaders(response_.headers);
+ partial_->FixResponseHeaders(response_.headers, true);
}
return OK;
}
@@ -1396,7 +1403,7 @@ int HttpCache::Transaction::BeginCacheValidation() {
bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE ||
!RequiresValidation();
- if (partial_.get() && !partial_->IsCurrentRangeCached())
+ if (partial_.get() && !partial_->IsCurrentRangeCached() || invalid_range_)
skip_validation = false;
if (skip_validation) {
@@ -1597,8 +1604,11 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
}
DCHECK(custom_request_.get());
+ bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() &&
+ !invalid_range_;
+
if (!etag_value.empty()) {
- if (partial_.get() && !partial_->IsCurrentRangeCached()) {
+ if (use_if_range) {
// We don't want to switch to WRITE mode if we don't have this block of a
// byte-range request because we may have other parts cached.
custom_request_->extra_headers.SetHeader(
@@ -1614,7 +1624,7 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
}
if (!last_modified_value.empty()) {
- if (partial_.get() && !partial_->IsCurrentRangeCached()) {
+ if (use_if_range) {
custom_request_->extra_headers.SetHeader(
HttpRequestHeaders::kIfRange, last_modified_value);
} else {
@@ -1644,8 +1654,8 @@ bool HttpCache::Transaction::ConditionalizeRequest() {
// WARNING: Whenever this code returns false, it has to make sure that the next
// time it is called it will return true so that we don't keep retrying the
// request.
-bool HttpCache::Transaction::ValidatePartialResponse(
- const HttpResponseHeaders* headers, bool* partial_content) {
+bool HttpCache::Transaction::ValidatePartialResponse(bool* partial_content) {
+ const HttpResponseHeaders* headers = new_response_->headers;
int response_code = headers->response_code();
bool partial_response = enable_range_support_ ? response_code == 206 : false;
*partial_content = false;
@@ -1657,10 +1667,13 @@ bool HttpCache::Transaction::ValidatePartialResponse(
// We gave up trying to match this request with the stored data. If the
// server is ok with the request, delete the entry, otherwise just ignore
// this request
- if (partial_response || response_code == 200 || response_code == 304) {
+ DCHECK(!reading_);
+ if (partial_response || response_code == 200) {
DoomPartialEntry(true);
mode_ = NONE;
} else {
+ if (response_code == 304)
+ FailRangeRequest();
IgnoreRangeRequest();
}
return true;
@@ -1734,6 +1747,11 @@ void HttpCache::Transaction::IgnoreRangeRequest() {
mode_ = NONE;
}
+void HttpCache::Transaction::FailRangeRequest() {
+ response_ = *new_response_;
+ partial_->FixResponseHeaders(response_.headers, false);
+}
+
int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) {
read_buf_ = data;
io_buf_len_ = data_len;
@@ -1829,6 +1847,7 @@ void HttpCache::Transaction::DoneWritingToEntry(bool success) {
}
void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
+ DVLOG(2) << "DoomPartialEntry";
int rv = cache_->DoomEntry(cache_key_, NULL);
DCHECK_EQ(OK, rv);
cache_->DoneWithEntry(entry_, this, false);
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 2883282..4d3673c 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -267,12 +267,15 @@ class HttpCache::Transaction : public HttpTransaction {
// Makes sure that a 206 response is expected. Returns true on success.
// On success, |partial_content| will be set to true if we are processing a
// partial entry.
- bool ValidatePartialResponse(const HttpResponseHeaders* headers,
- bool* partial_content);
+ bool ValidatePartialResponse(bool* partial_content);
// Handles a response validation error by bypassing the cache.
void IgnoreRangeRequest();
+ // Changes the response code of a range request to be 416 (Requested range not
+ // satisfiable).
+ void FailRangeRequest();
+
// Reads data from the network.
int ReadFromNetwork(IOBuffer* data, int data_len);
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 2c8e16d..eec8098 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -863,6 +863,7 @@ void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request,
std::string* response_data) {
if (request->extra_headers.IsEmpty()) {
response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
+ response_data->clear();
return;
}
@@ -871,6 +872,7 @@ void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request,
if (not_modified_) {
response_status->assign("HTTP/1.1 304 Not Modified");
+ response_data->clear();
return;
}
@@ -885,6 +887,7 @@ void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request,
net::HttpByteRange byte_range = ranges[0];
if (byte_range.first_byte_position() > 79) {
response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
+ response_data->clear();
return;
}
@@ -3164,7 +3167,7 @@ TEST(HttpCache, UnknownRangeGET_304) {
// Ask for the end of the file, without knowing the length.
transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
- transaction.data = "rg: 70-79 ";
+ transaction.data = "";
RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
// We just bypass the cache.
@@ -3409,13 +3412,34 @@ TEST(HttpCache, RangeGET_Previous200) {
// The last transaction has finished so make sure the entry is deactivated.
MessageLoop::current()->RunAllPending();
+ // Make a request for an invalid range.
+ MockTransaction transaction3(kRangeGET_TransactionOK);
+ transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER;
+ transaction3.data = "";
+ transaction3.load_flags = net::LOAD_PREFERRING_CACHE;
+ RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers);
+ EXPECT_EQ(2, cache.disk_cache()->open_count());
+ EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
+ EXPECT_NE(std::string::npos, headers.find("Content-Range: bytes 0-0/80"));
+ EXPECT_NE(std::string::npos, headers.find("Content-Length: 0"));
+
+ // Make sure the entry is deactivated.
+ MessageLoop::current()->RunAllPending();
+
+ // Even though the request was invalid, we should have the entry.
+ RunTransactionTest(cache.http_cache(), transaction2);
+ EXPECT_EQ(3, cache.disk_cache()->open_count());
+
+ // Make sure the entry is deactivated.
+ MessageLoop::current()->RunAllPending();
+
// Now we should receive a range from the server and drop the stored entry.
handler.set_not_modified(false);
transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
Verify206Response(headers, 40, 49);
- EXPECT_EQ(3, cache.network_layer()->transaction_count());
- EXPECT_EQ(2, cache.disk_cache()->open_count());
+ EXPECT_EQ(5, cache.network_layer()->transaction_count());
+ EXPECT_EQ(4, cache.disk_cache()->open_count());
EXPECT_EQ(1, cache.disk_cache()->create_count());
RunTransactionTest(cache.http_cache(), transaction2);
@@ -3484,6 +3508,7 @@ TEST(HttpCache, RangeGET_MoreThanCurrentSize) {
// A weird request should not delete this entry. Ask for bytes 120-.
MockTransaction transaction(kRangeGET_TransactionOK);
transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER;
+ transaction.data = "";
RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc
index 54900b3..799c3fa 100644
--- a/net/http/partial_data.cc
+++ b/net/http/partial_data.cc
@@ -127,6 +127,9 @@ bool PartialData::Init(const HttpRequestHeaders& headers) {
resource_size_ = 0;
current_range_start_ = byte_range_.first_byte_position();
+
+ DVLOG(1) << "Range start: " << current_range_start_ << " end: " <<
+ byte_range_.last_byte_position();
return true;
}
@@ -154,6 +157,8 @@ int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
if (!len)
return 0;
+ DVLOG(3) << "ShouldValidateCache len: " << len;
+
if (sparse_entry_) {
DCHECK(!callback_);
Core* core = Core::CreateCore(this);
@@ -171,6 +176,12 @@ int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
cached_start_ = 0;
}
} else {
+ if (byte_range_.HasFirstBytePosition() &&
+ byte_range_.first_byte_position() >= resource_size_) {
+ // The caller should take care of this condition because we should have
+ // failed IsRequestedRangeOK(), but it's better to be consistent here.
+ len = 0;
+ }
cached_min_len_ = len;
cached_start_ = current_range_start_;
}
@@ -250,6 +261,7 @@ bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
DCHECK(byte_range_.IsValid());
sparse_entry_ = false;
resource_size_ = entry->GetDataSize(kDataStream);
+ DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_;
return true;
}
@@ -335,28 +347,36 @@ bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) {
// We are making multiple requests to complete the range requested by the user.
// Just assume that everything is fine and say that we are returning what was
// requested.
-void PartialData::FixResponseHeaders(HttpResponseHeaders* headers) {
+void PartialData::FixResponseHeaders(HttpResponseHeaders* headers,
+ bool success) {
if (truncated_)
return;
headers->RemoveHeader(kLengthHeader);
headers->RemoveHeader(kRangeHeader);
- int64 range_len;
+ int64 range_len, start, end;
if (byte_range_.IsValid()) {
- if (!sparse_entry_)
- headers->ReplaceStatusLine("HTTP/1.1 206 Partial Content");
+ 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;
+ }
- DCHECK(byte_range_.HasFirstBytePosition());
- DCHECK(byte_range_.HasLastBytePosition());
headers->AddHeader(
base::StringPrintf("%s: bytes %" PRId64 "-%" PRId64 "/%" PRId64,
- kRangeHeader,
- byte_range_.first_byte_position(),
- byte_range_.last_byte_position(),
- resource_size_));
- range_len = byte_range_.last_byte_position() -
- byte_range_.first_byte_position() + 1;
+ kRangeHeader, start, end, resource_size_));
} else {
// TODO(rvargas): Is it safe to change the protocol version?
headers->ReplaceStatusLine("HTTP/1.1 200 OK");
@@ -396,6 +416,7 @@ int PartialData::CacheRead(disk_cache::Entry* entry, IOBuffer* data,
int PartialData::CacheWrite(disk_cache::Entry* entry, IOBuffer* data,
int data_len, CompletionCallback* callback) {
+ DVLOG(3) << "To write: " << data_len;
if (sparse_entry_) {
return entry->WriteSparseData(current_range_start_, data, data_len,
callback);
@@ -409,6 +430,7 @@ int PartialData::CacheWrite(disk_cache::Entry* entry, IOBuffer* data,
}
void PartialData::OnCacheReadCompleted(int result) {
+ DVLOG(3) << "Read: " << result;
if (result > 0) {
current_range_start_ += result;
cached_min_len_ -= result;
diff --git a/net/http/partial_data.h b/net/http/partial_data.h
index 22e0c8b..45bef31 100644
--- a/net/http/partial_data.h
+++ b/net/http/partial_data.h
@@ -84,7 +84,9 @@ class PartialData {
bool ResponseHeadersOK(const HttpResponseHeaders* headers);
// Fixes the response headers to include the right content length and range.
- void FixResponseHeaders(HttpResponseHeaders* headers);
+ // |success| is the result of the whole request so if it's false, we'll change
+ // the result code to be 416.
+ void FixResponseHeaders(HttpResponseHeaders* headers, bool success);
// Fixes the content length that we want to store in the cache.
void FixContentLength(HttpResponseHeaders* headers);