I created a rudimentary test "suite".
When I run the tests with a minimal Web.config on IIS 7.0 (Integrated pipline mode on .NET 4.0) everything passes; the test file's Cache-Control
response header is set to private
when it's request's Accept
header doesn't match the file's Content-Type
.
This leads me to believe that you have some module interrupting IIS's static caching routine or IIS 7.0 and 7.5 differ here.
Here are the files I used (sans some-script.js
since its just an empty file):
Web.Config:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
</compilation>
</system.web>
<system.webServer>
<staticContent>
<!-- Set expire headers to 30 days for static content-->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
test.html:
<!doctype html>
<html>
<head>
<title>http://serverfault.com/questions/346975</title>
<style>
body > div
{
border:1px solid;
padding:10px;
margin:10px;
}
</style>
</head>
<body>
<div>
<h2>Request JS file with Accepts: accept/nothing</h2>
<b>Response Headers: </b>
<pre id="responseHeaders-1">loading&hellip</pre>
</div>
<div>
<h2>Request JS file with Accepts: */*</h2>
<b>Response Headers: </b>
<pre id="responseHeaders-2">loading&hellip</pre>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
var responseHeaders1 = $("#responseHeaders-1"),
responseHeaders2 = $("#responseHeaders-2"),
fetchScript = function (accepts, element, successMsg, errorMsg) {
var jXhr = $.ajax({
// fetch the resource "fresh" each time since we are testing the Cache-Control header and not caching itself
"url": "some-script.js?" + (new Date).getTime(),
"headers": {
"Accept" : accepts
},
"complete": function () {
var headers = jXhr.getAllResponseHeaders();
headers = headers.replace(/(Cache-Control:.+)/i, "<strong><u>$1</u></strong>");
element.html(headers);
},
"success": function () {
element.after("<div>" + successMsg + "</div>");
},
"error": function () {
element.after("<div>" + errorMsg + "</div>");
}
});
};
fetchScript("accept/nothing", responseHeaders1, "Uh, your server is sending stuff when the client doesn't accept it.", "Your server (probably) responded correctly.");
fetchScript("*/*", responseHeaders2, "Your server responded correctly.", "Something went wrong.");
</script>
</body>
</html>
You could use proxy_cache_bypass
.
proxy_cache_bypass $http_cache_control;
This will cause nginx to fetch a fresh copy of the document in the presence of the Cache-Control
header in the HTTP request from the client.
Note that the resulting response from the backend is still eligible for caching. If you want to disqualify it from being cached, use the same arguments with the proxy_no_cache
directive, too.
Source: http://wiki.nginx.org/HttpProxyModule#proxy_cache_bypass
If you specifically want to only bypass the cache when the client has Cache-Control: max-age=0
in the headers (e.g. to explicitly not support another variant, Cache-Control: no-cache
, which is actually supposedly a stronger preference for a fresh copy of the page than max-age=0
is), then you can use the following, which I won't recommend due to such limitation:
set $cc_ma 0;
if ($http_cache_control = "max-age=0") { # honour ⌘R, ignore ⇧⌘R (yes, bad idea!)
set $cc_ma 1;
}
proxy_cache_bypass $cc_ma;
BTW, there's also Pragma: no-cache
, which this obviously won't account for, although in my limited set of experiments, it's always accompanied by a Cache-Control: no-cache
, so, the original one-liner would probably do the best job.
As a note, SeaMonkey sends Cache-Control: max-age=0
when you click Reload or ⌘R, and Pragma: no-cache\r\nCache-Control: no-cache
when you Shift Reload or ⇧⌘R.
Best Answer
Should Use
instead of
but the latter does not throw an error, just doesn't work.