diff --git a/src/WebApi.OutputCache.Core/Constants.cs b/src/WebApi.OutputCache.Core/Constants.cs
index 139b0b7..8553bcd 100644
--- a/src/WebApi.OutputCache.Core/Constants.cs
+++ b/src/WebApi.OutputCache.Core/Constants.cs
@@ -5,5 +5,7 @@ public sealed class Constants
public const string ContentTypeKey = ":response-ct";
public const string EtagKey = ":response-etag";
public const string GenerationTimestampKey = ":response-generationtimestamp";
+ public const string CustomHeaders = ":custom-headers";
+ public const string CustomContentHeaders = ":custom-content-headers";
}
}
diff --git a/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs b/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs
index f995dc9..fc79e71 100644
--- a/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs
+++ b/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
@@ -81,6 +82,11 @@ public int SharedTimeSpan
///
public Type CacheKeyGenerator { get; set; }
+ ///
+ /// Comma seperated list of HTTP headers to cache
+ ///
+ public string IncludeCustomHeaders { get; set; }
+
///
/// If set to something else than an empty string, this value will always be used for the Content-Type header, regardless of content negotiation.
///
@@ -185,6 +191,9 @@ public override void OnActionExecuting(HttpActionContext actionContext)
if (!_webApiCache.Contains(cachekey)) return;
+ var responseHeaders = _webApiCache.Get>>(cachekey + Constants.CustomHeaders);
+ var responseContentHeaders = _webApiCache.Get>>(cachekey + Constants.CustomContentHeaders);
+
if (actionContext.Request.Headers.IfNoneMatch != null)
{
var etag = _webApiCache.Get(cachekey + Constants.EtagKey);
@@ -194,7 +203,8 @@ public override void OnActionExecuting(HttpActionContext actionContext)
{
var time = CacheTimeQuery.Execute(DateTime.Now);
var quickResponse = actionContext.Request.CreateResponse(HttpStatusCode.NotModified);
-
+ if (responseHeaders != null) AddCustomCachedHeaders(quickResponse, responseHeaders, responseContentHeaders);
+
SetEtag(quickResponse, etag);
ApplyCacheHeaders(quickResponse, time);
actionContext.Response = quickResponse;
@@ -225,6 +235,8 @@ public override void OnActionExecuting(HttpActionContext actionContext)
var responseEtag = _webApiCache.Get(cachekey + Constants.EtagKey);
if (responseEtag != null) SetEtag(actionContext.Response, responseEtag);
+ if (responseHeaders != null) AddCustomCachedHeaders(actionContext.Response, responseHeaders, responseContentHeaders);
+
var cacheTime = CacheTimeQuery.Execute(DateTime.Now);
ApplyCacheHeaders(actionContext.Response, cacheTime, contentGenerationTimestamp);
}
@@ -275,10 +287,27 @@ public override async Task OnActionExecutedAsync(HttpActionExecutedContext actio
etag,
cacheTime.AbsoluteExpiration, baseKey);
-
_webApiCache.Add(cachekey + Constants.GenerationTimestampKey,
actionExecutionTimestamp.ToString(),
cacheTime.AbsoluteExpiration, baseKey);
+
+ if (!String.IsNullOrEmpty(IncludeCustomHeaders))
+ {
+ // convert to dictionary of lists to ensure thread safety if implementation of IEnumerable is changed
+ var headers = actionExecutedContext.Response.Headers.Where(h => IncludeCustomHeaders.Contains(h.Key))
+ .ToDictionary(x => x.Key, x => x.Value.ToList());
+
+ var contentHeaders = actionExecutedContext.Response.Content.Headers.Where(h => IncludeCustomHeaders.Contains(h.Key))
+ .ToDictionary(x => x.Key, x => x.Value.ToList());
+
+ _webApiCache.Add(cachekey + Constants.CustomHeaders,
+ headers,
+ cacheTime.AbsoluteExpiration, baseKey);
+
+ _webApiCache.Add(cachekey + Constants.CustomContentHeaders,
+ contentHeaders,
+ cacheTime.AbsoluteExpiration, baseKey);
+ }
}
}
}
@@ -311,6 +340,25 @@ protected virtual void ApplyCacheHeaders(HttpResponseMessage response, CacheTime
}
}
+ protected virtual void AddCustomCachedHeaders(HttpResponseMessage response, Dictionary> headers, Dictionary> contentHeaders)
+ {
+ foreach (var headerKey in headers.Keys)
+ {
+ foreach (var headerValue in headers[headerKey])
+ {
+ response.Headers.Add(headerKey, headerValue);
+ }
+ }
+
+ foreach (var headerKey in contentHeaders.Keys)
+ {
+ foreach (var headerValue in contentHeaders[headerKey])
+ {
+ response.Content.Headers.Add(headerKey, headerValue);
+ }
+ }
+ }
+
protected virtual string CreateEtag(HttpActionExecutedContext actionExecutedContext, string cachekey, CacheTime cacheTime)
{
return Guid.NewGuid().ToString();
diff --git a/test/WebApi.OutputCache.Core.Tests/WebApi.OutputCache.Core.Tests.csproj b/test/WebApi.OutputCache.Core.Tests/WebApi.OutputCache.Core.Tests.csproj
index 7739329..21df54c 100644
--- a/test/WebApi.OutputCache.Core.Tests/WebApi.OutputCache.Core.Tests.csproj
+++ b/test/WebApi.OutputCache.Core.Tests/WebApi.OutputCache.Core.Tests.csproj
@@ -56,6 +56,9 @@
WebApi.OutputCache.Core
+
+
+