Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: net/http/http_cache.cc

Issue 345019: Http cache: Allow multiple external validation headers.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | net/http/http_cache_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 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 #include "net/http/http_cache.h" 5 #include "net/http/http_cache.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 const char* related_response_header_name; 64 const char* related_response_header_name;
65 }; 65 };
66 66
67 static const ValidationHeaderInfo kValidationHeaders[] = { 67 static const ValidationHeaderInfo kValidationHeaders[] = {
68 { "if-modified-since", "last-modified" }, 68 { "if-modified-since", "last-modified" },
69 { "if-none-match", "etag" }, 69 { "if-none-match", "etag" },
70 }; 70 };
71 71
72 // Helper struct to pair a header name with its value, for 72 // Helper struct to pair a header name with its value, for
73 // headers used to validate cache entries. 73 // headers used to validate cache entries.
74 struct ValidationHeader { 74 struct ValidationHeaders {
75 enum {kInvalidIndex = -1}; 75 ValidationHeaders() : initialized(false) {}
76 76
77 ValidationHeader() : type_index(kInvalidIndex) {} 77 std::string values[ARRAYSIZE_UNSAFE(kValidationHeaders)];
78 78 bool initialized;
79 bool initialized() const {
80 return type_index != kInvalidIndex;
81 }
82
83 const ValidationHeaderInfo& type_info() {
84 DCHECK(initialized());
85 return kValidationHeaders[type_index];
86 }
87
88 // Index into |kValidationHeaders|.
89 int type_index;
90 std::string value;
91 }; 79 };
92 80
93 // If the request includes one of these request headers, then avoid reusing 81 // If the request includes one of these request headers, then avoid reusing
94 // our cached copy if any. 82 // our cached copy if any.
95 static const HeaderNameAndValue kForceFetchHeaders[] = { 83 static const HeaderNameAndValue kForceFetchHeaders[] = {
96 { "cache-control", "no-cache" }, 84 { "cache-control", "no-cache" },
97 { "pragma", "no-cache" }, 85 { "pragma", "no-cache" },
98 { NULL, NULL } 86 { NULL, NULL }
99 }; 87 };
100 88
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 // Called to signal completion of the cache's WriteData method: 352 // Called to signal completion of the cache's WriteData method:
365 void OnCacheWriteCompleted(int result); 353 void OnCacheWriteCompleted(int result);
366 354
367 // Called to signal completion of the cache entry's ReadyForSparseIO method: 355 // Called to signal completion of the cache entry's ReadyForSparseIO method:
368 void OnCacheEntryReady(int result); 356 void OnCacheEntryReady(int result);
369 357
370 scoped_refptr<LoadLog> load_log_; 358 scoped_refptr<LoadLog> load_log_;
371 const HttpRequestInfo* request_; 359 const HttpRequestInfo* request_;
372 scoped_ptr<HttpRequestInfo> custom_request_; 360 scoped_ptr<HttpRequestInfo> custom_request_;
373 // If extra_headers specified a "if-modified-since" or "if-none-match", 361 // If extra_headers specified a "if-modified-since" or "if-none-match",
374 // |external_validation_| contains the value of that header. 362 // |external_validation_| contains the value of those headers.
375 ValidationHeader external_validation_; 363 ValidationHeaders external_validation_;
376 base::WeakPtr<HttpCache> cache_; 364 base::WeakPtr<HttpCache> cache_;
377 HttpCache::ActiveEntry* entry_; 365 HttpCache::ActiveEntry* entry_;
378 scoped_ptr<HttpTransaction> network_trans_; 366 scoped_ptr<HttpTransaction> network_trans_;
379 CompletionCallback* callback_; // Consumer's callback. 367 CompletionCallback* callback_; // Consumer's callback.
380 HttpResponseInfo response_; 368 HttpResponseInfo response_;
381 HttpResponseInfo auth_response_; 369 HttpResponseInfo auth_response_;
382 std::string cache_key_; 370 std::string cache_key_;
383 Mode mode_; 371 Mode mode_;
384 bool reading_; // We are already reading. 372 bool reading_; // We are already reading.
385 bool invalid_range_; // We may bypass the cache for this request. 373 bool invalid_range_; // We may bypass the cache for this request.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 // requested cache access mode 439 // requested cache access mode
452 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { 440 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
453 mode_ = READ; 441 mode_ = READ;
454 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { 442 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
455 mode_ = WRITE; 443 mode_ = WRITE;
456 } else { 444 } else {
457 mode_ = READ_WRITE; 445 mode_ = READ_WRITE;
458 } 446 }
459 447
460 // Downgrade to UPDATE if the request has been externally conditionalized. 448 // Downgrade to UPDATE if the request has been externally conditionalized.
461 if (external_validation_.initialized()) { 449 if (external_validation_.initialized) {
462 if (mode_ & WRITE) { 450 if (mode_ & WRITE) {
463 // Strip off the READ_DATA bit (and maybe add back a READ_META bit 451 // Strip off the READ_DATA bit (and maybe add back a READ_META bit
464 // in case READ was off). 452 // in case READ was off).
465 mode_ = UPDATE; 453 mode_ = UPDATE;
466 } else { 454 } else {
467 mode_ = NONE; 455 mode_ = NONE;
468 } 456 }
469 } 457 }
470 } 458 }
471 459
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 const HeaderNameAndValue* search; 780 const HeaderNameAndValue* search;
793 int load_flag; 781 int load_flag;
794 } kSpecialHeaders[] = { 782 } kSpecialHeaders[] = {
795 { kPassThroughHeaders, LOAD_DISABLE_CACHE }, 783 { kPassThroughHeaders, LOAD_DISABLE_CACHE },
796 { kForceFetchHeaders, LOAD_BYPASS_CACHE }, 784 { kForceFetchHeaders, LOAD_BYPASS_CACHE },
797 { kForceValidateHeaders, LOAD_VALIDATE_CACHE }, 785 { kForceValidateHeaders, LOAD_VALIDATE_CACHE },
798 }; 786 };
799 787
800 std::string new_extra_headers; 788 std::string new_extra_headers;
801 bool range_found = false; 789 bool range_found = false;
802 790 bool external_validation_error = false;
803 // We will scan through the headers to see if any "if-modified-since" or
804 // "if-none-match" request headers were specified as part of extra_headers.
805 int num_validation_headers = 0;
806 ValidationHeader validation_header;
807 791
808 // scan request headers to see if we have any that would impact our load flags 792 // scan request headers to see if we have any that would impact our load flags
809 HttpUtil::HeadersIterator it(request_->extra_headers.begin(), 793 HttpUtil::HeadersIterator it(request_->extra_headers.begin(),
810 request_->extra_headers.end(), 794 request_->extra_headers.end(),
811 "\r\n"); 795 "\r\n");
812 while (it.GetNext()) { 796 while (it.GetNext()) {
813 if (!LowerCaseEqualsASCII(it.name(), "range")) { 797 if (!LowerCaseEqualsASCII(it.name(), "range")) {
814 new_extra_headers.append(it.name_begin(), it.values_end()); 798 new_extra_headers.append(it.name_begin(), it.values_end());
815 new_extra_headers.append("\r\n"); 799 new_extra_headers.append("\r\n");
816 } else { 800 } else {
(...skipping 10 matching lines...) Expand all
827 break; 811 break;
828 } 812 }
829 } 813 }
830 814
831 // Check for conditionalization headers which may correspond with a 815 // Check for conditionalization headers which may correspond with a
832 // cache validation request. 816 // cache validation request.
833 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); ++i) { 817 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); ++i) {
834 const ValidationHeaderInfo& info = kValidationHeaders[i]; 818 const ValidationHeaderInfo& info = kValidationHeaders[i];
835 if (LowerCaseEqualsASCII(it.name_begin(), it.name_end(), 819 if (LowerCaseEqualsASCII(it.name_begin(), it.name_end(),
836 info.request_header_name)) { 820 info.request_header_name)) {
837 num_validation_headers++; 821 if (!external_validation_.values[i].empty() || it.values().empty())
838 validation_header.type_index = i; 822 external_validation_error = true;
839 validation_header.value = it.values(); 823 external_validation_.values[i] = it.values();
824 external_validation_.initialized = true;
840 break; 825 break;
841 } 826 }
842 } 827 }
843 } 828 }
844 829
845 // We don't support ranges and validation headers. 830 // We don't support ranges and validation headers.
846 if (range_found && num_validation_headers) { 831 if (range_found && external_validation_.initialized) {
847 LOG(WARNING) << "Byte ranges AND validation headers found."; 832 LOG(WARNING) << "Byte ranges AND validation headers found.";
848 effective_load_flags_ |= LOAD_DISABLE_CACHE; 833 effective_load_flags_ |= LOAD_DISABLE_CACHE;
849 } 834 }
850 835
836 // If there is more than one validation header, we can't treat this request as
837 // a cache validation, since we don't know for sure which header the server
838 // will give us a response for (and they could be contradictory).
839 if (external_validation_error) {
840 LOG(WARNING) << "Multiple or malformed validation headers found.";
841 effective_load_flags_ |= LOAD_DISABLE_CACHE;
842 }
843
851 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) { 844 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
852 partial_.reset(new PartialData); 845 partial_.reset(new PartialData);
853 if (partial_->Init(request_->extra_headers, new_extra_headers)) { 846 if (partial_->Init(request_->extra_headers, new_extra_headers)) {
854 // We will be modifying the actual range requested to the server, so 847 // We will be modifying the actual range requested to the server, so
855 // let's remove the header here. 848 // let's remove the header here.
856 custom_request_.reset(new HttpRequestInfo(*request_)); 849 custom_request_.reset(new HttpRequestInfo(*request_));
857 request_ = custom_request_.get(); 850 request_ = custom_request_.get();
858 custom_request_->extra_headers = new_extra_headers; 851 custom_request_->extra_headers = new_extra_headers;
859 } else { 852 } else {
860 // The range is invalid or we cannot handle it properly. 853 // The range is invalid or we cannot handle it properly.
861 LOG(WARNING) << "Invalid byte range found."; 854 LOG(WARNING) << "Invalid byte range found.";
862 effective_load_flags_ |= LOAD_DISABLE_CACHE; 855 effective_load_flags_ |= LOAD_DISABLE_CACHE;
863 partial_.reset(NULL); 856 partial_.reset(NULL);
864 } 857 }
865 } 858 }
866
867 // If there is more than one validation header, we can't treat this request as
868 // a cache validation, since we don't know for sure which header the server
869 // will give us a response for (and they could be contradictory).
870 if (num_validation_headers > 1) {
871 LOG(WARNING) << "Multiple validation headers found.";
872 effective_load_flags_ |= LOAD_DISABLE_CACHE;
873 }
874
875 if (num_validation_headers == 1) {
876 DCHECK(validation_header.initialized());
877 external_validation_ = validation_header;
878 }
879 } 859 }
880 860
881 bool HttpCache::Transaction::ShouldPassThrough() { 861 bool HttpCache::Transaction::ShouldPassThrough() {
882 // We may have a null disk_cache if there is an error we cannot recover from, 862 // We may have a null disk_cache if there is an error we cannot recover from,
883 // like not enough disk space, or sharing violations. 863 // like not enough disk space, or sharing violations.
884 if (!cache_->disk_cache()) 864 if (!cache_->disk_cache())
885 return true; 865 return true;
886 866
887 // When using the record/playback modes, we always use the cache 867 // When using the record/playback modes, we always use the cache
888 // and we never pass through. 868 // and we never pass through.
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 if (rv < 0 && rv != ERR_IO_PENDING) 1002 if (rv < 0 && rv != ERR_IO_PENDING)
1023 HandleResult(rv); 1003 HandleResult(rv);
1024 return rv; 1004 return rv;
1025 } 1005 }
1026 1006
1027 return BeginCacheValidation(); 1007 return BeginCacheValidation();
1028 } 1008 }
1029 1009
1030 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { 1010 int HttpCache::Transaction::BeginExternallyConditionalizedRequest() {
1031 DCHECK_EQ(UPDATE, mode_); 1011 DCHECK_EQ(UPDATE, mode_);
1032 DCHECK(external_validation_.initialized()); 1012 DCHECK(external_validation_.initialized);
1033 1013
1034 // Read the cached response. 1014 // Read the cached response.
1035 int rv = ReadResponseInfoFromEntry(); 1015 int rv = ReadResponseInfoFromEntry();
1036 if (rv != OK) { 1016 if (rv != OK) {
1037 DCHECK(rv != ERR_IO_PENDING); 1017 DCHECK(rv != ERR_IO_PENDING);
1038 return HandleResult(rv); 1018 return HandleResult(rv);
1039 } 1019 }
1040 1020
1041 // Retrieve either the cached response's "etag" or "last-modified" header, 1021 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidationHeaders); i++) {
1042 // depending on which is applicable for the caller's request header. 1022 if (external_validation_.values[i].empty())
1043 std::string validator; 1023 continue;
1044 response_.headers->EnumerateHeader( 1024 // Retrieve either the cached response's "etag" or "last-modified" header.
1045 NULL, 1025 std::string validator;
1046 external_validation_.type_info().related_response_header_name, 1026 response_.headers->EnumerateHeader(
1047 &validator); 1027 NULL,
1028 kValidationHeaders[i].related_response_header_name,
1029 &validator);
1048 1030
1049 if (response_.headers->response_code() != 200 || truncated_ || 1031 if (response_.headers->response_code() != 200 || truncated_ ||
1050 validator.empty() || validator != external_validation_.value) { 1032 validator.empty() || validator != external_validation_.values[i]) {
1051 // The externally conditionalized request is not a validation request 1033 // The externally conditionalized request is not a validation request
1052 // for our existing cache entry. Proceed with caching disabled. 1034 // for our existing cache entry. Proceed with caching disabled.
1053 DoneWritingToEntry(true); 1035 DoneWritingToEntry(true);
1036 }
1054 } 1037 }
1055 1038
1056 return BeginNetworkRequest(); 1039 return BeginNetworkRequest();
1057 } 1040 }
1058 1041
1059 int HttpCache::Transaction::BeginNetworkRequest() { 1042 int HttpCache::Transaction::BeginNetworkRequest() {
1060 DCHECK(mode_ & WRITE || mode_ == NONE); 1043 DCHECK(mode_ & WRITE || mode_ == NONE);
1061 DCHECK(!network_trans_.get()); 1044 DCHECK(!network_trans_.get());
1062 1045
1063 // Create a network transaction. 1046 // Create a network transaction.
(...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after
2114 static_cast<net::HttpNetworkLayer*>(network_layer_.get()); 2097 static_cast<net::HttpNetworkLayer*>(network_layer_.get());
2115 HttpNetworkSession* session = network->GetSession(); 2098 HttpNetworkSession* session = network->GetSession();
2116 if (session) { 2099 if (session) {
2117 session->tcp_socket_pool()->CloseIdleSockets(); 2100 session->tcp_socket_pool()->CloseIdleSockets();
2118 } 2101 }
2119 } 2102 }
2120 2103
2121 //----------------------------------------------------------------------------- 2104 //-----------------------------------------------------------------------------
2122 2105
2123 } // namespace net 2106 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/http/http_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698