Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have apache 2.2.11 installed on my server and I have been trying to decrease the load time of my website pages based on the advice from the yslow firefox plugin.

I have configured gzip and etag and some of its other suggestions fine but I have noticed in the header for my css files etag is being appended with the text gzip.

Does anyone know why and how to get round this?

Header from my server
Date    Sun, 07 Jun 2009 10:40:57 GMT
Server  Apache/2.2.11 (Fedora)
Last-Modified   Sun, 31 May 2009 15:06:38 GMT
Etag    "3b4-46b36a802bb80"-gzip
Accept-Ranges   bytes
Cache-Control   max-age=2592000
Expires Tue, 07 Jul 2009 10:40:57 GMT
Vary    Accept-Encoding
Content-Encoding    gzip
Content-Length  530
Connection  close
Content-Type    text/css
The same code on my hosted package uses an older version of apache and doesn't have the same problem. Could this just be an apache bug?
Header from my hosting package
Date    Sun, 07 Jun 2009 10:48:26 GMT
Server  Apache/2.0.63 (FreeBSD) mod_python/3.3.1 Python/2.5.1 PHP/5.2.6 with Suhosin-Patch mod_fastcgi/2.4.6 mod_ssl/2.0.63 OpenSSL/0.9.7e-p1 DAV/2 mod_perl/2.0.4 Perl/v5.8.8
Last-Modified   Sat, 21 Feb 2009 13:54:52 GMT
Etag    "3b4-1d104300"
Accept-Ranges   bytes
Cache-Control   max-age=2592000
Expires Tue, 07 Jul 2009 10:48:26 GMT
Vary    Accept-Encoding
Content-Encoding    gzip
Content-Length  530
Connection  close
Content-Type    text/css
share|improve this question
What exactly is bad about that "-gzip" append? Since clients will always request either the gzipped or non-gzipped version, they won't end up having to cache two copies. Intermediate proxies will possibly now see two different files, but that's good, as if they only stored one of the variants, some people might receive the wrong format. – Alex J Jun 7 '09 at 12:43
The "-gzip" append is bad because it violates RFC 2616. ETags should not have suffixes outside the " symbol. So ETag: "foo" is good (and valid) but ETag: "foo"-gzip is not. A correctly formatted gzip suffix would be ETag: "foo-gzip" – mogsie Feb 6 '14 at 23:19
up vote 4 down vote accepted

Here's an ideal .htaccess that both compresses and sets sutiable expire headers.

# Insert filter
SetOutputFilter DEFLATE

# Netscape 4.x has some problems...
BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip

# MSIE masquerades as Netscape, but it is fine
# BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# Make sure proxies don't deliver the wrong content
Header append Vary User-Agent env=!dont-vary

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 seconds"
  ExpiresByType image/x-icon "access plus 2592000 seconds"
  ExpiresByType image/jpeg "access plus 2592000 seconds"
  ExpiresByType image/png "access plus 2592000 seconds"
  ExpiresByType image/gif "access plus 2592000 seconds"
  ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
  ExpiresByType text/css "access plus 604800 seconds"
  ExpiresByType text/javascript "access plus 216000 seconds"
  ExpiresByType application/x-javascript "access plus 216000 seconds"
  ExpiresByType text/html "access plus 600 seconds"
  ExpiresByType application/xhtml+xml "access plus 600 seconds"

<IfModule mod_headers.c>
  <FilesMatch "\\.(ico|jpe?g|png|gif|swf)$">
    Header set Cache-Control "max-age=2592000, public"
  <FilesMatch "\\.(css)$">
    Header set Cache-Control "max-age=604800, public"
  <FilesMatch "\\.(js)$">
    Header set Cache-Control "max-age=216000, private"
  <FilesMatch "\\.(x?html?|php)$">
    Header set Cache-Control "max-age=600, private, must-revalidate"

<IfModule mod_headers.c>
  Header unset ETag
FileETag None

<IfModule mod_headers.c>
  Header unset Last-Modified

The following article covers what it does and also talks about compression:

Hope that helps.

share|improve this answer
As a note, this removes the etags. This is because for instance if you are serving you site from several servers, the etags can vary with each machine, it is better to just use cache control & expires. – Sam Jun 7 '09 at 13:16

Apache mod_deflate is creating unique Etag for each entity as these identify the specific entity variant of the URL. Each negotiated variant needs to have unique ETag:s. For mod_deflate it's as simple as adding the encoding to the already computed ETag.

One workaround is to remove the encoding from the Etag:

<Location /js>
  RequestHeader  edit "If-None-Match" "^(.*)-gzip$" "$1"
  Header  edit "ETag" "^(.*[^g][^z][^i][^p])$" "$1-gzip"

If you are using Apache 2.5 with the mod_deflate module, you can use the directive DeflateAlterETag to specifies how the ETag hader should be altered when a response is compressed.

DeflateAlterETag AddSuffix|NoChange|Remove


This blog post suggest to remove Etags altogether and to rely on the Cache-Control header.

To do that in httpd.conf:

<IfModule mod_headers.c>
    Header unset ETag

FileETag None

Note that if entities gzip:ed by mod_deflate still carries the same ETag as the plain entiy, this may cause inconsistency in ETag aware proxy caches.

More info here:

share|improve this answer

Can you elaborate on how you configured gzip? For example, are you using mod_deflate? Can you post snippets from your httpd.conf, especially the AddOutputFilterByType field? I followed these directions for my particular hosting provider, and it's possible that text/css isn't in the list at your hosting provider:

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.