I am working on a statically generated html site, that is bundled into a container image. To reduce the overall size of the container image, we pre-compress all HTML files, and to simplify our Apache config we remove the '.gz' part of the file name, so index.html is actually pre-compressed, and then we set the content-encoding to gzip in our Apache config for text/html so the browser treats it as compressed and decompresses it in the client browser. This all works fantastically, however now to even further reduce the image size we would also like to use SSI to include the header and footer html without duplicating it on every page, but since our HTML files are already pre-compressed we need to set up an output filter chain in Apache to first decompress (INFLATE), then run SSI (INCLUDES), and then re-compress with DEFLATE.
In theory this should work:
<LocationMatch "/compressed/">
Options +Includes
SetOutputFilter INFLATE;INCLUDES;DEFLATE
</LocationMatch>
The problem I'm having is that INFLATE is not decompressing the pre-compressed files as the mod_deflate docs says it should.
Given that I have a directory called /compressed/
and in that directory I have a pre-compressed with gzip html file index.html
(note, .gz extension has been removed). This file also contains a couple SSI includes for header and footer.
First thing I dried was this:
<LocationMatch "/compressed/">
Options +Includes
SetOutputFilter INFLATE;INCLUDES;DEFLATE
</LocationMatch>
However the INFLATE filter does not work, so the INCLUDES filter does not work.
I also tried this method which according to the Apache filter example for INFLATE looked like exactly what I needed, also did not work:
<LocationMatch "/compressed/">
Options +Includes
# filter provider for decompressing
FilterDeclare gunzip CONTENT_SET
FilterProvider gunzip INFLATE "'1' == '1'"
# filter provider for SSI
FilterDeclare SSI
FilterProvider SSI INCLUDES "'1' == '1'"
FilterChain gunzip SSI
</LocationMatch>
This also did not work. Note I made the conditional for the FilterProvider always resolve to true with "'1' == '1'"
, just to eliminate that as the problem.
The problem is that in both cases INFLATE just does not decompress the pre-compressed HTML, even though the examples and official docs says that is exactly what it should do!
As a hacky work-around I created an external filter that uses the gunzip
binary directly which works perfectly:
ExtFilterDefine gunzip mode=output \
cmd="/usr/bin/gunzip"
<LocationMatch "/compressed/">
Options +Includes
SetOutputFilter gunzip;INCLUDES;DEFLATE
</LocationMatch>
The above works perfectly, it decompresses the HTML, runs SSI includes, then re-compresses it with DEFLATE to send the response. So from what I read about INFLATE it should be doing the exact same thing as gunzip
, so why does directly using gunzip
work fine, but no matter what I try with INFLATE it just will not decompress?
Can anyone help me with a working example of using INFLATE to decompressed pre-compressed HTML?
Thank you!