brotli is a compression algorithm based on lz77 and huffman. Special about it is that it uses a dictionary of common words and phrases to achieve a better compression ratio than ordinary compression algorithms. See wikipedia for more details.
Most modern browsers such as Firefox (since 44) and Chrome (50+) and Opera (36+) support brotli out of the box.
They send an Accept-Encoding: gzip, deflate, br
(or similar) header, with br
for brotli.
You'll need the brotli libraries and Apache httpd 2.4.26 or higher with mod_brotli
.
Even though nginx also supports brotli, this document only covers Apache httpd.
This configuration falls back to
mod_deflate
either ifmod_brotli
is not found or the client doesn't know about brotli.
# Load filter module
LoadModule filter_module modules/mod_filter.so
# Load brotli module
LoadModule brotli_module modules/mod_brotli.so
# Load deflate module as fallback
LoadModule deflate_module modules/mod_deflate.so
<IfModule filter_module>
<IfModule brotli_module>
# declare a filter for brotli compression
FilterDeclare COMPRESS_BR CONTENT_SET
# only compress certain content types
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^text/html\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^text/plain\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^text/xml\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^text/css\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^text/javascript\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^text/x-component\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/javascript\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/x-javascript\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/json\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/xml\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/xhtml\+xml\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/rss\+xml\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/atom\+xml\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/vnd\.ms-fontobject\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^image/svg\+xml\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^image/x-icon\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^image/vnd\.microsoft\.icon\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/x-font-ttf\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/font-sfnt\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^application/vnd\.ms-fontobject\b#"
FilterProvider COMPRESS_BR BROTLI_COMPRESS "%{Content_Type} =~ m#^font/opentype\b#"
FilterProtocol COMPRESS_BR BROTLI_COMPRESS change=yes;byteranges=no
</IfModule>
<IfModule deflate_module>
<IfModule setenvif_module>
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
</IfModule>
# declare a filter for deflate/gzip compression
FilterDeclare COMPRESS_GZ CONTENT_SET
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^text/html\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^text/plain\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^text/xml\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^text/css\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^text/javascript\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^text/x-component\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/javascript\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/x-javascript\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/json\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/xml\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/xhtml\+xml\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/rss\+xml\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/atom\+xml\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/vnd\.ms-fontobject\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^image/svg\+xml\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^image/x-icon\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^image/vnd\.microsoft\.icon\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/x-font-ttf\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/font-sfnt\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^application/vnd\.ms-fontobject\b#"
FilterProvider COMPRESS_GZ DEFLATE "%{Content_Type} =~ m#^font/opentype\b#"
FilterProtocol COMPRESS_GZ DEFLATE change=yes;byteranges=no
FilterTrace COMPRESS_GZ 1
</IfModule>
# client accepts brotli
<If "%{HTTP:Accept-Encoding} =~ /\bbr\b/">
<IfModule brotli_module>
# we have brotli support
FilterChain COMPRESS_BR
</IfModule>
<IfModule !brotli_module>
# we do not have brotli support, fallback to deflate if the client supports it
<If "%{HTTP:Accept-Encoding} =~ /\bdeflate\b/">
<IfModule deflate_module>
FilterChain COMPRESS_GZ
</IfModule>
</If>
</IfModule>
</If>
# client does not accept brotli, check for deflate support
<ElseIf "%{HTTP:Accept-Encoding} =~ /\bdeflate\b/">
<IfModule deflate_module>
FilterChain COMPRESS_GZ
</IfModule>
</ElseIf>
</IfModule>
$ curl -s -i -H 'Accept-Encoding: gzip,deflate,br' https://www.unixadm.org/ | \
sed -n '/^content-encoding:/Ip;/^\r$/q'
content-encoding: br
$ curl -s -i -H 'Accept-Encoding: gzip,deflate' https://www.unixadm.org/ | \
sed -n '/^content-encoding:/Ip;/^\r$/q'
content-encoding: gzip