ChatGPT解决这个技术问题 Extra ChatGPT

NodeJS/express: Cache and 304 status code

When I reload a website made with express, I get a blank page with Safari (not with Chrome) because the NodeJS server sends me a 304 status code.

How to solve this?

Of course, this could also be just a problem of Safari, but actually it works on all other websites fine, so it has to be a problem on my NodeJS server, too.

To generate the pages, I'm using Jade with res.render.

Update: It seems like this problem occurs because Safari sends 'cache-control': 'max-age=0' on reload.

Update 2: I now have a workaround, but is there a better solution? Workaround:

app.get('/:language(' + content.languageSelector + ')/:page', function (req, res)
{
    // Disable caching for content files
    res.header("Cache-Control", "no-cache, no-store, must-revalidate");
    res.header("Pragma", "no-cache");
    res.header("Expires", 0);

    // rendering stuff here…
}

Update 3: So the complete code part is currently:

app.get('/:language(' + content.languageSelector + ')/:page', pageHandle);

function pageHandle (req, res)
{
    var language = req.params.language;
    var thisPage = content.getPage(req.params.page, language);

    if (thisPage)
    {
        // Disable caching for content files
        res.header("Cache-Control", "no-cache, no-store, must-revalidate");
        res.header("Pragma", "no-cache");
        res.header("Expires", 0);

        res.render(thisPage.file + '_' + language, {
            thisPage : thisPage,
            language: language,
            languages: content.languages,
            navigation: content.navigation,
            footerNavigation: content.footerNavigation,
            currentYear: new Date().getFullYear()
        });
    }
    else
    {
        error404Handling(req, res);
    }
}
304 is not a problem. It simply means that your response is not modified and your browser turns to cache to fetch the resource. Can you post the relevant code in which anomaly is happening.
yes, actually it isn't modified, but Safari empties its cache on CMD + R (reload) and the server only says it didn't change.
How is blank page related to 304 status code? Node would also send 304 to other browsers.
It is related because with 304 the body is not sent and the browser uses its cache, but since there is no cache, you get a blank page
@AkshatJiwanSharma Any program is developed to be meet the product owner's contract exactly. The product owner is the one who owns the code and pays the money, not some organization that writes papers that nobody cares about. If the contract says "200" then absolutely any status that is not equal to "200" is a bug. When there is a bug I MUST rewrite code until everything is exactly as expected. W3C do not have a say in the matter.

b
blented

Easiest solution:

app.disable('etag');

Alternate solution here if you want more control:

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/


Could you explain the "easiest solution" or give a reference on how this affects?
@SamuelMéndez it disables caching basically, the wiki on etag has a lot of good info en.wikipedia.org/wiki/HTTP_ETag
Worked for me :)
This makes sense. I believe the etag was not being recomputed properly because I wasn't setting the the last modified date, as mentioned in vlasenko's link. My problem went away when I updated my code as follows: const headers = { 'Last-Modified': (new Date()).toUTCString() }; app.get('/*', (req, res) => { res.sendFile(join(DIST_FOLDER + '/index.html'), { headers } ); });
s
sbugert

Try using private browsing in Safari or deleting your entire cache/cookies.

I've had some similar issues using chrome when the browser thought it had the website in its cache but actually had not.

The part of the http request that makes the server respond a 304 is the etag. Seems like Safari is sending the right etag without having the corresponding cache.


that works for me when I tried to delete entire cache, thanks
u
user907567

I had the same problem in Safari and Chrome (the only ones I've tested) but I just did something that seems to work, at least I haven't been able to reproduce the problem since I added the solution. What I did was add a metatag to the header with a generated timstamp. Doesn't seem right but it's simple :)

<meta name="304workaround" content="2013-10-24 21:17:23">

Update P.S As far as I can tell, the problem disappears when I remove my node proxy (by proxy i mean both express.vhost and http-proxy module), which is weird...


I also use an Apache proxy, this could be the problem. My workaround was to just disable caching for content sites with http headers.
Disabling cache through the headers is definitely the way to go. At first it didn't work for me but now it does. In other words I must've made a mistake somewhere the first time around :)
J
J. Scott Elblein

As you said, Safari sends Cache-Control: max-age=0 on reload. Express (or more specifically, Express's dependency, node-fresh) considers the cache stale when Cache-Control: no-cache headers are received, but it doesn't do the same for Cache-Control: max-age=0. From what I can tell, it probably should. But I'm not an expert on caching.

The fix is to change (what is currently) line 37 of node-fresh/index.js from

if (cc && cc.indexOf('no-cache') !== -1) return false;  

to

if (cc && (cc.indexOf('no-cache') !== -1 ||
  cc.indexOf('max-age=0') !== -1)) return false;

I forked node-fresh and express to include this fix in my project's package.json via npm, you could do the same. Here are my forks, for example:

https://github.com/stratusdata/node-fresh https://github.com/stratusdata/express#safari-reload-fix

The safari-reload-fix branch is based on the 3.4.7 tag.


Great work! I see that express 3.5.1 includes your fix via node-fresh 0.2.2.
Actually, I'm wrong, your fix was reverted and did not actually make it to 0.2.2. Still no fresh/express fix.
C
Codebeat

Old question, I know. Disabling the cache facility is not needed and not the best way to manage the problem. By disabling the cache facility the server needs to work harder and generates more traffic. Also the browser and device needs to work harder, especially on mobile devices this could be a problem.

The empty page can be easily solved by using Shift key+reload button at the browser.

The empty page can be a result of:

a bug in your code

while testing you served an empty page (you can't remember) that is cached by the browser

a bug in Safari (if so, please report it to Apple and don't try to fix it yourself)

Try first the Shift keyboard key + reload button and see if the problem still exists and review your code.


H
Hasan Gökçe

Operating system: Windows

Browser: Chrome

I used Ctrl + F5 keyboard combination. By doing so, instead of reading from cache, I wanted to get a new response. The solution is to do hard refresh the page.

On MDN Web Docs:

"The HTTP 304 Not Modified client redirection response code indicates that there is no need to retransmit the requested resources. It is an implicit redirection to a cached resource."


S
Slava Rozhnev
// just add * in URL
    
app.get('/api*', (req, res)=>{

// do something 

});