Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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?

share|improve this question
    
Are you using custom error pages? –  Justin Niessner Jan 5 '12 at 16:26
    
@Justin - Nope, not in this case –  Nick Craver Jan 5 '12 at 16:37
    
IIS 7.0 doesn't send Max-Age on 40* for me. I'm not sure if its a discrepancy between IIS versions though. –  David Murdoch Jan 5 '12 at 16:58
    
Also, how does one force static content to send a 500 error code? –  David Murdoch Jan 5 '12 at 17:00
1  
@DavidMurdoch for example, we're seeing 406 responses sent with cache control headers when users request javascript, but the client only accepts image MIME types. Proxies are respecting this caching directive (as they should, by the spec) and other users are unable to download the script. –  Jarrod Dixon Jan 5 '12 at 22:39

1 Answer 1

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>
share|improve this answer
    
We can reproduce your findings using requests to localhost - have you tried doing the same tests from a remote machine? –  Geoff Dalgas Jan 6 '12 at 22:32
    
Yes, I did. 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 6 '12 at 22:57
    
The error embedded in that response exposes some somewhat risky information - see here. It appears that your server believes all requests were issued locally - see: iis.net/ConfigReference/system.webServer/httpErrors If you enable CustomErrors via: <httpErrors errorMode="Custom" /> you will see the same issue we are having @David –  Geoff Dalgas Jan 8 '12 at 20:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.