Webinoly is just the perfect tool for NGINX experts. Give it a try!
0 votes
1.5k views
by Rookie

This question is for a Wordpress site with -cache=on.

The cache-control header "public, no-cache" is set in common/headers-html.conf but browsers and CDNs are unable to cache the html assets because there is no ETag header set.The server will always return 200 and download the html again instead of responding with a 304 if the html has not changed. 

There is an ETag header set for static assets (.css, .js, images, etc) but nothing for the html asset. I have modified the common/headers.conf file as follows, but there is still no ETag header set.

add_header Cache-Control "public, no-cache";
add_header Referrer-Policy "no-referrer-when-downgrade";
#add_header Content-Security-Policy " ";

#edit by James may get overwritten
expires max;
etag on;

I am now getting cache-control: max-age and expires headers in addition to the cache-control: public, no-cache, but still no ETag header for the html/page asset.

I am trying to figure out where the ETag header gets set for the static assets, but I don't see anything in common/locations.conf other than "expires: max".

My goal is for browsers and CDN to cache the html and for nginx to send a 304 response instead of 200 if the page has not changed.

by
James, were you ever able to find an answer for this question?

It's been months since I have been scratching my head around this. All my static assets including images, JS, and CSS emit ETags and last-modified headers, but not the HTML.

I have already tried resetting the server, reinstalling WP, disabling all installed plugins, cleaning up the DB, changing back to the default theme and what not.

1 Answer

0 votes
by Expert

Not sure, try with: add_header Cache-Control "public, must-revalidate";

by Rookie
Whether "public, no-cache" or "public must-revalidate", the problem remains that there is no cache validator (etag or last-modified) set. Without a cache validator, "public, no-cache" and "public, must-revalidate" don't have any effect.
by Rookie
Hey, any update on this? I still haven't found a solution.
by Expert
The only one having an issue is you, so I highly doubt you will get any other "updates"!

Our CDN is working fine with the current configuration, by the way. Tell us if you find something relevant to improve.
by Rookie

Everything is working fine as long as you don't want to cache html pages. Your current configuration is setting "public, no-cache" without a cache validator for html assets, which I think is a bug. 

Here is some more information about cache validation.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#Cache_validation

Without setting either last-modified or etag, browsers (and CDNs) have nothing to validate against, and must bypass the cache completely and download the resource again as if there was no cache at all. Setting "public, no-cache" in the header without a cache validator is pointless and does nothing.

Maybe you don't think it's a big deal because most people don't bother with caching html assets anyway. The size is usually small and downloading it again doesn't save much time vs re-validating. But then why add "public, no-cache" in the first place then?

by Expert
And after all that long explanation...

What's your proposal?

How do you think it should be?

How can we improve our current Nginx conf?
by Expert

Setting "public, no-cache" in the header without a cache validator is pointless and does nothing.

By the way, that's not true!

by Rookie
What's your proposal?

How do you think it should be?

How can we improve our current Nginx conf?

My proposal is that a cache validator (either last-modified or etag) should be set in the http header along with "public, no-cache" for html assets.

I don't know how to achieve this. I have already tried the steps mentioned in my top level post (etag on; and expires max;). This should set the cache-validators according to the NGINX documentation, but it's not working and I don't know why.

Setting "public, no-cache" in the header without a cache validator is pointless and does nothing. 

By the way, that's not true!

Then what is the effect of adding "public, no-cache" without a validator?

I'm not sure if you don't understand cache-control very well. Or maybe I am the one who is misunderstanding something here. Here is my understanding.

"no-cache" says to the client (browser or cdn) "here is the resource, but don't use this again without validating first". It is essentially the same as "must re-validate, max-age: 0".

On the next request, the client (browser or cdn) should send a validation request to see if whether the resource can be used or not (whether it is different from the copy in the cache). This validation requires an etag or last-modified header. Otherwise, there is no way to do the required validation and the no-cache directive doesn't do anything.

Please let me know if your understanding of this is different than mine. Here is the relevant spec:

https://tools.ietf.org/html/rfc7234

by Expert

Definitely, we have a very different understanding of this topic.

I don't know how to achieve this. I have already tried the steps mentioned in my top level post (etag on; and expires max;). This should set the cache-validators according to the NGINX documentation, but it's not working and I don't know why.

Please, keep trying, that's the best way to learn and achieve things!

Welcome to the Community site for Webinoly.

Our Optimized LEMP Web Server is a powerful set of commands for doing just about anything you could wish.

With Webinoly you can set up your NGINX web server in just one step.

* * * * * * *

To report a bug, please create a new issue on GitHub or ask a question here with the bug tag.
Webinoly Support Paypal Donations

PayPal · GitHub Sponsors · Bitcoin

It is very important that any visitor to the site read the disclaimer, terms of use and privacy and legal statement before start browsing.

...