Striezel Striezel - 3 months ago 11
Apache Configuration Question

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?

Answer

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.