I seem to have discovered what I think is a bug in the interaction between mod_dir and mod_rewrite (at least as it functions on a per-directory basis) today. It didn't exist on my old installation (1.3.27); when I moved a site over to my new installation (2.0.50), the bug reared its head. Say that you have a server with two files and a directory in its DocumentRoot, index.php, stuff.txt, and /stuff. One function of index.php is to include the text of a file passed in as the query string -- e.g., /index.php?stuff.txt would include the text of the file stuff.txt. Now, say that the following .htaccess file existed: RewriteEngine on RewriteRule ^(stuff)$ /index.php?$1.txt [L] which served to allow people to shorten URLs; instead of /index.php?stuff.txt, that would allow them to type /stuff and have the rewriting take place internal to httpd. The problem here is that there's *also* a directory named /stuff, and while mod_rewrite sees a match with the URI "/stuff", mod_dir sees a potential directory name expansion from "/stuff" to "/stuff/". And the way that it all comes together is just broken -- the end result is "/stuff/?stuff.txt", which is just wrong. The relevant directory definition in my httpd.conf file is: <Directory (DocumentRoot directory)> Options FollowSymLinks RewriteEngine on AllowOverride FileInfo AuthConfig Limit Indexes </Directory> The virtual host definition is: <VirtualHost 204.193.152.163> ServerName rewritetest.queso.org DocumentRoot (DocumentRoot directory) CustomLog logs/rewrite-access_log combined ErrorLog logs/rewrite-error_log DirectoryIndex index.php RewriteEngine on SuexecUserGroup rewrite rewrite </VirtualHost> There aren't any other directives in the httpd.conf file that would affect the behavior of the host; the order that the LoadModule statements is that mod_dir is loaded before mod_rewrite. (While I know that the new API structure is supposed to make it meaningless what order they are loaded, I also know that there have been a few edge cases in Bugzilla that showed that it can matter at times.) I've put together a test website that shows the problem -- it's (shockingly) located at http://rewritetest.queso.org/, and there's a slightly more fleshed-out example there, along with all the relevant sources and log files. Am I right that this is a bug, or is there something I'm missing in how one configures mod_rewrite and/or mod_dir?
mod_rewrite gets the first stab at processing the request. If we look at the rules described in the bug report, mod_rewrite first changes the URI "/stuff" into two parts: the base URI "/index.php" and the arguments "stuff.txt". mod_rewrite can glue these back together, but the component parts are stored in the request object. What looks like is happening is that "/stuff" gets left as the URI, the file gets set to "/index.php", and the arguments get set to "stuff.txt". This structure gets passed to mod_dir, which adds a slash to the URI and glues on the argument resulting in an external redirect of "/stuff/?stuff.txt". Based on the documentation, I believe this is the correct behavior even if it is neither desirable nor intuitive. I believe that the way to not encounter this behavior would be to set the passthrough flag. If PT is set, "/index.php" should replace "/stuff" as the request URI, and the argument "stuff.txt" still is added to the URI. Unfortunately, it looks like PT does not work with a per-directory configuration. The workaround is to move the rewrite directive from the .htaccess or <location> config locations and to a server location. This comment from the source of mod_rewrite.c is interesting: > /* if someone used the PASSTHROUGH flag in per-dir > * context we just ignore it. It is only useful > * in per-server context > */ I think this behavior is could be a bug in mod_rewrite. Alternatively, this behavior should be documented outside of the source code.
*** This bug has been marked as a duplicate of bug 40373 ***