What headers do I want to send together with a 304 response?
Asked Answered
B

2

20

When I send a 304 response. How will the browser interpret other headers which I send together with the 304?

E.g.

header("HTTP/1.1 304 Not Modified");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT");

Will this make sure the browser will not send another conditional GET request (nor any request) until $offset time has "run out"?

Also, what about other headers?

Should I send headers like this together with the 304:

header('Content-Type: text/html');

Do I have to send:

header("Last-Modified:" . $modified);
header('Etag: ' . $etag);

To make sure the browser sends a conditional GET request the next time the $offset has "run out" or does it simply save the old Last Modified and Etag values?

Are there other things I should be aware about when sending a 304 response header?

Bifurcate answered 27/3, 2009 at 20:16 Comment(0)
P
14

This blog post helped me a lot in order to tame the "conditional get" beast.

An interesting excerpt (which partially contradicts Ben's answer) states that:

If a normal response would have included an ETag header, that header must also be included in the 304 response.

Cache headers (Expires, Cache-Control, and/or Vary), if their values might differ from those sent in a previous response.

This is in complete accordance with the RFC 2616 sec 10.3.5.


Below a 200 request...

HTTP/1.1 200 OK
Server: nginx/0.8.52
Date: Thu, 18 Nov 2010 16:04:38 GMT
Content-Type: image/png
Last-Modified: Thu, 15 Oct 2009 02:04:11 GMT
Expires: Thu, 31 Dec 2010 02:04:11 GMT
Cache-Control: max-age=315360000
Accept-Ranges: bytes
Content-Length: 6394
Via: 1.1 proxyIR.my.corporate.proxy.name:8080 (IronPort-WSA/6.3.3-015)
Connection: keep-alive
Proxy-Connection: keep-alive
X-Junk: xxxxxxxxxxxxxxxx

...And its optimal valid 304 counterpart.

HTTP/1.1 304 Not Modified
Server: nginx/0.8.52
Date: Thu, 18 Nov 2010 16:10:35 GMT
Expires: Thu, 31 Dec 2011 16:10:35 GMT
Cache-Control: max-age=315360000
Via: 1.1 proxyIR.my.corporate.proxy.name:8080 (IronPort-WSA/6.3.3-015)
Connection: keep-alive
Proxy-Connection: keep-alive
X-Junk: xxxxxxxxxxx

Notice that the Expires header is at most Current Date + One Year as per RFC-2616 14.21.

Pay answered 19/11, 2010 at 15:23 Comment(4)
Actually I'd say Ben's answer is partially right, as Expires and Etag only need to be supplied if they are different to the original (from the RFC excerpt above). Of course, as Willem originally asked, yes you can supply a new Expires header and it will extend the client cache time.Telecommunication
Note that the Expires date, in HTTP 1.1, is limited to now + 1 year. So 2037 is not considered valid in this circumstance. w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21 «HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future.»Maxa
@AlexisWilke Good catch! Would you feel like editing this answer and fix it?Pay
with apache i'm getting an internal error 500 when sending etag last-modified headers along the 304 one, if somebody understands why thanks for help (i've also posted a question about it)Suctorial
T
6

The Content-Type header only applies to responses which contain a body. A 304 response does not contain a body, so that header does not apply. Similarly, you don't want to send Last-Modified or ETag because a 304 response means that the document hasn't changed (and so neither have the values of those two headers).

For an example, see this blog post by Anne van Kesteren examining WordPress' http_modified function. Note that it returns either Last-Modified and ETag or a 304 response.

Tolentino answered 27/3, 2009 at 20:27 Comment(3)
Didn't w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 specifically said that if the original had an ETag, we MUST include it in a 304 too?Kyles
If-None-Match can contain multiple ETags (that's why it's called if-NONE-match. The browser or caching proxy may have cached multiple versions of the document, so they send the ETag from ALL of the versions. If you don't respond with an ETag, the caller won't know which version to use.Singletree
my problem is that if a 304 is sent alone then at the next request of the same page the browser doesn't send if modified since & if none match requests headers (and with apache if i try to send etag and last modified response headers i'm getting a 500 internal error. If somebody could help me understand why that'd be amazing (ii have also just posted a question about this #74256141)Suctorial

© 2022 - 2024 — McMap. All rights reserved.