Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This particular issue is probably lurking in code that I've written. The gist of the fix is to ensure that Cache-Control: no-cache is explicitly set on anything you don't want cached.


It is a bug to ignore the max-age parameter that is presently widely used.


Also consider max-age=0


The stackoverflow post says that max-age=0 doesn't work for this particular case, but no-cache does.


If you've read the article, the issue is with unique POST requests coming from client-side. That kind of behavior is absolutely unacceptable.


> If you've read the article, the issue is with unique POST requests coming from client-side. That kind of behavior is absolutely unacceptable.

Maybe I'm missing something, but reading the StackOverflow discussion in the source link, it looks like the HTTP RFC actually allows this case:

> I suspect that Apple is taking advantage of this from the HTTP spec in section 9.5 about POST:

"Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource."


> Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields.

The response does not include a cache-control or expires header, as such the method is not cacheable. iOS is in violation with the specification if that's what iOS does and the above specification is the reference.


Indeed, this behavior may be compliant with the HTTP spec. From RFC 2616 §14.9.3:

> The expiration time of an entity MAY be specified by the origin server using the Expires header (see section 14.21). Alternatively, it MAY be specified using the max-age directive in a response. When the max-age cache-control directive is present in a cached response, the response is stale if its current age is greater than the age value given (in seconds) at the time of a new request for that resource. The max-age directive on a response implies that the response is cacheable (i.e., "public") unless some other, more restrictive cache directive is also present.

So, people were using "max-age=0" as a substitute for "don't cache", when the actual meaning is "don't cache for more than 0 seconds". The key here is:

1) You can just use "no-cache" in the "Cache-Control" header.

2) I always felt it was okay for caches to be "sloppy", to cache things too long if the software decides it's okay, as long as it's not extreme and as long as they're not caching things they're not supposed to cache.

3) Cache ages are integral seconds, so I'd expect "max-age=0" to mean that it expires when 1000 ms passes.

I've dealt with a few terrible problems involving the "Cache-Control" header, mostly with IE. And PDFs. And both at the same time.


RFC 2616 Section 14.9.1 states:

    14.9.1 What is Cacheable

    By default, a response is cacheable if the requirements of the
    request method, request header fields, and the response status
    indicate that it is cacheable.
Section 9.5 (for the POST request method):

    Responses to this method are not cacheable, unless the response
    includes appropriate Cache-Control or Expires header fields. However,
    the 303 (See Other) response can be used to direct the user agent to
    retrieve a cacheable resource.
Responses to the POST request method are not cacheable by default according to the spec.


I keep on seeing this get thrown around, that POST is not cacheable:

> unless the response includes appropriate Cache-Control

Forgive me if I'm dense, but doesn't this "unless" clause mean exactly that if you include a Cache-Control header, the POST will be cacheable unless the Cache-Control header says otherwise? The discussion is then really about whether max-age 0 means "for 1 second" or "never". I don't see why it would be necessary for it to mean "never" when there are two other ways you can get that behavior: by specifying "no-cache" or by simply omitting the header.

The entire discussion is about a developer who uses the following header:

    Cache-Control: max-age=0


What's broken is this: when you make a POST request to a server that omits the Cache-Control header, iOS 6 caches that response by default. That behavior violates the HTTP spec.


> The discussion is then really about whether max-age 0 means "for 1 second" or "never".

max-age 0 means "cacheable resource fresh for 0 seconds". It means neither "don't cache" nor "cache for n seconds". The resource is cacheable and always stale, and must be revalidated before returning it to a client.

> I don't see why it would be necessary for it to mean "never"

It doesn't, but returning the resource without checking its validity against the source is forbidden by the spec. So Safari is buggy on that, and buggy when there's no Cache-Control as well.


OK, I guess I should salute for doing the ultimate in defensive programming.

But I come from a system software background and definitely expect that age=0 means age=0. If '0' is allowed for age, then I expect Apple to handle that case according to the rules of normal arithmetic.


Yeah, and there's no indication that 303 response was generated.


The 303 status is one possible behavior presented, it's not even a recommendation, never mind a SHOULD or MUST.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: