Reputation: 17554
I'm doing some close to the metal HTTP tangling with Owin. I have a owin middleware that outputs javascripts. It looks like this (relevant parts)
public override Task Invoke(IOwinContext context)
{
var response = context.Response;
response.ContentType = "application/javascript";
response.StatusCode = 200;
if (ClientCached(context.Request, scriptBuildDate))
{
response.StatusCode = 304;
response.Headers["Content-Length"] = "0";
response.Body.Close();
response.Body = Stream.Null;
return Task.FromResult<Object>(null);
}
response.Headers["Last-Modified"] = scriptBuildDate.ToUniversalTime().ToString("r");
return response.WriteAsync(js);
}
private bool ClientCached(IOwinRequest request, DateTime contentModified)
{
string header = request.Headers["If-Modified-Since"];
if (header != null)
{
DateTime isModifiedSince;
if (DateTime.TryParse(header, out isModifiedSince))
{
return isModifiedSince >= contentModified;
}
}
return false;
}
It will output 200 if its not client cached and add a Last-Modified date to the header, if its client cached it will output 304 "Not modified".
The problem is that the client will not call the url again unless they are doing a hard F5 in the browser. My understanding of Last modified caching is that it should call each time to check if the content has been modified?
Update:
F5 and ctrl+F5 will call server, opening site in new tab or restarting browser will call server, typing the address in same tab will not call server. If-Modified-Since
only cleared when doing Ctrl+F5 which means it can be used to return 304 correctly when content not modified
F5 and ctrl+F5 will call server, opening site in new tab will not call server, typing the address in same tab will not call server. If-Modified-Since
cleared when doing Ctrl+F5 OR when restarting browser
Will call server for every action If-Modified-Since
only cleared when doing Ctrl+F5
If-Modified-Since
cleared for both restarting browser and Ctrl+F5Conclusion
Looks like no-cache
is might better if you want to be sure it calls to check for 304
each time
Upvotes: 2
Views: 3160
Reputation: 24567
From the HTTP/1.1 spec (RFC2616, my emphasis):
13.2.2 Heuristic Expiration
Since origin servers do not always provide explicit expiration times, HTTP caches typically assign heuristic expiration times, employing algorithms that use other header values (such as the Last-Modified time) to estimate a plausible expiration time. The HTTP/1.1 specification does not provide specific algorithms, but does impose worst-case constraints on their results. Since heuristic expiration times might compromise semantic transparency, they ought to used cautiously, and we encourage origin servers to provide explicit expiration times as much as possible.
Providing a Last-Modified
header is not equivalent to asking user agents to check for updates every time they need a resource from your server.
Ideally, you should add an Expires
header whenever possible. However, adding the header Cache-Control: must-revalidate
should help.
Upvotes: 1