12.8 mod_rewrite Examples

In the mod_proxy and mod_perl servers scenario, ProxyPass was used to redirect all requests to the mod_perl server by matching the beginning of the relative URI (e.g., /perl). What should you do if you want everything, except files with .gif, .cgi, and similar extensions, to be proxypassed to the mod_perl server? (These other files are to be served by the light Apache server, which carries the mod_proxy module.)

The following example locally handles all requests for files with extensions .gif, .jpg, .png, .css, .txt, and .cgi and relative URIs starting with /cgi-bin (e.g., if you want some scripts to be executed under mod_cgi), and rewrites everything else to the mod_perl server. That is, first handle locally what you want to handle locally, then hand off everything else to the backend guy. Notice that we assume that there are no static HTML files. If you have any of those, adjust the rules to handle HTML files as well.

RewriteEngine On
# handle static files and traditional CGIs directly
RewriteRule \.(gif|jpg|png|css|txt|cgi)$ - [last]
RewriteRule ^/cgi-bin - [last]
# pass off everything but images to the heavy-weight server via proxy
RewriteRule ^/(.*)$ http://localhost:4077/$1 [proxy]

This is the configuration of the logging facilities:

RewriteLogLevel 1
RewriteLog "| /home/httpd/httpd_docs/bin/rotatelogs \
/home/httpd/httpd_docs/logs/r_log 86400"

It says to log all the rewrites through the Unix process pipe to the rotatelogs utility, which will rotate the logs every 24 hours (86,400 seconds).

As another example, here's how to redirect all those Internet Explorer 5 (IE5) requests for favicon.ico to a central image:

RewriteRule .*favicon.ico /wherever/favicon.ico [passthrough]

The passthrough flag tells mod_rewrite to set the URI of the request to the value of the rewritten filename /whatever/favicon.ico, so that any other rewriting directives, such as Alias, still apply.

Here's a quick way to make dynamic pages look static:

RewriteRule ^/wherever/([a-zA-Z]+).html /perl/$1.pl [passthrough]

passthrough is used again so that the URI is properly rewritten and any ScriptAlias or other directives applying to /perl will be carried out.

Instead of keeping all your Perl scripts in /perl and your static content everywhere else, you could keep your static content in special directories and keep your Perl scripts everywhere else. You can still use the light/heavy Apache separation approach described earlier, with a few minor modifications.

In the light Apache's httpd.conf file, turn rewriting on:

RewriteEngine On

Now list all directories that contain only static objects. For example, if the only directories relative to DocumentRoot are /images and /style, you can set the following rule:

RewriteRule ^/(images|style) - [last]

The [last] flag means that the rewrite engine should stop if it has a match. This is necessary because the very last rewrite rule proxies everything to the heavy server:

RewriteRule ^/(.*) http://www.example.com:8080/$1 [proxy]

This line is the difference between a server for which static content is the default and one for which dynamic (Perlish) content is the default.

You should also add the reverse rewrite rule, as before:

ProxyPassReverse / http://www.example.com/

so that the user doesn't see the port number :8000 in the browser's location window in cases where the heavy server issues a redirect.

It is possible to use localhost in the RewriteRule above if the heavy and light servers are on the same machine. So if we sum up the above setup, we get:

RewriteEngine On
RewriteRule ^/(images|style) - [last]
RewriteRule ^/(.*) http://www.example.com:8000/$1 [proxy]
ProxyPassReverse / http://www.example.com/

In the next example, we use mod_rewrite's env flag to set an environment variable only for proxied requests. This variable can later be used by other directives.

RewriteRule ^/(images|style) - [last]
RewriteRule ^/(.*) http://www.example.com:8000/$1 [env=dyn:1,proxy]
ProxyPassReverse / http://www.example.com/

We could use this environment variable to turn off logging for dynamic requests:

LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common env=!dyn

This comes in handy when using an authentication module on the mod_perl server, such as Apache::AuthenDBI. Authenticated user credentials we're interested in logging are available only in the backend server. This technique is most useful when virtual hosts are used: logging can be turned on in the mod_perl server for this specific virtual host only.

    Part I: mod_perl Administration
    Part II: mod_perl Performance
    Part VI: Appendixes