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.gzexists on server:Content-Encodingis set togzip.Content-Typeis set to value offile.ext(!!!).- Server returns
file.ext.gz.
- Otherwise,
file.extis 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.exttofile.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.