Bug 31210 - Problematic competition between mod_rewrite and mod_dir
Summary: Problematic competition between mod_rewrite and mod_dir
Status: RESOLVED DUPLICATE of bug 40373
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_dir (show other bugs)
Version: 2.0.50
Hardware: Other Linux
: P3 major (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL: http://rewritetest.queso.org/
Keywords:
Depends on:
Blocks:
 
Reported: 2004-09-14 03:10 UTC by Jason Levine
Modified: 2008-12-13 14:12 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jason Levine 2004-09-14 03:10:35 UTC
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?
Comment 1 Sam Greenfield 2004-09-14 18:59:28 UTC
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.
Comment 2 Bob Ionescu 2008-12-13 14:12:52 UTC

*** This bug has been marked as a duplicate of bug 40373 ***