public void SetUp() { _cacheResponse = new CacheResponse(new Response().OK()); _cachedUtcTimestamp = new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Utc); _expiresUtcTimestamp = new DateTime(2013, 01, 01, 0, 0, 0, DateTimeKind.Utc); _cacheItem = new CacheItem(_cacheResponse, _cachedUtcTimestamp, _expiresUtcTimestamp); }
public void Must_throw_exception() { var cacheResponse = new CacheResponse(new Response().OK()); Assert.That(() => new CacheItem(cacheResponse, new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Local), new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Utc)), Throws.InstanceOf<ArgumentException>()); Assert.That(() => new CacheItem(cacheResponse, new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Utc), new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Local)), Throws.InstanceOf<ArgumentException>()); }
public void Must_throw_exception() { var cacheResponse = new CacheResponse(Response.OK()); Assert.Throws<ArgumentException>(() => new CacheItem(cacheResponse, new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Local), new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Utc))); Assert.Throws<ArgumentException>(() => new CacheItem(cacheResponse, new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Utc), new DateTime(2012, 01, 01, 0, 0, 0, DateTimeKind.Local))); }
public ResponseHandlerResult HandleResponse(HttpRequestBase httpRequest, HttpResponseBase httpResponse, IResponse suggestedResponse, ICache cache, string cacheKey) { httpRequest.ThrowIfNull("httpRequest"); httpResponse.ThrowIfNull("httpResponse"); suggestedResponse.ThrowIfNull("suggestedResponse"); var cacheResponse = new CacheResponse(suggestedResponse); cacheResponse.WriteResponse(httpResponse); return ResponseHandlerResult.ResponseWritten(); }
public void Add(string key, CacheResponse response, DateTime expirationUtcTimestamp) { key.ThrowIfNull("key"); response.ThrowIfNull("response"); if (expirationUtcTimestamp.Kind != DateTimeKind.Utc) { throw new ArgumentException("Expiration must be UTC.", "expirationUtcTimestamp"); } var cacheItem = new CacheItem(response, _systemClock.UtcDateTime); _httpRuntime.Cache.Insert(key, cacheItem, null, expirationUtcTimestamp, Cache.NoSlidingExpiration); }
public void SetUp() { Response response = Response .OK() .ApplicationJson() .Charset("utf-8") .Content("content") .ContentEncoding(Encoding.ASCII) .Cookie(new HttpCookie("name", "value")) .Header("field", "value") .HeaderEncoding(Encoding.UTF8); response.CachePolicy.ETag("etag"); _cacheResponse = new CacheResponse(response); }
public CacheItem(CacheResponse response, DateTime cachedUtcTimestamp, DateTime? expiresUtcTimestamp = null) { response.ThrowIfNull("response"); if (cachedUtcTimestamp.Kind != DateTimeKind.Utc) { throw new ArgumentException("Cached timestamp must be UTC.", "cachedUtcTimestamp"); } if (expiresUtcTimestamp != null && expiresUtcTimestamp.Value.Kind != DateTimeKind.Utc) { throw new ArgumentException("Absolute expiration timestamp must be UTC.", "expiresUtcTimestamp"); } _response = response; _cachedUtcTimestamp = cachedUtcTimestamp; _expiresUtcTimestamp = expiresUtcTimestamp; }
public CacheItem(CacheResponse response, DateTime cachedUtcTimestamp, DateTime?expiresUtcTimestamp = null) { response.ThrowIfNull("response"); if (cachedUtcTimestamp.Kind != DateTimeKind.Utc) { throw new ArgumentException("Cached timestamp must be UTC.", "cachedUtcTimestamp"); } if (expiresUtcTimestamp != null && expiresUtcTimestamp.Value.Kind != DateTimeKind.Utc) { throw new ArgumentException("Absolute expiration timestamp must be UTC.", "expiresUtcTimestamp"); } _response = response; _cachedUtcTimestamp = cachedUtcTimestamp; _expiresUtcTimestamp = expiresUtcTimestamp; }
public void SetUp() { _httpCachePolicyBase = MockRepository.GenerateMock<HttpCachePolicyBase>(); _httpResponseBase = MockRepository.GenerateMock<HttpResponseBase>(); _httpResponseBase.Stub(arg => arg.Cache).Return(_httpCachePolicyBase); _httpResponseBase.Stub(arg => arg.Cookies).Return(new HttpCookieCollection()); _httpResponseBase.Stub(arg => arg.Headers).Return(new NameValueCollection()); Response response = new Response() .OK() .ApplicationJson() .Charset("utf-8") .Content("content") .ContentEncoding(Encoding.ASCII) .Cookie(new HttpCookie("name", "value")) .Header("field", "value") .HeaderEncoding(Encoding.UTF8); response.CachePolicy.NoClientCaching(); _cacheResponse = new CacheResponse(response); _cacheResponse.WriteResponseAsync(_httpResponseBase).Wait(); }
public async Task<ResponseHandlerResult> HandleResponseAsync(HttpContextBase context, IResponse suggestedResponse, ICache cache, string cacheKey) { context.ThrowIfNull("context"); suggestedResponse.ThrowIfNull("suggestedResponse"); if (!suggestedResponse.CachePolicy.HasPolicy || cache == null || cacheKey == null) { return ResponseHandlerResult.ResponseNotHandled(); } CacheItem cacheItem = await cache.GetAsync(cacheKey); string responseETag = suggestedResponse.CachePolicy.ETag; #region If-Match precondition header IfMatchHeader[] ifMatchHeaders = IfMatchHeader.ParseMany(context.Request.Headers["If-Match"]).ToArray(); // Only consider If-Match headers if response status code is 2xx or 412 if (ifMatchHeaders.Any() && ((suggestedResponse.StatusCode.StatusCode >= 200 && suggestedResponse.StatusCode.StatusCode <= 299) || suggestedResponse.StatusCode.StatusCode == 412)) { // Return 412 if no If-Match header matches the response ETag // Return 412 if an "If-Match: *" header is present and the response has no ETag if (ifMatchHeaders.All(arg => arg.EntityTag.Value != responseETag) || (responseETag == null && ifMatchHeaders.Any(arg => arg.EntityTag.Value == "*"))) { return await WriteResponseAsync(context.Response, new Response().PreconditionFailed()); } } #endregion #region If-None-Match precondition header IfNoneMatchHeader[] ifNoneMatchHeaders = IfNoneMatchHeader.ParseMany(context.Request.Headers["If-None-Match"]).ToArray(); if (ifNoneMatchHeaders.Any()) { // Return 304 if an If-None-Match header matches the response ETag and the request method was GET or HEAD // Return 304 if an "If-None-Match: *" header is present, the response has an ETag and the request method was GET or HEAD // Return 412 if an "If-None-Match: *" header is present, the response has an ETag and the request method was not GET or HEAD if (ifNoneMatchHeaders.Any(arg => arg.EntityTag.Value == responseETag) || (ifNoneMatchHeaders.Any(arg => arg.EntityTag.Value == "*") && responseETag != null)) { if (String.Equals(context.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase) || String.Equals(context.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase)) { if (cacheItem != null) { cacheItem.Response.CachePolicy.Apply(context.Response.Cache); } else { suggestedResponse.CachePolicy.Apply(context.Response.Cache); } return await WriteResponseAsync(context.Response, new Response().NotModified()); } return await WriteResponseAsync(context.Response, new Response().PreconditionFailed()); } } #endregion #region If-Modified-Since precondition header IfModifiedSinceHeader ifModifiedSinceHeader = IfModifiedSinceHeader.Parse(context.Request.Headers["If-Modified-Since"]); bool validIfModifiedSinceHttpDate = ifModifiedSinceHeader != null && ifModifiedSinceHeader.HttpDate <= _systemClock.UtcDateTime; // Only consider an If-Modified-Since header if response status code is 200 and the HTTP-date is valid if (suggestedResponse.StatusCode.ParsedStatusCode == HttpStatusCode.OK && validIfModifiedSinceHttpDate) { // Return 304 if the response was cached before the HTTP-date if (cacheItem != null && cacheItem.CachedUtcTimestamp < ifModifiedSinceHeader.HttpDate) { return await WriteResponseAsync(context.Response, new Response().NotModified()); } } #endregion #region If-Unmodified-Since precondition header IfUnmodifiedSinceHeader ifUnmodifiedSinceHeader = IfUnmodifiedSinceHeader.Parse(context.Request.Headers["If-Unmodified-Since"]); bool validIfUnmodifiedSinceHttpDate = ifUnmodifiedSinceHeader != null && ifUnmodifiedSinceHeader.HttpDate <= _systemClock.UtcDateTime; // Only consider an If-Unmodified-Since header if response status code is 2xx or 412 and the HTTP-date is valid if (((suggestedResponse.StatusCode.StatusCode >= 200 && suggestedResponse.StatusCode.StatusCode <= 299) || suggestedResponse.StatusCode.StatusCode == 412) && validIfUnmodifiedSinceHttpDate) { // Return 412 if the previous response was removed from the cache or was cached again at a later time if (cacheItem == null || cacheItem.CachedUtcTimestamp >= ifUnmodifiedSinceHeader.HttpDate) { return await WriteResponseAsync(context.Response, new Response().PreconditionFailed()); } } #endregion #region No server caching // Do not cache the response when the response sends a non-cacheable status code, or when an Authorization header is present if (!_cacheableStatusCodes.Contains(suggestedResponse.StatusCode) || context.Request.Headers["Authorization"] != null) { return await WriteResponseAsync(context.Response, suggestedResponse); } CacheControlHeader cacheControlHeader = CacheControlHeader.Parse(context.Request.Headers["Cache-Control"]); // Do not cache the response if a "Cache-Control: no-cache" or "Cache-Control: no-store" header is present if (cacheControlHeader != null && (cacheControlHeader.NoCache || cacheControlHeader.NoStore)) { return await WriteResponseAsync(context.Response, suggestedResponse); } IEnumerable<PragmaHeader> pragmaHeader = PragmaHeader.ParseMany(context.Request.Headers["Pragma"]); // Do not cache the response if a "Pragma: no-cache" header is present if (pragmaHeader.Any(arg => String.Equals(arg.Name, "no-cache", StringComparison.OrdinalIgnoreCase))) { return await WriteResponseAsync(context.Response, suggestedResponse); } #endregion // Return 504 if the response has not been cached but the client is requesting to receive only a cached response if (cacheItem == null && cacheControlHeader != null && cacheControlHeader.OnlyIfCached) { return await WriteResponseAsync(context.Response, new Response().GatewayTimeout()); } if (cacheItem != null) { // Write the cached response if no Cache-Control header is present // Write the cached response if a "Cache-Control: max-age" header is validated // Write the cached response if a "Cache-Control: max-stale" header is validated // Write the cached response if a "Cache-Control: min-fresh" header is validated if (cacheControlHeader == null || _systemClock.UtcDateTime - cacheItem.CachedUtcTimestamp <= cacheControlHeader.MaxAge || cacheControlHeader.OnlyIfCached || cacheItem.ExpiresUtcTimestamp == null || _systemClock.UtcDateTime - cacheItem.ExpiresUtcTimestamp.Value <= cacheControlHeader.MaxStale || cacheItem.ExpiresUtcTimestamp.Value - _systemClock.UtcDateTime < cacheControlHeader.MinFresh) { return await WriteResponseInCacheAsync(context.Response, cacheItem); } } bool cacheOnServer = suggestedResponse.CachePolicy.AllowsServerCaching; var cacheResponse = new CacheResponse(suggestedResponse); if (cacheOnServer) { DateTime expirationUtcTimestamp = suggestedResponse.CachePolicy.ServerCacheExpirationUtcTimestamp != null ? suggestedResponse.CachePolicy.ServerCacheExpirationUtcTimestamp.Value : _systemClock.UtcDateTime + suggestedResponse.CachePolicy.ServerCacheMaxAge.Value; await cache.AddAsync(cacheKey, cacheResponse, expirationUtcTimestamp); } return await WriteResponseAsync(context.Response, cacheResponse); }
private static async Task<ResponseHandlerResult> WriteResponseAsync(HttpResponseBase httpResponse, CacheResponse cacheResponse) { await cacheResponse.WriteResponseAsync(httpResponse); return ResponseHandlerResult.ResponseWritten(); }
private static ResponseHandlerResult WriteResponse(HttpResponseBase httpResponse, CacheResponse cacheResponse) { cacheResponse.WriteResponse(httpResponse); return ResponseHandlerResult.ResponseWritten(); }
public Task AddAsync(string key, CacheResponse response, DateTime expirationUtcTimestamp) { return Task.Factory.Empty(); }
public void Add(string key, CacheResponse response, DateTime expirationUtcTimestamp) { }
public Task AddAsync(string key, CacheResponse response, DateTime expirationUtcTimestamp) { return(Task.Factory.Empty()); }