Search code examples
apache.htaccessmod-rewritelampapache2.2

apache mod_rewrite: How to add different rewrite rules for same directory depending on file existence in other directory?


I'm currently having a bit of trouble to configure the rewrite rule(s) in a .htaccess file for an Apache 2.2 server with mod_rewrite. Here's the general idea of what I want to do:

Let's say the server domain is example.com/, and all requests to example.com/abc/ and paths below that directory shall be rewritten. There are two scenarios:

  1. Requests directly to example.com/abc/ or example.com/abc/index.php shall become requests to example.com/index.php with an additional parameter to indicate the original directory of the request. To give a few examples:

    • example.com/abc/ ==> example.com/abc/index.php?directory=abc
    • example.com/abc/?foo=1&bar=2 ==> example.com/abc/index.php?directory=abc&foo=1&bar=2
    • example.com/abc/?a=b&c=d ==> example.com/abc/index.php?directory=abc&a=b&c=d
    • ... and so on
  2. Requests to files within example.com/abc/ shall become requests to files in example.com/, if these files exist there. parameter to indicate the current directory. To give a few examples:

    • example.com/abc/image.png ==> example.com/image.png (if the later file exists)
    • example.com/abc/sub/file.css ==> example.com/sub/file.css (if the later file exists)
    • example.com/abc/foo/bar/baz/name.js ==> example.com/foo/bar/baz/name.js (if the later file exists)
    • ... and so on.

The content of my .htaccess currently looks similar to this:

RewriteEngine on
Options FollowSymLinks
RewriteBase /

# rule for files in abc/: map to files in root directory
RewriteCond $1 -f
RewriteRule ^abc/(.*?)$ $1

# rule for abc/index.php: map to index.php?directory=abc&...
RewriteCond $1 !-f
RewriteRule ^abc/(.*?)$ index.php?directory=abc&$1 [QSA]

The later rule seems to work, requests to example.com/abc/index.php get rewritten as intended. However, that does not work for files in the abc/ directory. Any hints on what I am doing wrong here and how to solve that problem are appreciated. What changes have to be applied to .htaccess to get things working as described?


Solution

  • I've found a working solution:

    RewriteEngine on
    Options FollowSymLinks
    RewriteBase /
    
    # rule for file in abc/: map them to files in document root
    RewriteCond %{DOCUMENT_ROOT}/$1 -f
    RewriteRule ^abc/(.*?)$ %{DOCUMENT_ROOT}/$1 [L]
    
    # rule for abc/index.php: map to index.php?directory=abc&...
    RewriteRule ^abc/(.*?)$ %{DOCUMENT_ROOT}/index.php?directory=abc&$1 [QSA,L]
    

    The two main differences are:

    • using the [L] flag to indicate that no further rules should be considered after a rule matches - that was probably the problem why only the last rule seemed to work.
    • prefacing locations in the condition and the rewrite location with %{DOCUMENT_ROOT} to get absolute paths.