3

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).

0xC0000022L
  • 1,516
  • 2
  • 22
  • 42

2 Answers2

2

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>
0xC0000022L
  • 1,516
  • 2
  • 22
  • 42
  • Instead of inventing a MIME type, it would be cleaner to have RewriteRule [E=GZIPFILTER:1] set an environment variable, to trigger ExtFilterDefine enable=GZIPFILTER . – 200_success Jun 05 '12 at 02:06
  • @200_success: thanks, this worked fine. I amended my answer to reflect the change. – 0xC0000022L Jun 05 '12 at 22:32
  • According to the documentation for ExtFilterDefine, you should be able to activate the filter using the environment variable, without using SetOutputFilter. That was the point of setting the environment variable NEEDGZIP=1 in RewriteRule. – 200_success Jun 08 '12 at 10:34
  • @200_success: you're right, forgot the `enableenv`, have this in my config, of course. So you mean the `Location` could also be left out? ... meaning that the `RewriteRule` should actually be narrow enough to not match on other stuff. – 0xC0000022L Jun 09 '12 at 13:25
-1

mod_gzip should be able to help you

http://sourceforge.net/projects/mod-gzip/

Here are some sample configs http://schroepl.net/projekte/mod_gzip/config.htm

ckliborn
  • 2,778
  • 4
  • 25
  • 37
  • 1
    Thanks. I'm sorry, how does this apply to my case? Could you give me an example. Because from reading through the (second) page I take it that it still requires the `.gz` file to be stored in the same folder although internally. I'll start trying but would appreciate some clues which of the many directives you had in mind. Thanks again. – 0xC0000022L Mar 06 '12 at 22:45