diff --git a/src/WebApi.OutputCache.Core/Constants.cs b/src/WebApi.OutputCache.Core/Constants.cs index bc8885c..7a4cc9d 100644 --- a/src/WebApi.OutputCache.Core/Constants.cs +++ b/src/WebApi.OutputCache.Core/Constants.cs @@ -4,5 +4,6 @@ public sealed class Constants { public const string ContentTypeKey = ":response-ct"; public const string EtagKey = ":response-etag"; + public const string Headers = ":headers"; } } diff --git a/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs b/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs index 9742dc7..87e74eb 100644 --- a/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs +++ b/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs @@ -1,4 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; @@ -61,7 +63,12 @@ public class CacheOutputAttribute : FilterAttribute, IActionFilter /// Class used to generate caching keys /// public Type CacheKeyGenerator { get; set; } - + + /// + /// Comma seperated list of HTTP headers to cache + /// + public string HeadersToInclude { get; set; } + private MediaTypeHeaderValue _responseMediaType; // cache repository @@ -143,6 +150,8 @@ private void OnActionExecuting(HttpActionContext actionContext) if (!_webApiCache.Contains(cachekey)) return; + var responseHeaders = _webApiCache.Get(cachekey + Constants.Headers) as string; + if (actionContext.Request.Headers.IfNoneMatch != null) { var etag = _webApiCache.Get(cachekey + Constants.EtagKey) as string; @@ -152,6 +161,7 @@ private void OnActionExecuting(HttpActionContext actionContext) { var time = CacheTimeQuery.Execute(DateTime.Now); var quickResponse = actionContext.Request.CreateResponse(HttpStatusCode.NotModified); + if (responseHeaders != null) AddCachedHeaders(quickResponse, responseHeaders); ApplyCacheHeaders(quickResponse, time); actionContext.Response = quickResponse; return; @@ -171,6 +181,8 @@ private void OnActionExecuting(HttpActionContext actionContext) var responseEtag = _webApiCache.Get(cachekey + Constants.EtagKey) as string; if (responseEtag != null) SetEtag(actionContext.Response, responseEtag); + if (responseHeaders != null) AddCachedHeaders(actionContext.Response, responseHeaders); + var cacheTime = CacheTimeQuery.Execute(DateTime.Now); ApplyCacheHeaders(actionContext.Response, cacheTime); } @@ -215,6 +227,16 @@ private async Task OnActionExecuted(HttpActionExecutedContext actionExecutedCont _webApiCache.Add(cachekey + Constants.EtagKey, etag, cacheTime.AbsoluteExpiration, baseKey); + + + if (!String.IsNullOrEmpty(HeadersToInclude)) + { + string headersSerialized = JsonConvert.SerializeObject(actionExecutedContext.Response.Headers.Where(h => HeadersToInclude.Contains(h.Key))); + + _webApiCache.Add(cachekey + Constants.Headers, + headersSerialized, + cacheTime.AbsoluteExpiration, baseKey); + } } } } @@ -251,6 +273,19 @@ private static void SetEtag(HttpResponseMessage message, string etag) } } + protected virtual void AddCachedHeaders(HttpResponseMessage response, string headers) + { + var headersDeserialized = JsonConvert.DeserializeObject>>>(headers); + + foreach (var header in headersDeserialized) + { + foreach (var headerValue in header.Value) + { + response.Headers.Add(header.Key, headerValue); + } + } + } + Task IActionFilter.ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation) { if (actionContext == null)