In an attempt to reduce the size of the response payload over the wire, various compression algorithms are used to compress the response body.
The most popular compression algorithm by far is gzip. HTTP has the mechanisms in place to perform content negotiation, and to request either the plain-text or the compressed version.
In terms of content negotiation, the browser can advertise its
content encoding capabilities by issuing an Accept-Encoding header
containing the compression/encoding algorithms it supports.
Here’s what my browser advertises:
Accept-Encoding: gzip, deflate, br
Basically, my browser supports gzip compression, deflate
compression, and br compression. br is short for Brotli.
A server can choose one of the supported compression algorithms and
return the algorithm it used for compression in the form of a
Content-Encoding header.
Because gzip is the most popular web compression algorithm, web servers are likely to return the following response header:
Content-Encoding: gzip
Varnish natively supports gzip compression and encourages servers to send compressed responses to Varnish.
It does so by modifying the Accept-Encoding header to
Accept-Encoding: gzip for every miss, regardless of the
Accept-Encoding value that the client may have set.
Responses will be stored in cache in a compressed format. If it turns out that the client doesn’t support gzip, Varnish will decompress the response on-the-fly.
Because gunzip is very fast, it is more efficient to decompress on-the-fly than to store two versions of the object in cache.
When a client doesn’t support gzip, the plain-text version is
returned, the Content-Encoding: gzip header is stripped off, and
Etags get weakened.
When a gzip’ed object is stored in cache, a Vary: Accept-Encoding
header will be returned to the client. Any attempt by the origin to
issue a Vary: Accept-Encoding will be ignored because only the
compressed version is kept.
If the origin doesn’t respond with a compressed response, Varnish will trust that it’s because the compression wasn’t worth it. This is the case for images, video and other binary resources. In such cases, the object is stored as-is, and user requests for compression will be ignored. The next section explains how to override this.
To explicitly disable gzip support in Varnish, the http_gzip_support
runtime parameter can be disabled.
Even though Varnish handles gzip compression behind the scenes, the VCL programming language still allows you to override the default behavior.
Imagine that your origin server doesn’t support gzip, but you still want to serve compressed content. In that case you can use the following VCL snippet:
sub vcl_backend_response {
if (beresp.http.content-type ~ "text") {
set beresp.do_gzip = true;
}
}
As you can see, there is an if-condition in there to ensure that only plain-text content gets compressed. Binary content, such as JPEG images, shouldn’t be compressed.
You can also decompress gzip’ed content in VCL by setting
set beresp.do_gunzip = true;. You can even check whether or not the
client supports gzip through the req.can_gzip variable, which
returns a boolean.
As of version 6.0.6r10 Brotli compression is supported in Varnish
Enterprise. It is not available by default but requires vmod_brotli
to be initialized.
The module can handle brotli-compressed responses from the origin, but it can also turn gzip-compressed data into Brotli.
Here’s a VCL example that will store gzip-compressed or plain-text objects into brotli-compressed objects:
vcl 4.1;
import brotli;
sub vcl_init {
brotli.init(BOTH, transcode = true);
}
sub vcl_backend_response {
if (beresp.http.content-encoding ~ "gzip" ||
beresp.http.content-type ~ "text") {
brotli.compress();
}
}
By initializing vmod_brotli with BOTH as the encoding value, it can
normalize the Accept-Encoding request header and support plain-text
encoding, gzip encoding and Brotli encoding.
By setting the transcode argument to true, the module will
decompress objects when the client doesn’t support Brotli, or transcode
the object to gzip when the client only supports gzip.