I have an ASPX page that issues a Response.Redirect
that points to an image file.
The redirect response headers look like this:
HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Location: https://www.site.com/folder/file.jpg
Server: Microsoft-IIS/8.0
Date: Tue, 29 Apr 2014 08:29:58 GMT
Content-Length: 241
Is it possible to force the client and any proxy servers to cache this response for say 30 days? Should I do this with Cache-Control, ETags or both? If so, how?
I have figured this out and tested it. The following code adds the ETags and cache-control:
protected void Page_Load(object sender, EventArgs e)
{
var absoluteUrl = GetUrlFromDatabase(Request["fileId"]);
CacheResponse(absoluteUrl);
Response.Redirect(absoluteUrl);
}
private static void CacheResponse(string absoluteLocation)
{
// you need to clear the headers that ASP.NET automatically adds
HttpContext.Current.Response.ClearHeaders();
// now get the etag (hash the
var etag = GetETag(absoluteLocation);
// see if the etag matches what was sent
var requestedETag = HttpContext.Current.Request.Headers["If-None-Match"];
if (requestedETag == etag)
{
HttpContext.Current.Response.Status = "304 Not Modified";
HttpContext.Current.ApplicationInstance.CompleteRequest();
return;
}
// otherwise set cacheability and etag.
HttpContext.Current.Response.Cache.SetValidUntilExpires(true);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate);
HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.AddMonths(1));
HttpContext.Current.Response.Cache.SetLastModified(DateTime.UtcNow);
HttpContext.Current.Response.Cache.SetETag("\"" + etag + "\"");
}
private static string GetETag(string url)
{
var guid = StringToGuid(url);
var etag = new ShortGuid(guid); // see reference to ShortGuid below
return etag.Value.Replace("-", string.Empty);
}
private static Guid StringToGuid(string value)
{
// Create a new instance of the MD5CryptoServiceProvider object.
var md5Hasher = MD5.Create();
// Convert the input string to a byte array and compute the hash.
var data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(value));
return new Guid(data);
}
Reference: ShortGuid.
The initial HTTP response headers are now:
HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Expires: Thu, 29 May 2014 09:07:41 GMT
Last-Modified: Tue, 29 Apr 2014 09:07:41 GMT
ETag: "k28kbGNuxkWzP6gmLO2xQ"
Location: https://www.site.com/folder/file.jpg
Date: Tue, 29 Apr 2014 09:07:41 GMT
Content-Length: 241