Apache RewriteRule help

Hope this is the correct section for this.

I´m trying to setup some apache Rewrite Rules that will let me do the following:

If we go to the url www.mydomain.com/dir1/dir2/dir3/myfile.php , if myfile.php does not exist, then it tries for /dir1/dir2/myfile.php and if that doesn´t exist it tries for /dir/myfile.php and if that doesn´t exist then it defaults to /standard/myfile.php.

Also in the case of mydomain.com/dir1/dir2/dir3/ it does as above but for index.php ending in /standard/index.php if it wasn´t found in the other directories.

I have it working so that if mydomain.com/dir1/dir2/dir3/myfile.php doesn’t exist it uses /standard/myfile.php, with:

RewriteCond %{DOCUMENT_ROOT}/$1/$2 !-f
RewriteRule /(.+)/(.*)$ /section/$2 [L,QSA]

but i can´t figure out the intermediate recursion, the following i tried does not work at all:

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4 !-f
RewriteRule /([^/]+)/([^/]+)/([^/]+)/([[^/]]*)$ /$2/$4 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3 !-f
RewriteRule /([^/]+)/([^/]+)/([[^/]]*)$ /$1/$3 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2 !-f
RewriteRule /([^/]+)/([[^/]]*)$ /section/$2 [L,QSA]

Anyone have any tips or advice for me? would greatly appreciate it.

Thank you!

dan,

The reason is obvious!

/([^/\\.]*)(\\.php|\\.html)?$

is requiring a non / and non-dot (which should NOT be escaped in the character range definition) but with an optional extension. In other words, it’s doing exactly as you are directing.

BTW, PLEASE test to be sure that the $dir values in the path are FORWARD referenced properly and not using the last “drive through” of the mod_rewrite code.

Regards,

DK

one issue is that if you type the url /dir1/dir2/

it doesn’t work, but /dir1/dir2/index.php does… the issue is obviously in

/([^/\.]*)(\.php|\.html)?$

But why? doesn’t this allow the filename to be empty and the extension to be neither of the listed with the ? delimiter. How would i say .php or .html or empty??

Thanks!

Don’t forget to escape the . in (.php) :



#
# If the user requests a 3rd level file (/dir1/dir2/dir3/file.php) and it doesn´t exist
# - if /dir1/dir2/file.php exists then display that page
# - if above does not exist then use /dir1/file.php
# - if the above does not exist then use /default/file.php
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$4$5 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/([^/.]+)([COLOR=RED]\\[/COLOR].php)$ /$1/$2/$4$5 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$4$5 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/([^/.]+)([COLOR=RED]\\[/COLOR].php)$ /$1/$4$5 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
RewriteCond %{DOCUMENT_ROOT}/default/$4$5 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/([^/.]+)([COLOR=RED]\\[/COLOR].php)$ /default/$4$5 [L,QSA]

# If no file is specified (/dir1/dir2/dir3/) repeat but force checking for index.php
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/$ /$1/$2/index.php [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/$ /$1/index.php [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/default/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/$ /default/index.php [L,QSA]

#
# If the user requests a 2nd level file (/dir1/dir2/file.php) and it doesn´t exist
# - if /dir1/file.php exists then display that page
# - if the above does not exist then use /default/file.php
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3$4 !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$3$4 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)([COLOR=RED]\\[/COLOR].php)$ /$1/$3$4 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3$4 !-f
RewriteCond %{DOCUMENT_ROOT}/default/$3$4 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)([COLOR=RED]\\[/COLOR].php)$ /default/$3$4 [L,QSA]

# If no file is specified (/dir1/dir2/) use index.php
RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/$1/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/$ /$1/index.php [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/default/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/$ /default/index.php [L,QSA]

#
# If the user requests a 1st level file (/dir1/file.php) and it doesn´t exist
# - if /default/file.php exists use it
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2$3 !-f
RewriteCond %{DOCUMENT_ROOT}/default/$2$3 -f
RewriteRule ^/([^/.]+)/([^/.]+)([COLOR=RED]\\[/COLOR].php)$ /default/$2$3 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/default/index.php -f
RewriteRule ^/([^/.]+)/$ /default/index.php [L,QSA]

Other than that, there is probably something you can do with the skip flag to make it a bit shorter if you wish (Look for skip|S=num on that link) :slight_smile:

dan,

IMHO, you have a mess with all that “lazy regex” (probably justified) so my advice is (1) use [ code ] … [ /code ] bulletin board code to set your code apart from the text and (2) ALWAYS go from the most specific to the most general (the order you have in the second set).

Your “recursion” set will merely repeat the section/yadda-yadda in a loop.

TIP: Define verbally (or write it down) EXACTLY what you’re trying to do, i.e., preserve directories enroute to a specific filename, test for existence then redirect. It seems as if you have that covered PROVIDED the $n values can be used as a forward reference (which I don’t believe they can - testing is required on my part).

Regards,

DK

great stuff, got it working! but is there anyway i can make it more generic?? and not restricted to having to have a block for each depth …??

Thanks for your help dklynn! Much appreciated.




#
# If the user requests a 3rd level file (/dir1/dir2/dir3/file.php) and it doesn´t exist
# - if /dir1/dir2/file.php exists then display that page
# - if above does not exist then use /dir1/file.php if it exists
# - if the above does not exist then use /default/file.php
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
#check if /dir1/dir2/file.php exists 
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$4$5 -f
RewriteRule ^/([^/\\.]+)/([^/\\.]+)/([^/\\.]+)/([^/\\.]*)(\\.php|\\.html)?$ /$1/$2/$4$5 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
#check if /dir1/file.php exists 
RewriteCond %{DOCUMENT_ROOT}/$1/$4$5 -f
RewriteRule ^/([^/\\.]+)/([^/\\.]+)/([^/\\.]+)/([^/\\.]*)(\\.php|\\.html)?$ /$1/$4$5 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
#check if /default/file.php exists
RewriteCond %{DOCUMENT_ROOT}/default/$4$5 -f
RewriteRule ^/([^/\\.]+)/([^/\\.]+)/([^/\\.]+)/([^/\\.]*)(\\.php|\\.html)?$ /default/$4$5 [L,QSA]


#
# If the user requests a 2nd level file (/dir1/dir2/file.php) and it doesn´t exist
# - if /dir1/file.php exists then display that page
# - if the above does not exist then use /default/file.php
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3$4 !-f
#check if /dir1/file.php exists 
RewriteCond %{DOCUMENT_ROOT}/$1/$3$4 -f
RewriteRule ^/([^/\\.]+)/([^/\\.]+)/([^/\\.]*)(\\.php|\\.html)?$ /$1/$3$4 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3$4 !-f
#check if /default/file.php exists
RewriteCond %{DOCUMENT_ROOT}/default/$3$4 -f
RewriteRule ^/([^/\\.]+)/([^/\\.]+)/([^/\\.]*)(\\.php|\\.html)?$ /default/$3$4 [L,QSA]

#
# If the user requests a 1st level file (/dir1/file.php) and it doesn´t exist
# - if /default/file.php exists use it
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2$3 !-f
#check if /default/file.php exists
RewriteCond %{DOCUMENT_ROOT}/default/$2$3 -f
RewriteRule ^/([^/\\.]+)/([^/\\.]*)(\\.php|\\.html)?$ /default/$2$3 [L,QSA]

thanks for the reply, basically i´m not sure how to do the if statements in the apache file as rewrite conditions. Basically what i want is:

Given a url mydomain.com/dir1/dir2/dir3/myfile.php

IF /dir1/dir2/dir3/myfile.php doesn´t exist THEN
IF /dir1/dir2/myfile.php doesn´t exist THEN
IF /dir1/myfile.php doesn´t exist THEN
IF /generic/myfile.php doesn´t exist THEN
use /404.php
ELSE use /generic/myfile.php
ELSE use /dir1/myfile.php
ELSE use /dir1/dir2/myfile.php
ELSE use /dir1/dir2/dir3/myfile.php

Can any one lend a hand?

Fixed it, and seems to be behaving as required.

Many thanks for your help. He’res the finally code in case anyone wants to do something similar, will in future try to make it more generic and will repost.






#
# If the user requests a 3rd level file (/dir1/dir2/dir3/file.php) and it doesn´t exist
# - if /dir1/dir2/file.php exists then display that page
# - if above does not exist then use /dir1/file.php
# - if the above does not exist then use /default/file.php
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$4$5 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/([^/.]+)(.php)$ /$1/$2/$4$5 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$4$5 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/([^/.]+)(.php)$ /$1/$4$5 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/$4$5 !-f
RewriteCond %{DOCUMENT_ROOT}/default/$4$5 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/([^/.]+)(.php)$ /default/$4$5 [L,QSA]

# If no file is specified (/dir1/dir2/dir3/) repeat but force checking for index.php
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/$ /$1/$2/index.php [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/$ /$1/index.php [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/default/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)/$ /default/index.php [L,QSA]

#
# If the user requests a 2nd level file (/dir1/dir2/file.php) and it doesn´t exist
# - if /dir1/file.php exists then display that page
# - if the above does not exist then use /default/file.php
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3$4 !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$3$4 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)(.php)$ /$1/$3$4 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/$3$4 !-f
RewriteCond %{DOCUMENT_ROOT}/default/$3$4 -f
RewriteRule ^/([^/.]+)/([^/.]+)/([^/.]+)(.php)$ /default/$3$4 [L,QSA]

# If no file is specified (/dir1/dir2/) use index.php
RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/$1/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/$ /$1/index.php [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/$2/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/default/index.php -f
RewriteRule ^/([^/.]+)/([^/.]+)/$ /default/index.php [L,QSA]

#
# If the user requests a 1st level file (/dir1/file.php) and it doesn´t exist
# - if /default/file.php exists use it
# Last stop 404.php 
#
RewriteCond %{DOCUMENT_ROOT}/$1/$2$3 !-f
RewriteCond %{DOCUMENT_ROOT}/default/$2$3 -f
RewriteRule ^/([^/.]+)/([^/.]+)(.php)$ /default/$2$3 [L,QSA]

RewriteCond %{DOCUMENT_ROOT}/$1/index.php !-f
RewriteCond %{DOCUMENT_ROOT}/$1/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/default/index.php -f
RewriteRule ^/([^/.]+)/$ /default/index.php [L,QSA]




Dan,

Sure, get the filename and directories then cycle through

%{DocumentRoot}/dir1/dir2/dir3/filename -f => redirect else
%{DocumentRoot}/dir1/dir2/filename -f => redirect else
%{DocumentRoot}/dir1/filename -f => redirect else
go to default script.

Regards,

DK