Why are custom headers missing in "304 (Not Modified)" responses?
304 (Not Modified) responses minimize the amount of information that needs to be transferred in subsequent requests made after an initial
200 (OK) response if the resources being requested are unchanged1.
This has performance benefits for a website, particularly where larger assets such as images are involved.
If you are developing a website that makes use of custom headers in responses, it’s worth noting a behaviour with respect to headers that
304 responses have that differ from
If a visitor to the website were to inspect their network requests and look at a
200 response, they can expect to see not only custom headers defined for the response, but the following headers which relate to the caching of the resource2:
304 response however, the specification details that1:
… a sender SHOULD NOT generate representation metadata…unless said metadata exists for the purpose of guiding cache updates.
This means that that same request, if the resources are cached on the browser, will receive a response that will generally be missing the additional metadata (in this case the custom headers) since they don’t tend to serve ‘the purpose of guiding cache updates’.
As an example to illustrate this behaviour, let’s use a demo site that Netlify has for the Next.js framework. The specific page that we’re interested in can be found here.
Looking at the ‘Network’ tab within the browser console, the request fetching the image on the page is the one that we’ll take a closer look at. It should look something like:
200 response headers:
HTTP/2 200 OK age: 0 cache-control: public, max-age=0, must-revalidate content-type: image/jpeg date: Tue, 23 Aug 2022 01:05:36 GMT etag: "3b-XMihzCU33fI+mTMhk6V4yc9TZww" server: Netlify strict-transport-security: max-age=31536000 x-nf-request-id: 01GB43QGZ949EAFF6HBMX480RG x-test: foobar X-Firefox-Spdy: h2
Now if we were to refresh the page, we’ll see a
304 response for that request instead:
HTTP/2 304 Not Modified cache-control: public, max-age=0, must-revalidate date: Tue, 23 Aug 2022 01:08:03 GMT etag: "3b-XMihzCU33fI+mTMhk6V4yc9TZww" server: Netlify x-nf-request-id: 01GB43W0VGYVR87CHSMZ70T4HQ X-Firefox-Spdy: h2
Notice how the
x-test custom header near the bottom of the list for the
200 response is now missing from the
I hadn’t realized until recently that the minimization of data in a
304 response extended to the response headers, and so for those who have run into this behaviour and were also a bit puzzled as to why this happens, I hope this quick explanation was helpful.