I thought I knew how Drupal's "clean" URLs interacted with Apache's mod_rewrite and the file system. The logical flow seems obvious after observing the following code in .htaccess
:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
The Apache 1.3 documentation for RewriteCond
says:
'-d' (is directory) Treats the TestString as a pathname and tests if it exists and is a directory.
'-f' (is regular file) Treats the TestString as a pathname and tests if it exists and is a regular file.
The code checks for a file or directory that matches the request and, if neither is found, rewrites the clean URL such that Drupal can handle it. But all is not as it seems. I expected RewriteCond %{REQUEST_FILENAME} !-f
to require a complete match between the file system and the URL before failing.
Here is the caveat:
Apache will not rewrite a clean URL if Apache finds a file at the base of the Drupal installation whose name matches everything up to the first slash (/) in the request. As an added twist, Apache does the same if the file ends with .txt
, .diff
, and perhaps some other common extensions.
Here is how to demonstrate the quirk: