Using AddEncoding x-gzip .gz without actual files

apache-2.2gzipmod-rewrite

With Apache (2.2 and later) how can I achieve the following. I want to transparently compress using GZip encoding (not plain Deflate) the output when a certain file is queried with its name plus the extension .gz, where the .gz version doesn't physically exist on disk.

So let's say I have a file named /path/foo.bar and no file foo.bar.gz in the folder to which the URI /path maps, how can I get Apache to serve the contents of /path/foo.bar but with AddEncoding x-gzip ... applied to the (non-existing) file?

The rewrite part appears to be easy, but the problem is how to apply the encoding to a non-existent item. The other way around also seems to be simple as long as the client supports the encoding.

Is the only solution really a script that does this on the fly?


I'm aware of mod_deflate and mod_gzip and it is not what I'm looking for – at least not alone. In particular I need an actual GZIP file and not just a deflated stream.

Now I was thinking of using mod_ext_filter, but couldn't bridge the gap between rewriting the name of the (non-existent) file.gz to file on one side and the LocationMatch on the other. Here's what I have.

RewriteRule ^(.*?\.ext)\.gz$ $1 [L]
ExtFilterDefine gzip mode=output cmd="/bin/gzip"
<LocationMatch "/my-files/special-path/.*?\.ext\.gz">
    AddType application/octet-stream .ext.gz
    SetOutputFilter gzip
    Header set Content-Encoding gzip
</LocationMatch>

Note that the header for Content-Encoding isn't really needed by the clients in this case. They expect to see actual GZIP files, but I want to do this on-the-fly without caching (this is a test scenario).

Best Answer

Alright, sorry for answering my own answer so shortly after offering the bounty, but I finally found out how to accomplish what I want. My last edit to my question was close, but not close enough.

It turned out I could abuse the fact that mod_rewrite lets me set the MIME-type of a rewritten path (T=) in order to apply my filter (using mod_ext_filter) using the AddOutputFilterByType directive like this:

RewriteRule ^(.*?\.ext)\.gz$ $1 [L,T=application/my-file-type]
ExtFilterDefine gzip mode=output cmd="/bin/gzip"
<Location "/my-files">
    AddOutputFilterByType gzip application/my-file-type
</Location>

So this way the actual file (e.g. somename.ext.gz) does not exist, but somename.ext does exist and mod_rewrite takes care to apply the filter conditionally only when the request comes in with the .ext.gz extension, but never if the request comes in under the (existing) name.

All I did there was to invent my own MIME-type.


As 200_success suggested in his/her comment, I adjusted this once again to be more readable and relying on an environment variable (conditionally set through mod_rewrite):

RewriteRule ^(.*?\.ext)\.gz$ $1 [L,E=NEEDGZIP:1]
ExtFilterDefine gzip mode=output cmd="/bin/gzip" enableenv=NEEDGZIP
<Location "/my-files">
    SetOutputFilter gzip
</Location>