Initially written in 2004.

I've seen a number of examples of how to use Apache's mod_rewrite to do various fun things. Something I needed to do, which was fairly trivial but not explicitly covered in any of the online material I found, was redirect requests based on referer.

This can be done either in the server's global configuration (httpd.conf) or through an .htaccess file. The only requirement is that the mod_rewrite module is loaded.

In my case, someone had misbehaved and linked in-line images directly off my server, so I figured it would be amusing if I redirected requests for those particular images to a more "shocking image" as long as they were being loaded as a part of the offending page (i.e. the images would load normally if linked from my own page)

In an appropriately placed .htaccess file:

RewriteEngine on
RewriteCond %{HTTP_REFERER} ^http://www\.example\.com [NC]
RewriteRule \.png [R]


RewriteEngine on

This enables mod_rewrite operation. Without it, the rewrite directives have no effect.

RewriteCond %{HTTP_REFERER} ^http://www\.example\.com [NC]

A RewriteRule directive may be preceded by multiple RewriteCond directives, all of which must match for the RewriteRule to fire.

%{HTTP_REFERER} is the string we're matching against: the referer header in the HTTP request.

^http://www\.example\.com is the regular expression we're matching. ^ matches the beginning of the line (meaning we're looking for something at the beginning of the string). A period matches any character, so to match a literal period, it must be escaped with a backslash.

[NC] means No Case. The matching will be case insensitive.

RewriteRule \.png [R]

The RewriteRule itself has a pattern. In this case looking for the substring ".png" in the request URI.

The URL is where the client will be diverted.

[R] means the response sent should be an HTTP 302 redirect. mod_rewrite can masquerade different files under the requested URI, but in this case I wanted a redirect.

When I loaded the offending page, all the images were redirected, as expected. Then I went and loaded the original page, and the images were still the redirected ones because the browser had cached the redirect.

A forced reload fixed the problem, but if you want to be really extreme about it, you can load the mod_expires module and add something like the following to the same .htaccess file:

<FilesMatch "\.png">
 Header set Cache-Control: must-revalidate
 ExpiresActive On
 ExpiresDefault "access plus 0 seconds"

What this is supposed to do is force the browser, and any web caches on the way to your server, to re-validate the files in question (in this case files with ".png" in the filename) every time they are loaded. This will cause extra traffic for you, but ideally most requests will be answered with an HTTP 304 Not Modified instead of the images being re-transmitted on every reload.

Note that this isn't guaranteed to work since many browsers and web caches are utterly braindead, not to mention in severe violation of the HTTP standard. (and most everyone doesn't know or care. The interweb sucks like that sometimes)

Finally, I'd like to say in my defense, that I don't normally react like this. The interweb is all about people linking to other people. This sort of thing generally isn't a problem, except that in this particular case, it had been done in a totally inconsiderate and inappropriate way:

The person in question, who I have sorted things out with since, had plagiarised a page I wrote, stripped off my copyright, and linked in-line images off my webserver.

Further reading: mod_rewrite documentation.