Should HTTP 304 Not Modified-responses contain cache-control headers?

HtmlHttp HeadersEtag

Html Problem Overview


I've tried to understand this, and searched SO for similar questions, but I still don't have a 100% understanding on how this is supposed to work.

I get this response on a request for an image resource:

Response Headers
    Server	Apache-Coyote/1.1
    Date	Mon, 19 Oct 2009 09:04:04 GMT
    Expires	Mon, 19 Oct 2009 09:06:05 GMT
    Cache-Control	public, max-age=120
    Etag	image_a70703fb393a60b6da346c112715a0abd54a3236
    Content-Disposition	inline;filename="binary-216-420"
    Content-Type	image/jpg;charset=UTF-8
    Content-Length	4719

The desired behavior is that the client should cache this for 120 seconds, then request it from the server again. Within the 120 seconds, no request is sent to the server.

Then, after 120 seconds, a request is sent and a 304 response is received:

Response Headers
    Server	Apache-Coyote/1.1
    Date	Mon, 19 Oct 2009 09:06:13 GMT

Request Headers
    Host	localhost:8080
    User-Agent	Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3
    Accept	image/png,image/*;q=0.8,*/*;q=0.5
    Accept-Language	en-us,no;q=0.8,sq;q=0.7,en;q=0.5,sv;q=0.3,nn;q=0.2
    Accept-Encoding	gzip,deflate
    Accept-Charset	ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive	300
    Connection	keep-alive
    Referer	http://localhost:8080/cms/site/0/en/home
    Cookie	JSESSIONID=768ABBE1A3BFABE3B535900233330650; versionsCssDisplayState=block; iceInfo=iceOn:false,activePortletKey:,icePagePanelX:1722,icePagePanelY:3
    If-None-Match	image_a70703fb393a60b6da346c112715a0abd54a3236

So far, all well. But then, on the next request (whithin 120 seconds) i would have thought that the resource should be cached for 120 new seconds. What i see in the browser (Firefox) on the other hand, is that it from this point on always request the resource and receives the 304-response.

Am I supposed to attach the cache-control headers in the 304-response? From what i can read in the spec, it seems like the cache-control settings should be omitted, and that the cache should cache it for 120 new seconds automatically?

Html Solutions


Solution 1 - Html

RFC7232 updates RFC2616 to say:

> The server generating a 304 response MUST generate any of the following header fields that would have been sent in a 200 (OK) response to the same request: Cache-Control, Content-Location, Date, ETag, Expires, and Vary.

Solution 2 - Html

In theory you shouldn't have to send Cache-Control for a 304 -- the recipient should just continue to use the cache directives that it received from the original 200. However, as you've found, in practice if you don't keep sending Cache-Control, browsers will ignore the cache directives that you sent originally, and revert to their own default heuristics.

So in practice, you should include the same Cache-Control with a 304 that you would with a 200. The spec only mandates that you send it for a 304 if it's different than what you sent previously (see 10.3.5 304 Not Modified) -- but it certainly doesn't forbid you from repeating it when it's the same.

And to respond specifically to the wrong-headed points from the other answer (Structure's):

  1. You do want intermediary caches to cache the response (that is, update their cache entry for the resource). They will respond appropriately to requests from clients with a 200 or a 304, depending on whether the client included a conditional header like If-Modified-Since.

  2. The 120-second ttl will be refreshed by the 304 (so the same client shouldn't make another request for the same resource for at least another 120 seconds). And clients, as long as they've still got the content cached, will continue to make conditional requests for the resource, which you can continue to respond to with a 304.

Solution 3 - Html

If I understand correctly then the browser is in fact caching for 120 seconds and your server is responding 304 Not Modified to subsequent If-Modified-Since requests. This "IMS" request occurs when the end-user accesses the same URL. At that time the browser can send an If-Modified-Since request. The browser wants to know if it is displaying stale content. This seems normal.

Upon receiving this request your server should reply 200 OK, 304 Not Modified (or a 4XX, if necessary).

I do not believe you should set your server to send a Cache-Control header with the 304 response for two reasons:

  1. You do not want any intermediary caches to cache that 304 response (there is a possibility that they could)
  2. The 120 second TTL will not be refreshed by the 304 response. The browser will retain the object for 120 seconds from the 200 OK response. After 120 seconds the browser should send a GET request, not an If-Modified-Since, so your server will respond with the bytes of the file and not just a 304 response.

Note that the browser will not request the file again automatically after 120 seconds unless the end-user specifically requests it via a page load or directly inputting the URL into their address bar (or unless you have a custom application that controls that functionality somehow).

Edited the first paragraph to read a bit better(hopefully)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrunarMView Question on Stackoverflow
Solution 1 - HtmlMark NottinghamView Answer on Stackoverflow
Solution 2 - HtmlJustin LudwigView Answer on Stackoverflow
Solution 3 - HtmlStructureView Answer on Stackoverflow