Ejemplo n.º 1
0
			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);
			}
Ejemplo n.º 2
0
			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>());
			}
Ejemplo n.º 3
0
            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();
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
            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);
            }
Ejemplo n.º 7
0
        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;
        }
Ejemplo n.º 8
0
        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;
        }
Ejemplo n.º 9
0
			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();
			}
Ejemplo n.º 10
0
		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);
		}
Ejemplo n.º 11
0
		private static async Task<ResponseHandlerResult> WriteResponseAsync(HttpResponseBase httpResponse, CacheResponse cacheResponse)
		{
			await cacheResponse.WriteResponseAsync(httpResponse);

			return ResponseHandlerResult.ResponseWritten();
		}
Ejemplo n.º 12
0
        private static ResponseHandlerResult WriteResponse(HttpResponseBase httpResponse, CacheResponse cacheResponse)
        {
            cacheResponse.WriteResponse(httpResponse);

            return ResponseHandlerResult.ResponseWritten();
        }
Ejemplo n.º 13
0
 public Task AddAsync(string key, CacheResponse response, DateTime expirationUtcTimestamp)
 {
     return Task.Factory.Empty();
 }
Ejemplo n.º 14
0
 public void Add(string key, CacheResponse response, DateTime expirationUtcTimestamp)
 {
 }
Ejemplo n.º 15
0
 public Task AddAsync(string key, CacheResponse response, DateTime expirationUtcTimestamp)
 {
     return(Task.Factory.Empty());
 }