Chrome browser is not sending if-modified-since header to server
Asked Answered
D

6

55

I have these headers being sent to the client by the server:

Cache-Control:private
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html
Date:Sun, 27 Nov 2011 11:10:38 GMT
ETag:"12341234"
Set-Cookie:connect.sid=e1u...7o; path=/; expires=Sun, 27 Nov 2011 11:40:38 GMT; httpOnly
Transfer-Encoding:chunked
last-modified:Sat, 26 Nov 2011 21:42:45 GMT

I want the client to validate that the file hasn't changed on the server and send a "200" if it has otherwise a "304".

Firefox sends:

if-modified-since: Sat, 26 Nov 2011 21:42:45 GMT
if-none-match: "12341234"

Why isn't the chrome sending the same on a refresh of the page? I'm after the behavior that .Net has running:

context.Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate)
Damiendamietta answered 28/11, 2011 at 9:48 Comment(4)
I do not understand "I'm after the behavior that .Net has running:". Could you edit it? The question is important to me.Sheikdom
It was a matter of getting the behavior you get from running the code after the : in .Net. Looking at the tags I was trying to mimic the behavior in node.js.Damiendamietta
For all who think this is a client side issue and vote on those answers. Please read this: It is server-related as I'm after making the browser request using etag (if-none-match). The etag is created server-side and has nothing to do with the client. What I need to know is what to send from the server to the client to make it also send the etag header in chrome. The selected answer is the only right one as it is telling the server to also send if-none-match.Damiendamietta
Even if this seems to not be the case, also note that Chrome doesn't send the "If-Modified-Since" header if you request an image directly from the address bar. Images are retrived from the cache only if they are requested from "img" tags or any image-related css attribute.Reinareinald
P
15

In my experience you need more than just the "Private" Cache-Control header. You need either "Max-Age" or "Expires" to force Chrome to revalidate content with the server.

Remember that revalidation will only start after these time values have elapsed, so they may need to be set to a small value.

Poetess answered 28/11, 2011 at 9:58 Comment(6)
I tried cache-control: private,max-age=0. Didn't work... any other ideas? I also added the expires header but still no go.Damiendamietta
Actually... should be max-age=100000 or something. Almost got it to work. Get it to send the if-none-match some times so that's were it's acting up. Thanks!Damiendamietta
I typically set Max-age to 1 hour but it totally depends on how often you update your static content. If not sure keep the value low to be on the safe side.Poetess
Did any of you find a true solution to this. I'm having the same issue where it's sending it every now and then. I can reload the page 5 times and it's like random whether it will send it back.Acanthocephalan
Yes, as I said, it's all about adding the Max-Age or Expires headers. You need to be specific about when the content is likely to become out of date, otherwise the browser will use its own algorithm, which can be unpredictable as you have seen. In my experience you can always get predictable behaviour when you supply this extra information.Poetess
I was only able to get the header sent with a Cache-Control containing a max-age, a Last-Modified, AND an Expires header set.Matador
D
73

After spending half a day on this yesterday, I tracked down what was causing the issue for me. So long as you have the Chrome object inspector/Client Debugger/Network monitor/Thing that pops up when you hit F12, Chrome will not send cache request headers. Period. (update: in newer versions of Chrome, there is a checkbox "Disable cache"). Even if you don't have the "network" tab open (ex: have the javascript console open), this checkbox still disables all cacheing.

Its sad, because debugging this from the client side obligates you to leave the network panel open to see what headers are being sent and received, and what codes are being returned. Without the network panel open, there is no way to know if your content is being cached from the client side.

If you dig into your server access logs, you will notice your server returning 304s(Cached Content) the minute you close the debug window on your Chrome client. Hope this helps.

Chrome 24.0.1312.57

Delcine answered 15/2, 2013 at 17:14 Comment(6)
The dev tools have an option "Disable cache (while DevTools is open)", perhaps you had that enabled? Click the 'gear' icon in the bottom right corner and check your settings.Clerk
+1 (yes you need to uncheck "Disable cache (while DevTools is open)").Endways
This is not the answer and the answer is server related.Damiendamietta
This answer is an excellent clue (and it did lead to the solution, which is in Neek's comment), but it's unfortunately wrong. It's not having devtools open that prevents the header; it's having 'disable cache' checked. @Neek's comment is the real answer and s/he should consider making it an answer.Abhorrent
If I understand correctly, the answer cannot be server-related because If-Modified-Since is a request header. Therefore, it has to be sent by the client.Abhorrent
This is still the case in (almost) 2022 and Chrome v95Tacy
C
39

I found one answer to this behaviour when using HTTPS, thought I'd share what I found. You do not specify if you are requesting via HTTP or HTTPS.

"The rule is actually quite simple: any error with the certificate means the page will not be cached."

https://code.google.com/p/chromium/issues/detail?id=110649

If you are using a self-signed certificate, even if you tell Chrome to add an exception for it so that the page loads, no resources from that page will be cached, and subsequent requests will not have an If-Modified-Since header.

Clerk answered 18/7, 2013 at 7:15 Comment(6)
This appears no longer to be true. I have a page which the browser is sending if-modified-since headers for some resources and doesn't send them for others.Proudlove
Contrary to the previous comment, I did just see this same exact behavior. If-Modified-Since was not being sent in an environment where I had an invalid certificate, but it was being sent when I had a valid one.Reluctant
Thank you, I had this problem also. I was using a self signed certificate testing on a dev machine. As a test, I temporarily trusted the certificate and started getting 304's as you'd expect.Flout
Noticed the same thing while optimizing our included libs a bit. Self-signed certificate or certificate for a different domain would cause script files to not cache at all. Browser send no if-modified-since or if-none-match headers on the request. Switching to HTTP or going through the Certificate's DNS to the same servers would make the browser include these headers.Candescent
Thumbs up to you! 4 years later and this seems to be the correct answer. When working on a local environment with self-signed / ignored certificate, Chrome will never send If-None-Match headers.Anatropous
This is the actual answer and should be the top answer. I've wasted half a day going crazy and couldn't figure it out. Turns out, it works just fine out of the box in Safari.Catechize
P
15

In my experience you need more than just the "Private" Cache-Control header. You need either "Max-Age" or "Expires" to force Chrome to revalidate content with the server.

Remember that revalidation will only start after these time values have elapsed, so they may need to be set to a small value.

Poetess answered 28/11, 2011 at 9:58 Comment(6)
I tried cache-control: private,max-age=0. Didn't work... any other ideas? I also added the expires header but still no go.Damiendamietta
Actually... should be max-age=100000 or something. Almost got it to work. Get it to send the if-none-match some times so that's were it's acting up. Thanks!Damiendamietta
I typically set Max-age to 1 hour but it totally depends on how often you update your static content. If not sure keep the value low to be on the safe side.Poetess
Did any of you find a true solution to this. I'm having the same issue where it's sending it every now and then. I can reload the page 5 times and it's like random whether it will send it back.Acanthocephalan
Yes, as I said, it's all about adding the Max-Age or Expires headers. You need to be specific about when the content is likely to become out of date, otherwise the browser will use its own algorithm, which can be unpredictable as you have seen. In my experience you can always get predictable behaviour when you supply this extra information.Poetess
I was only able to get the header sent with a Cache-Control containing a max-age, a Last-Modified, AND an Expires header set.Matador
E
4

In addition (https://mcmap.net/q/333069/-chrome-browser-is-not-sending-if-modified-since-header-to-server):

F12 > Settings > General > Disable cache (while DevTools is open) -> uncheck this...

Endways answered 7/3, 2014 at 23:53 Comment(2)
Disable cache is not checked and the problem persists. I'm running version 58.0.3029.110 (64-bit).Discountenance
It suffices to actually have DevTools open. It's a kind of bug in Chrome.Tacy
F
0

I know this question is old, but still.. I noticed that chrome remembers the last refresh that you made. So if you press ctrl+shift+r (refreshing and deleting cache), and pressing ctrl+r (just refreshing), chrome keeps on deleting cache and does not show the 304 in the received response. There is a workaround for this. Press ctrl+shift+r and then go to the address bar, focus it, and hit enter. If your etags are set correctly, and your server is ready to serve a 304, you'll see a new response code in the debugger - 304. so it works.

Foreplay answered 4/3, 2014 at 17:27 Comment(6)
I observed this behaviour on multiple sites. Client error or not, it's still good to know that sometimes cmd+r might be not enough.Foreplay
The accepted answer will help the site(s) where it's not working and not force the site users to do things they shouldn't have to.Damiendamietta
My answer wasn't meant as an alternative to the accepted one :) It's just an additional info.Foreplay
You can use the comments just below the question for that. It gets confusing to read "answers" that is not really relevant.Damiendamietta
1. It is too long for a comment. 2. I had the same issue, stumbled upon this answer, couldn't find the solution here, found one myself, came back here, and shared my solution. You cannot know whether it is a right one or not! It is just the same as the answer above, from Qeremy with the Chrome cache. I just wanted to save time for some other poor bastard who has the same issue. Feel free to delete it though.Foreplay
Thank you for mentioning this, I would never have guessed that there was a difference between normal refresh, and CR on the address bar. This works even if the debug panel is open.Leandra
H
0

Browsers have a lot of counter intuitive behavior when it comes to caching. You would expect, that if the response includes a last-modified-date, that the browser would revalidate this before reusing it. But none of the major browsers actually do that.

The ideal settings for your situation depend on when you want the browser to revalidate, see link below.

Not only do browsers act counter intuitively, different browsers also behave differently in the same situation. For example when the user clicks on the refresh button.

You can read how the different browsers (Internet Explorer, Edge, Safari, FireFox, Chrome) behave with different caching directives (Etag, last-modified, must-revalidate, expires, max-age, no-cache, no-store) at https://gertjans.home.xs4all.nl/javascript/cache-control.html

Holmes answered 8/12, 2018 at 19:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.