1 /*++ 2 Copyright (c) Microsoft Corporation 3 4 Module Name: 5 6 RequestCacheValidator.cs 7 8 Abstract: 9 10 The file specifies the contract for plugged cache validation logic. 11 12 Author: 13 14 Alexei Vopilov 21-Dec-2002 15 16 Revision History: 17 Aug 25 2003 - Moved into a separate file and implemented Whidbey M3 changes 18 Jan 25 2004 - Changed the visibility of the class from public to internal. 19 20 --*/ 21 namespace System.Net.Cache { 22 using System; 23 using System.Diagnostics; 24 using System.Text; 25 using System.IO; 26 using System.Collections.Specialized; 27 using System.Threading; 28 29 30 // 31 // We need Undefined value because sometime a cache entry does not provide a clue when it should expire 32 // not flags! 33 internal enum CacheFreshnessStatus 34 { 35 Undefined = 0, 36 Fresh = 1, 37 Stale = 2 38 } 39 40 // 41 // These are valus that can be returned from validation methods. 42 // Most validation methods can only return a subset of below values. 43 // 44 // not flags! 45 internal enum CacheValidationStatus 46 { 47 DoNotUseCache = 0, //Cache is not used for this request and response is not cached. 48 Fail = 1, //Fail this request (allows a protocol to generate own exception) 49 DoNotTakeFromCache = 2, //Don't used caches value for this request 50 RetryResponseFromCache = 3, //Retry cache lookup using changed cache key 51 RetryResponseFromServer = 4, //Retry this request as the result of invalid response received 52 ReturnCachedResponse = 5, //Return cached response to the application 53 CombineCachedAndServerResponse = 6, //Combine cached and live responses for this request 54 CacheResponse = 7, //Replace cache entry with received live response 55 UpdateResponseInformation = 8, //Update Metadata of cache entry using live response headers 56 RemoveFromCache = 9, //Remove cache entry referenced to by a cache key. 57 DoNotUpdateCache = 10, //Do nothing on cache update. 58 Continue = 11 //Proceed to the next protocol stage. 59 } 60 61 /// <summary> 62 /// <para> 63 /// This class reserves a pattern for all WebRequest related cache validators. 64 /// All exposed protected methods are virtual. 65 /// If a derived class method does not call the base method implementation, 66 /// then the base class context may not be updated so it's recommended suppressing the base 67 /// methods for all subsequent calls on this class. 68 /// </para> 69 /// </summary> 70 internal abstract class RequestCacheValidator { 71 72 internal WebRequest _Request; 73 internal WebResponse _Response; 74 internal Stream _CacheStream; 75 76 private RequestCachePolicy _Policy; 77 private Uri _Uri; 78 private String _CacheKey; 79 private RequestCacheEntry _CacheEntry; 80 private int _ResponseCount; 81 private CacheValidationStatus _ValidationStatus; 82 private CacheFreshnessStatus _CacheFreshnessStatus; 83 private long _CacheStreamOffset; 84 private long _CacheStreamLength; 85 86 private bool _StrictCacheErrors; 87 private TimeSpan _UnspecifiedMaxAge; 88 89 /*-------------- public members -------------*/ 90 CreateValidator()91 internal abstract RequestCacheValidator CreateValidator(); 92 93 /* 94 // Consider removing. 95 protected RequestCacheValidator(): this(false, TimeSpan.FromDays(1)) 96 { 97 } 98 */ 99 RequestCacheValidator(bool strictCacheErrors, TimeSpan unspecifiedMaxAge)100 protected RequestCacheValidator(bool strictCacheErrors, TimeSpan unspecifiedMaxAge) 101 { 102 _StrictCacheErrors = strictCacheErrors; 103 _UnspecifiedMaxAge = unspecifiedMaxAge; 104 _ValidationStatus = CacheValidationStatus.DoNotUseCache; 105 _CacheFreshnessStatus = CacheFreshnessStatus.Undefined; 106 } 107 108 //public 109 internal bool StrictCacheErrors 110 { 111 get {return _StrictCacheErrors;} 112 } 113 // 114 // This would help cache validation when the entry does 115 // not have any expiration mechanism defined. 116 //public 117 internal TimeSpan UnspecifiedMaxAge 118 { 119 get {return _UnspecifiedMaxAge;} 120 } 121 122 /*------------- get-only protected properties -------------*/ 123 protected internal Uri Uri {get {return _Uri;}} 124 protected internal WebRequest Request {get {return _Request; }} 125 protected internal WebResponse Response {get {return _Response; }} 126 protected internal RequestCachePolicy Policy {get {return _Policy; }} 127 protected internal int ResponseCount {get {return _ResponseCount;}} 128 protected internal CacheValidationStatus ValidationStatus {get {return _ValidationStatus;}} 129 protected internal CacheFreshnessStatus CacheFreshnessStatus {get {return _CacheFreshnessStatus;}} 130 protected internal RequestCacheEntry CacheEntry {get {return _CacheEntry;}} 131 132 /*------------- protected methods and settable protected properties ------------*/ 133 protected internal Stream CacheStream 134 { 135 get {return _CacheStream;} 136 set {_CacheStream = value;} 137 } 138 // 139 protected internal long CacheStreamOffset 140 { 141 get {return _CacheStreamOffset;} 142 set {_CacheStreamOffset = value;} 143 } 144 // 145 protected internal long CacheStreamLength 146 { 147 get {return _CacheStreamLength;} 148 set {_CacheStreamLength = value;} 149 } 150 // 151 protected internal string CacheKey 152 { 153 get {return _CacheKey;} 154 /* 155 // Consider removing. 156 set 157 { 158 // Security: Setting a cache key would allow reading an arbitrary cache location 159 //new RequestCachePermission(RequestCacheActions.CacheReadWrite, value).Demand(); 160 _CacheKey = value; 161 } 162 */ 163 } 164 // 165 /*-------------- protected virtual methods -------------*/ 166 // ValidateRequest()167 protected internal abstract CacheValidationStatus ValidateRequest(); 168 // ValidateFreshness()169 protected internal abstract CacheFreshnessStatus ValidateFreshness(); 170 // ValidateCache()171 protected internal abstract CacheValidationStatus ValidateCache(); 172 // ValidateResponse()173 protected internal abstract CacheValidationStatus ValidateResponse(); 174 // RevalidateCache()175 protected internal abstract CacheValidationStatus RevalidateCache(); 176 // UpdateCache()177 protected internal abstract CacheValidationStatus UpdateCache(); 178 // FailRequest(WebExceptionStatus webStatus)179 protected internal virtual void FailRequest(WebExceptionStatus webStatus) 180 { 181 if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_failing_request_with_exception, webStatus.ToString())); 182 if (webStatus == WebExceptionStatus.CacheEntryNotFound) 183 throw ExceptionHelper.CacheEntryNotFoundException; 184 else if (webStatus == WebExceptionStatus.RequestProhibitedByCachePolicy) 185 throw ExceptionHelper.RequestProhibitedByCachePolicyException; 186 187 throw new WebException(NetRes.GetWebStatusString("net_requestaborted", webStatus), webStatus); 188 } 189 190 /*-------------- internal members -------------*/ 191 // FetchRequest(Uri uri, WebRequest request)192 internal void FetchRequest(Uri uri, WebRequest request) 193 { 194 _Request = request; 195 _Policy = request.CachePolicy; 196 _Response = null; 197 _ResponseCount = 0; 198 _ValidationStatus = CacheValidationStatus.DoNotUseCache; 199 _CacheFreshnessStatus = CacheFreshnessStatus.Undefined; 200 _CacheStream = null; 201 _CacheStreamOffset = 0L; 202 _CacheStreamLength = 0L; 203 204 if (!uri.Equals(_Uri)) 205 { 206 // it's changed from previous call 207 _CacheKey = uri.GetParts(UriComponents.AbsoluteUri, UriFormat.Unescaped); 208 } 209 _Uri = uri; 210 } 211 // FetchCacheEntry(RequestCacheEntry fetchEntry)212 internal void FetchCacheEntry(RequestCacheEntry fetchEntry) 213 { 214 _CacheEntry = fetchEntry; 215 } 216 FetchResponse(WebResponse fetchResponse)217 internal void FetchResponse(WebResponse fetchResponse) 218 { 219 ++_ResponseCount; 220 _Response = fetchResponse; 221 } 222 SetFreshnessStatus(CacheFreshnessStatus status)223 internal void SetFreshnessStatus(CacheFreshnessStatus status) 224 { 225 _CacheFreshnessStatus = status; 226 } 227 SetValidationStatus(CacheValidationStatus status)228 internal void SetValidationStatus(CacheValidationStatus status) 229 { 230 _ValidationStatus = status; 231 } 232 } 233 234 } 235