10

I have some static content with cache control Max-Age headers attached to it so clients will cache the static content. However, IIS 7.5 still sends this header out when there are error responses advising the client to cache this.

The has the negative effect that some proxies will then cache that error response. I could Vary: Accept,Accept-Encoding but this doesn't really address the root problem of Max-Age going out on error responses.

The current relevant IIS web.config section is:

<configuration>
  <system.webServer>
    <staticContent>
      <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
    </staticContent>
  </system.webServer>
</configuration>

Is there a way so I can make it so we don't tell clients or proxies to cache 400/500 error codes?

Kyle Brandt
  • 83,619
  • 74
  • 305
  • 448

2 Answers2

2

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>
David Murdoch
  • 492
  • 6
  • 19
  • We can reproduce your findings using requests to localhost - have you tried doing the same tests from a remote machine? – Geoff Dalgas Jan 06 '12 at 22:32
  • Yes, I did. http://se.vervestudios.co/tests/se-test/test.html (note to people of the future, the previous link was for temporary testing purposes only and probably doesn't work anymore, sorry) – David Murdoch Jan 06 '12 at 22:57
  • The error embedded in that response exposes some somewhat risky information - see [here](http://i.stack.imgur.com/LyuR5.png). It appears that your server believes all requests were issued locally - see: http://www.iis.net/ConfigReference/system.webServer/httpErrors If you enable CustomErrors via: you will see the same issue we are having @David – Geoff Dalgas Jan 08 '12 at 20:42
0

you should specify what type of content you are going to cache. for instance you could cache Scripts, css,image ..etc. so use <location path ="Scripts"> tag before the <system.webServer> tag. so your web config looks like this.

 <location path ="Scripts">
    <system.webServer>
      <staticContent>
        <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="07:00:00" />
      </staticContent>
    </system.webServer>
  </location>
  <location path ="css">
    <system.webServer>
      <staticContent>
        <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="07:00:00" />
      </staticContent>
    </system.webServer>
 </location>