I need a manual compression solution on Apache. My goals:
- Provide gzip-encoded content on my server along with uncompressed.
- Files are pre-compressed.
- Not all files are served compressed. I want to specify these files and the choice isn't type (extension) based.
- Many content-types (custom ones) are served, and new types are showing up from time to time. Also, file extension doesn't determine if it will be compressed or not (!!!).
- Keep overhead minimal (the less extra headers, the better).
- Always provide Content-Length header and never send chunked response (this disqualifies
mod_deflate
).
Ideal Functionality
Ideal functionality would work like that:
- Web client asks for file
file.ext
. - If
file.ext.gz
exists on server:Content-Encoding
is set togzip
.Content-Type
is set to value offile.ext
(!!!).- Server returns
file.ext.gz
.
- Otherwise,
file.ext
is returned.
I tested a number of solutions, this article contains a good compilation, but there was always a problem with parts marked with (!!!). I have hundreds of thousands of files and dozens of content types and because of that I'm looking for some automatic solution, without need of adding ForceType
for each file.
What I tried
Multiviews
How this works:
- Rename a file
file.ext
tofile.ext.en
- Create a file
file.ext.gz
Configure Apache:
Options +MultiViews AddEncoding x-gzip .gz RemoveType .gz
Works almost as expected, except it requires the original file (file.ext
) to not exist and it adds many (useless to me) headers (TCN
, Content-Language
and few more) that can't be removed (Header unset
doesn't remove them).
Rewrite
How this works:
- Create file.ext.gz
file.
- Configure Apache:
<pre>
RewriteEngine On
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule (.*)$ $1.gz [L]
AddEncoding x-gzip .gz
<Files file.ext>
ForceType my-custom/mime-type
</FilesMatch>
</pre>
This works well, but requires a ForceType
for each compressed file. As I said before, I can't rely on extensions because not all files of certain type will be compressed.
mod_deflate
I didn't investigate it too much, the problem is that if file is too big, then it's split into pieces and sent in chunks and Content-Length
is not provided. Increasing size of compression buffers can't eliminate this problem.
Is it possible at all to configure Apache to work as I'd liked to?
I tried to dynamically get Content-Type
of file.ext
and set it to file.ext.gz
, but I didn't find the way how to do this.