Insane Apache RewriteRules

I have just spent a few fun hours fighting Apache rewrite rules in an .htaccess file. It turns out that temporary redirects just work, but permanent redirects require RewriteBase! Frankly, this is insane.

Suppose, I have my web site test.ikriv.com that lives in /var/www/html on the server disk. Let’s say I have the following contents in /var/www/html/.htaccess:

RewriteEngine on
RewriteRule ^(.*)\.temp$ $1.html
RewriteRule ^(.*)\.perm$ $1.html [R=permanent]

If type in the browser https://test.ikriv.com/file.temp, I see the contents of /var/www/html/file.html, as expected. The server does not report the redirect back to the browser, but quietly serves file.html instead of file.temp.

If, however, I type https://test.ikriv.com/file.perm I get redirected to https://test.ikriv.com/var/www/html/file.html and then get error 404, telling me such file is not available.

The root cause seems to be that in both cases mod_rewrite converts the incoming URL into var/www/html/file.html. In the first case it just serves this file, which works great, but in the second case it returns the file path to the browser, who interprets that as a URL, and it all goes downhill from there. To fix the problem, I must add RewriteBase to the .htaccess file. To be fair, Apache docs do say it is required, but they don’t say it is required only for permanent redirects. Most sane people would assume that if temporary redirects work, permanent redirects will work as well, but it is not the case.

RewriteEngine on
RewriteBase /
RewriteRule ^(.*)\.temp$ $1.html
RewriteRule ^(.*)\.perm$ $1.html [R=permanent]

Note that I need to specify the base URL of the directory. I.e., if I have .htaccess file in some other directory, I must add RewriteBase /that/dir/url. This is quite inconvenient, because

a) as I move directories around, RewriteBase may become broken, and
b) if a directory can be reached via multiple URLs, I will have to pick one as RewriteBase, with possible security issues and other inconveniences.

Why can’t we just make things work without surprises? That’s obviously, a rhetoric question: one’s person surprise is another person completely obvious and logical behavior.

8 Comments


  1. Why do you define redirect rules in a separate files instead of defining all redirect logic in web application code (C#)?

    Reply

  2. Why don’t they eat cake?
    These are static files. There is no web application. And most definitely no C#: it’s a LAMP machine.

    Reply

  3. > The server does not report the redirect back to the browser, but quietly serves file.html instead of file.temp.

    Is that what you call “temporary redirect”? Usually what you described is called “URL routing”.
    Usually under “temporary redirect” we understand “HTTP 302 redirect” which is distinct from “HTTP 301 redirect” (AKA “Permanent Redirect”).

    > It turns out that temporary redirects just work

    Now it is not clear what exactly works in your case: “URL routing” or “HTTP 302 redirect”.

    Reply

    1. Sorry for the long delay. Temporary redirect is not visible to the client, it is done quietly on the server side. Permanent redirect results in code 301 by default.

      I bother about static files, because they are in Google results and what-not, and I want to keep the old URLs functional.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *