An implementation of ICachControlHeaderHandler that use the etag to check whether these is an exisisting cache data
Inheritance: ICachControlHeaderHandler
        /// <summary>
        /// Create required components to use Flatwhite cache for WebApi
        /// </summary>
        /// <param name="config"></param>
        /// <param name="flatwhiteConfig"></param>
        public static HttpConfiguration UseFlatwhiteCache(this HttpConfiguration config, FlatwhiteWebApiConfiguration flatwhiteConfig = null)
        {
            _fwConfig = flatwhiteConfig ?? new FlatwhiteWebApiConfiguration();
            Global.CacheStrategyProvider = new WebApiCacheStrategyProvider();
            Global.BackgroundTaskManager = new RegisteredTasks();

            var allHandlers = config.DependencyResolver
                .GetServices(typeof(ICachControlHeaderHandler))
                .OfType<ICachControlHeaderHandler>()
                .ToList();

            if (allHandlers.All(h => h.GetType() != typeof(EtagHeaderHandler)))
            {
                var cacheResponseBuilder = config.DependencyResolver.GetService(typeof(ICacheResponseBuilder)) as ICacheResponseBuilder
                                         ?? new CacheResponseBuilder();
                var etagHeaderHandler = new EtagHeaderHandler(cacheResponseBuilder);
                allHandlers.Add(etagHeaderHandler);
            }

            var handlerProvider = config.DependencyResolver.GetService(typeof(ICachControlHeaderHandlerProvider)) as ICachControlHeaderHandlerProvider
                                ?? new CachControlHeaderHandlerProvider();
            allHandlers.ForEach(h => handlerProvider.Register(h));

            config.MessageHandlers.Add(new CacheMessageHandler(handlerProvider));
            if (_fwConfig.EnableStatusController)
            {
                config.Routes.MapHttpRoute(
                    name: "_FlatwhiteStatus",
                    routeTemplate: "_flatwhite/{action}/{id}",
                    defaults: new {id = RouteParameter.Optional, controller = "FlatwhiteStatus"}
                    );
            }
            return config;
        }
Example #2
0
        /// <summary>
        /// Create required components to use Flatwhite cache for WebApi
        /// </summary>
        /// <param name="app"></param>
        /// <param name="config"></param>
        public static IAppBuilder UseFlatwhiteCache(this IAppBuilder app, HttpConfiguration config)
        {
            Global.CacheStrategyProvider = new WebApiCacheStrategyProvider();
            _dependencyResolverActivator = new WebApiDependencyResolverActivator(() => config.DependencyResolver);

            var allHandlers = config.DependencyResolver
                .GetServices(typeof (ICachControlHeaderHandler))
                .OfType<ICachControlHeaderHandler>()
                .ToList();

            if (allHandlers.All(h => h.GetType() != typeof (EtagHeaderHandler)))
            {
                var cacheResponseBuilder = config.DependencyResolver.GetService(typeof(ICacheResponseBuilder)) as ICacheResponseBuilder
                                         ?? new CacheResponseBuilder();
                var etagHeaderHandler = new EtagHeaderHandler(cacheResponseBuilder);
                allHandlers.Add(etagHeaderHandler);
            }

            var handlerProvider = config.DependencyResolver.GetService(typeof(ICachControlHeaderHandlerProvider)) as ICachControlHeaderHandlerProvider
                                ?? new CachControlHeaderHandlerProvider();
            allHandlers.ForEach(h => handlerProvider.Register(h));

            config.MessageHandlers.Add(new CacheMessageHandler(handlerProvider));
            return app;
        }
        public async Task Should_return_null_if_no_etag_in_request()
        {
            // Arrange
            var cacheControl = new CacheControlHeaderValue();
            var request = new HttpRequestMessage
            {
                Method = new HttpMethod("GET"),
                RequestUri = new Uri("http://localhost")
            };
            var builder = Substitute.For<ICacheResponseBuilder>();
            var handler = new EtagHeaderHandler(builder);
            
            // Action
            var response = await handler.HandleAsync(cacheControl, request, CancellationToken.None);

            Assert.IsNull(response);
        }
        public async Task Should_return_null_if_cache_item_not_found()
        {
            // Arrange
            var cacheControl = new CacheControlHeaderValue();
            var request = new HttpRequestMessage
            {
                Method = new HttpMethod("GET"),
                RequestUri = new Uri("http://localhost")
            };
            request.Headers.Add("If-None-Match", "\"fw-1000-HASHEDKEY-CHECKSUM\"");
            var builder = Substitute.For<ICacheResponseBuilder>();
            var handler = new EtagHeaderHandler(builder);

            // Action
            var response = await handler.HandleAsync(cacheControl, request, CancellationToken.None);

            Assert.IsNull(response);
        }
        public async Task Should_return_new_etag_if_cache_item_found_but_doesnt_match_checksum(string cacheChecksum, HttpStatusCode resultCode)
        {
            // Arrange
            
            var cacheControl = new CacheControlHeaderValue
            {
                MaxStale = true,
                MaxStaleLimit = TimeSpan.FromSeconds(15),
                MinFresh = TimeSpan.FromSeconds(20)
            };

            var oldCacheItem = new WebApiCacheItem
            {
                CreatedTime = DateTime.UtcNow.AddSeconds(-11),
                MaxAge = 10,
                StaleWhileRevalidate = 5,
                IgnoreRevalidationRequest = true,
                ResponseCharSet = "UTF8",
                ResponseMediaType = "text/json",
                Content = new byte[0],
                Key = "fw-0-HASHEDKEY",
                Checksum = cacheChecksum
            };

            var request = new HttpRequestMessage
            {
                Method = new HttpMethod("GET"),
                RequestUri = new Uri("http://localhost")
            };

            request.Headers.Add("If-None-Match", "\"fw-0-HASHEDKEY-OLDCHECKSUM\"");
            var builder = new CacheResponseBuilder();
            var handler = new EtagHeaderHandler(builder);
            await Global.CacheStoreProvider.GetAsyncCacheStore().SetAsync("fw-0-HASHEDKEY", oldCacheItem, DateTimeOffset.Now.AddDays(1)).ConfigureAwait(false);


            // Action
            Global.Cache.PhoenixFireCage["fw-0-HASHEDKEY"] = new WebApiPhoenix(NSubstitute.Substitute.For<_IInvocation>(), new CacheInfo(), oldCacheItem, request);
            var response = await handler.HandleAsync(cacheControl, request, CancellationToken.None).ConfigureAwait(false);

            Assert.AreEqual(resultCode, response.StatusCode);
            if (resultCode == HttpStatusCode.OK)
            {
                Assert.AreEqual($"\"fw-0-HASHEDKEY-{cacheChecksum}\"", response.Headers.ETag.Tag);
            }
            else
            {
                Assert.IsNull(response.Headers.ETag);
            }
        }