Greg
Greg

Reputation: 21

Serving precompressed content with Brotli on Apache

I have installed mod_brotli on my WHM server via easyapache 4 - html, css, js files etc are all being compressed.

I then came across this in the offocial docs - https://httpd.apache.org/docs/2.4/mod/mod_brotli.html#precompressed

I have since added this to my Post VirtualHost include file in WHM (post_virtualhost_global.conf) instead of htaccess as I want this to be server wide.

How can I verify if this is working and indeed serving precompressed files? I haven't found anything to say either way, I can only confirm that brotli compression is in use. CPU loads are near enough the same with or without the include so I suspect it may not be saving the compressed files for next time.

This is the virtual host include:

<IfModule mod_headers.c>
  # Serve brotli compressed CSS and JS files if they exist
  # and the client accepts brotli.
  RewriteCond "%{HTTP:Accept-encoding}" "br"
  RewriteCond "%{REQUEST_FILENAME}\.br" "-s"
  RewriteRule "^(.*)\.(js|css)" "$1\.$2\.br" [QSA]

  # Serve correct content types, and prevent double compression.
  RewriteRule "\.css\.br$" "-" [T=text/css,E=no-brotli:1]
  RewriteRule "\.js\.br$"  "-" [T=text/javascript,E=no-brotli:1]

  <FilesMatch "(\.js\.br|\.css\.br)$">
    # Serve correct encoding type.
    Header append Content-Encoding br

    # Force proxies to cache brotli &
    # non-brotli css/js files separately.
    Header append Vary Accept-Encoding
  </FilesMatch>
</IfModule>

this is my /etc/apache2/conf.2/brotli.conf

<IfModule brotli_module>
  # Compress only a few types
  # https://httpd.apache.org/docs/trunk/mod/mod_brotli.html
  AddOutputFilterByType BROTLI_COMPRESS text/plain text/css text/html application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript
    
  SetOutputFilter BROTLI_COMPRESS
  SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-brotli
    
  BrotliFilterNote Input instream
  BrotliFilterNote Output outstream
  BrotliFilterNote Ratio ratio
    
  LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' brotli
  CustomLog "logs/brotli_log" brotli
</IfModule>

and this is /etc/apache2/conf.modules.d/115_mod_brotli.conf

# Enable mod_brotli
LoadModule brotli_module modules/mod_brotli.so

So if anyone can help me figure out how to confirm if the files are precompressed or not that would be great.

Edit: I don't think my files are being pre-compressed. Does anyone have any further info about this? I cannot find any further posts or docs on it at akk

Upvotes: 2

Views: 4352

Answers (4)

Mohammad Alavi
Mohammad Alavi

Reputation: 714

To make it work within a virtual host, lookahead should be used to get the absolute file path the request is mapped to.

<VirtualHost *:8080>

    <Files *.html.br>
        AddType "text/html" .br
        AddEncoding br .br
    </Files>
    <Files *.js.br>
        AddType "text/javascript" .br
        AddEncoding br .br
    </Files>
    <Files *.css.br>
        AddType "text/css" .br
        AddEncoding br .br
    </Files>
    <Files *.svg.br>
        AddType "image/svg+xml" .br
        AddEncoding br .br
    </Files>

    RewriteEngine On
    RewriteCond %{HTTP:Accept-Encoding} br
    RewriteCond %{LA-U:REQUEST_FILENAME} -f
    RewriteRule ^(.*)$ $1.br [L]



    ServerAdmin [email protected]
    DocumentRoot "/opt/homebrew/opt/httpd/docs/dummy-host.example.com"
    ServerName dummy-host.example.com
    ServerAlias www.dummy-host.example.com
    ErrorLog "/opt/homebrew/var/log/httpd/dummy-host.example.com-error_log"
    CustomLog "/opt/homebrew/var/log/httpd/dummy-host.example.com-access_log" common

</VirtualHost>

Upvotes: 0

phil
phil

Reputation: 21

I'm late to the party, but in my crash course of Brotli through Apache, the OP isn't possible.

What the Apache docs show is how to properly serve the files "if" they are pre-compressed, hence the text: "if they exist".

From what I gather in my search to understand this better, Apache can't actually pre-compress the files, this must be accomplished through a binary or extension which is out of Apache's scope.

What Apache mod_brotli does for you is dynamically compress requests on-the-fly as it's being sent. In the case of the OP, using cPanel, if you enable mod_brotli, EasyApache4 adds the necessary bits to serve and compress the files outlined in AddOutputFilterByType as Brotli. Again, these are served dynamically. Generated and served on-the-fly. As far as I can tell, these are cached in memory and not on disk.

Enabling mod_brotli is the easy way to go about enabling brotli, however it's better to pre-compress the files being served as the OP wanted due to the overhead and performance hit on having to literally compress all requests flowing through Apache. I ran across a blog where they talk about this and the difference between dynamic vs static is worth using static pre-compressed files, however if you have a small site, or maybe a really beefy hosting platform, then dynamically serving might work just fine for you.

If I'm not mistaken, you don't even need mod_brotli enabled in order to serve the pre-compressed .br files if you can figure out a way to pre-compress them.

Here's an example of using PHP to pre-compress the files: https://github.com/kjdev/php-ext-brotli

So far, no-one has answered the OP with viable ways to pre-compress files as Brotli (as I too am searching for this) but what I need to point out is that Apache doesn't do the pre-compressing and you will have to continue your search if you're looking for a static way of serving Brotli .br files.

Upvotes: 1

Punit S
Punit S

Reputation: 3247

To configure Apache to serve pre-compressed Brotli files:

  1. Make sure brotli compressed files exist right next to the normal files in respective folders. Eg if you have a file /var/www/html/index.html there should also be /var/www/html/index.html.br

  2. Add the following to the right VirtualHost configuration:

RewriteCond %{HTTP:Accept-Encoding} br RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME}.br -f RewriteRule ^(.*)$ $1.br [L]

<Files *.js.br>
  AddType "text/javascript" .br
  AddEncoding br .br
</Files>
<Files *.css.br>
  AddType "text/css" .br
  AddEncoding br .br
</Files>
<Files *.svg.br>
  AddType "image/svg+xml" .br
  AddEncoding br .br
</Files>
<Files *.html.br>
  AddType "text/html" .br
  AddEncoding br .br
</Files>

To check if pre-compressed brotli files are being served:

You can log the rewrites to see if your rewrites are in action or no. If these are in action, your pre-compressed brotli files are being served. In your virtual host, add the following:

LogLevel alert rewrite:trace6

Restart your apache2, hit your URL and then grep for rewrite statements in your apache error log

tail -f /var/log/apache2/error.log | grep '[rewrite'

Upvotes: 1

Barry Pollard
Barry Pollard

Reputation: 46040

Just remove the reference to /etc/apache2/conf.2/brotli.conf temporarily and restart Apache, and you should see that your precompressed brotli files are still delivered with brotli compression whereas dynamic compressed files (e.g. HTML, or CSS or JS where a precompressed file does not exist) are now not compressed at all.

Upvotes: 1

Related Questions