37

I have an nginx server and can't seem to find any information on how to send Vary: Accept-Encoding headers for CSS and JS files. Does anyone have info about this?

Thanks!

Mitchell
  • 503
  • 3
  • 8
  • 19

4 Answers4

45

This is from the nginx documentation.

gzip_vary
syntax: gzip_vary on|off
default: gzip_vary off
context: http, server, location

Enables response header of "Vary: Accept-Encoding". Note that this header causes IE 4-6 not to cache the content due to a bug (see 2 ).

There if you just add gzip_vary on; it should do it's job.

Also make sure you have any one of the directives gzip, gzip_static, or gunzip are active.

Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125
Atanas Markov
  • 474
  • 5
  • 2
  • 2
    I think this is NOT the correct answer - at least, not alone, and maybe not for all nginx versions (this I can't tell). gzip_vary alone WILL enable gzip if it's off, but will retain the default gzip_types and won't enable Vary for resources different from the default text/html mimetype. http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip (tested on nginx 1.4.6) – Alan Franzoni Aug 26 '15 at 21:50
  • 1
    @AlanFranzoni this question has nothing to do with enabling gzip or making it encode other content types, it's only about adding the vary header. – jbg Feb 23 '17 at 10:42
  • @jbg I think you misunderstood the purpose of Vary, which is often used with compression (check out https://www.fastly.com/blog/best-practices-for-using-the-vary-header). If gzip and vary have nothing to do together, why would the nginx option be called gzip_vary ? – Alan Franzoni Feb 23 '17 at 21:14
  • I understand the purpose of the Vary HTTP header perfectly well. My point is that the question didn't ask how to turn gzip compression on (they most likely already have turned it on) and for you to claim that an answer that directly answers the exact (quite narrow) question posed is "NOT the correct answer" is absurd. – jbg Feb 24 '17 at 10:56
  • @jbg I think you misunderstood my answer, then (maybe the uppercase 'will' is misleading, I should have written 'will just'). I was clarifying what gzip_vary does and does not. Did you test the answer? On nginx 1.4.6 the answer is wrong, and won't enable vary for CSS and JS, only for text/html. PJunior answer is the correct one. – Alan Franzoni Feb 27 '17 at 19:52
  • 1
    I did test the answer. I had already set up gzip correctly, including the content types, and I came here to find out how to send the "Vary: Accept-Encoding" header. This answer perfectly answered the question as stated, and presumably the asker agrees since they accepted it. – jbg Mar 01 '17 at 15:21
  • @jbg Sincerely, I don't understand why you're being stubborn on this topic. If YOU solved YOUR issue with this answer, it doesn't mean it's correct. Mitchell never stated that he had already setup gzip_types. This answer is incomplete as it doesn't mention gzip_types. I wasn't able to activate Vary with this answer, while PJunior's answer solved my issue. The fact that PJunior's answer is got a lot of upvotes - and that my comments have upvotes as well - probably mean that somebody else needed more clarification on the topic. – Alan Franzoni Mar 17 '17 at 10:59
  • Nothing to do with what I did or didn't solve, it's just what the question asks (versus what you imagine the question is implying). – jbg Mar 19 '17 at 14:06
  • @jbg I hadn't seen your last reply. Very quick gist: the question is: "how to send Vary: Accept-Encoding headers for CSS and JS files?". This answer says: "just add gzip_vary on;" and "make sure you have any one of the directives gzip, gzip_static, or gunzip". Does that answer enable Vary for CSS and JS? No; because if you don't set gzip_types, NEITHER gzip nor vary will work for those types. Full stop. The question is not "I have enabled GZIP for types X and Y; how do I enable Vary header as well?". – Alan Franzoni Oct 26 '18 at 13:33
31

Inside the server { of the domain/subdomain that you want to set it, add

    gzip on;
    gzip_min_length  1100;
    gzip_buffers  4 32k;
    gzip_types    text/plain application/x-javascript text/xml text/css;
    gzip_vary on;

Save the file and restart nginx.

PJunior
  • 2,649
  • 1
  • 33
  • 29
  • 6
    as far as I can tell, this is is the only correct answer. gzip_types is the key here, since the default is just text/html, hence vary won't be enabled for different content types. – Alan Franzoni Aug 26 '15 at 21:48
  • 1
    Worked great in my vhost file on my nginx server. Thanks! – james-see Jan 01 '16 at 01:36
  • 1
    this should be the right answer. gzip_types should be uncommented. it's not enought with only gzip_vary on; as others suggested. – abc May 02 '18 at 11:58
  • `gzip_min_length` is also important if you are testing this on small little dummy files without much content, `gzip` and thus `vary` will fail to send because the file size doesn't meet the minimum length requirements: https://www.thedotproduct.org/posts/nginx-vary-header-handling.html – Jesse Nickles Sep 27 '22 at 14:00
2

Simple. In Nginx conf:

vim /etc/nginx/nginx.conf

Add the following near the bottom under the section:

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

Just uncomment the gzip_vary on; parameter and restart or reload nginx service:

service nginx restart

This should fix the issue. If you are running an old version of nginx, you may need to enable gzip on;, as this is required for the vary header to work.

I hope this helps. FYI, this applies to all server/site conf files unless overwritten in their own respective server blocks. server {}

Source info for nginx, apache and IIS: https://www.maxcdn.com/blog/accept-encoding-its-vary-important/

Tony-Caffe
  • 631
  • 1
  • 8
  • 13
2

If you've tried the other answers and are still seeing vary off (e.g. if you are testing speed of your page using GTMetrix), the following might help:

Make sure all your gzip_types are also set in /etc/nginx/nginx.conf http section.

The server block in /etc/nginx/sites-available/* is one place where you can set the vary header and gzip_types, but depending on how you have your site setup you may be processing and returning files before they reach that bit of config.

In /etc/nginx/nginx.conf you will find an 'http' section - in here, there is also a gzip_types and gzip_vary.

For me - CSS and JS are static files and were being served up before hitting the (wordpress) nginx sites-available file (I have varnish in front of it).

So adding the full list of gzip_types to the http section in nginx.conf fixed my issue.

Dave Hilditch
  • 5,299
  • 4
  • 27
  • 35
  • Can you please help me to figure out what you did? I'm also seeing the same thing on GTMetric and I'm also using wordpress, but I always see that I'm scoring low on that metric. How did you solve it? – VaTo Sep 05 '19 at 16:23