HTACCES mod rewrite, stacking rules - .htaccess

We have a rewrite rule that looks like this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule (?!^(cms|images|js|mobile)(/.*|)$)^.*$ page.php [NC,L]
Which works as expected; if the file does not exist, forward to page.php which is a generic page and allows for pages with custom URLs.
We also want to force the www. to precede the domain: example.com -> www.example.com
For that, we use:
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
This also works, but when the two are supposed to work together:
example.com/non-existent-file
We end up getting:
www.example.bom/page.php
Which defaults to our 404 page. How do I modify these rules to work together? I have tried playing with some of the different suffic characters (ie. removing the L in the [NC,L] in an attempt to get both rules to process).
I have also tried repeating the forward to page.php lines beneath the www redirect (and removing the L suffix) with no success.
The entire HTACCESS file looks like:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule (?!^(cms|images|js|mobile)(/.*|)$)^.*$ page.php [NC,L]
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule ^(.*)$ http://www.example.com/$1 [R=302,L]
Also, is there a %{CONSTANT} I can use in place of example.com that represents the current domain?

The constant you're looking for is %{HTTP_HOST} as provided by the HTTP request. Perhaps you are looking for the variable %{SERVER_NAME} for the virtual host's default servername?
Place the hostname checking rule first, and use a RewriteCond in the page.php rule to only apply if the domain is already correct:
RewriteEngine On
# First rewrite the domain
RewriteCond %{HTTP_HOST} ^example\.com$
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
# Then rewrite the files
# At this point, the domain should already have been enforced
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule (?!^(cms|images|js|mobile)(/.*|)$)^.*$ page.php [NC,L]

Related

.htaccess rewrite domain and subdomain to directory and subdirectory

I'm trying to use my .htaccess file to point domains/subdomains to directories/subdirectories without changing the url in the browser.
Examples of the incoming url and the directory it should point to:
domain1.com/* -> /domain1.com/www/*
foo.domain1.com/* -> /domain1.com/foo/*
bar.domain1.com/* -> /domain1.com/bar/*
domain2.com/* -> /domain2.com/www/*
foo.domain2.com/* -> /domain2.com/foo/*
bar.domain2.com/* -> /domain2.com/bar/*
Here's my current attempt that is continually appending the directory/subdirectory to the url:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^(?:([^.]+)\.)?([^.]+)\.([^.]+)$ [NC]
RewriteCond %{REQUEST_URI} !^/%2\.%3/%1/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /%2.%3/%1/$1 [L,NE,P,QSA,R]
Why so complicated? The following should satisfy all requirements you listed:
RewriteCond %{HTTP_HOST} ^([^.]+)\.[^.]+$
RewriteRule ^ /www%{REQUEST_URI} [L]
RewriteCond %{HTTP_HOST} ^([^.]+)\.([^.]+)\.[^.]+$
RewriteRule ^ /%1%{REQUEST_URI} [L]
Have a try yourself at made with love
It took a little work, but that to the help of the first response, I was able to get everything working eventually.
Here's my final solution to this issue:
## Turn the rewrite engine on to allow for url mapping to work
RewriteEngine on
## Don't require a trailing "/" for directories
DirectorySlash Off
## If subdomain was missing, redirect into the "www" subdirectory
# If no %{REQUEST_FILENAME} was provided, redirect to the "www" subdirectory
RewriteCond %{HTTP_HOST} ^([^.]+)\.([^.]+)$ [NC]
RewriteRule ^$ /%2.%3/www/ [END,NC]
# If a %{REQUEST_FILENAME} was provided, redirect to the directory/file in the "www" subdirectory
RewriteCond %{HTTP_HOST} ^([^.]+)\.([^.]+)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /%2.%3/www/$1 [END,NC,QSA]
# If subdomain was given, redirect into the given subdirectory
# If no %{REQUEST_FILENAME} was provided, redirect to the given subdirectory
RewriteCond %{HTTP_HOST} ^([^.]+)\.([^.]+)\.([^.]+)$ [NC]
RewriteRule ^$ /%2.%3/%1/ [END,NC]
# If a %{REQUEST_FILENAME} was provided, redirect to the directory/file in the given subdirectory
RewriteCond %{HTTP_HOST} ^([^.]+)\.([^.]+)\.([^.]+)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /%2.%3/%1/$1 [END,NC,QSA]

.htaccess Multiple subdirectory rewriting to www-root

I have the following folder structure:
www-root
Backend
Config
Etc
Frontend
Administration
StoreFront
I would like to be able to access the directories from the main url and hiding the subdirectories in between.
So the administrative part I should be able to access like this:
http://localhost/Administration/
The main page which is stored in the subdirectory "StoreFront", I want to be able to access from the root:
http://localhost
This is the code in my .htaccess file so far:
# Store Redirect
RewriteEngine on
RewriteCond %{HTTP_HOST} ^localhost [NC]
RewriteCond %{REQUEST_URI} !^/Frontend/StoreFront
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /Frontend/StoreFront/$1
RewriteCond %{HTTP_HOST} ^localhost [NC]
RewriteRule ^(/)?$ /Frontend/StoreFront/index.php [L]
RewriteCond %{REQUEST_URI} !^/Administration
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /Frontend/Administration/$2
This code however does not work correctly. It rewrites every file except the index.php file to the Administration subdirectory. One side note: php files which are in the backend directory should remain "includable" from the frontend.
Let me tell upfront you that what you're trying to achieve is mission impossible, now let me tell you why. You have this rule:
RewriteRule ^(.*)$ /Frontend/StoreFront/$1
and down further you have:
RewriteRule ^(.*)$ /Frontend/Administration/$2
You cannot have .* going to both the places. You need to distinguish these 2 paths somehow.
It is besides the point that you have other problems also e.g.:
Not using L (LAST) flag wherever needed
Using $2 instead of $1 in 2nd rule
EDIT: Based on your comments:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteRule ^(Administration(?:/.*|))$ /Frontend/$1 [L,NC]
RewriteCond %{HTTP_HOST} ^localhost [NC]
RewriteRule ^$ /Frontend/StoreFront/index.php [L]
RewriteCond %{HTTP_HOST} ^localhost [NC]
RewriteCond %{REQUEST_URI} !^/Frontend/StoreFront
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /Frontend/StoreFront/$1 [L]

htaccess mod rewrite - how to create virtual subdomains?

I would like to create virtual subdomains through htaccess in the following way.
Entering:
http://testuser.domain.com/1/2/3/
Should be processed as:
http://www.domain.com/user.php?id=testuser&var1=1&var2=2&var3=3
HOWEVER, this rewrite should not use user.php, but index.php, in case someone enters:
http://www.domain.com or http://domain.com
This is what I got so far, however it doesn't seem to work.
Any help from a mod rewrite expert would be much appreciated.
Thanks in advance.
Options +FollowSymLinks
Options +Indexes
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^(www\.)?domain.com$ [NC]
RewriteRule ^(.*)/?(.*)/?(.*)/?$ index.php?var1=$1&var2=$2&var3=$3 [NC,QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^(www|mail).domain.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+).domain.com$ [NC]
RewriteRule ^(.*)/?(.*)/?(.*)/?$ user.php?id=%2&var1=$1&var2=$2&var3=$3 [NC,QSA,L]
Your rules are actually very close to doing what you want them to. The only problem that I can see is in your test patterns for your two RewriteRule statements. Currently, you have
RewriteRule ^(.*)/?(.*)/?(.*)/?$ ...
...which happens to be equivalent to this:
RewriteRule ^(.*)$
This is because everything past the first capture group can match nothing and still be considered a match, so that first group is greedy and matches the whole input string without needing to defer to the other parts of the pattern.
Since the capture groups shouldn't capture forward slashes anyway, as they're being used as a variable delimiter here, the straightforward fix is to change them to [^/]*, as so:
Edit: I also modified the RewriteCond set in the second group to ignore the !-f condition in the case of /index.php, which will happen if you request the subdomain without anything after the domain.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^(www\.)?domain.com$ [NC]
RewriteRule ^([^/]*)/?([^/]*)/?([^/]*)/?$ index.php?var1=$1&var2=$2&var3=$3 [NC,QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_URI} ^/index.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^(www|mail).domain.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+).domain.com$ [NC]
RewriteRule ^([^/]*)/?([^/]*)/?([^/]*)/?$ user.php?id=%2&var1=$1&var2=$2&var3=$3 [NC,QSA,L]

.htaccess redirect root to subfolder

I would like mod_rewrite to redirect all requests to non existing files and folders, and all requests to the main folder ("root") to a subfolder. So i've set it up like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f [NC]
RewriteCond %{REQUEST_FILENAME} !-d [NC,OR]
RewriteCond %{REQUEST_URI} / [NC]
RewriteRule ^(.*)$ /my/subfolder/$1 [L,QSA]
Unfortunately, it does not work: if i request example.com/public/ it redirects to my processing script (so redirecting to my/subfolder/index.php?app=public ) although the folder "public" exists.
Note that requesting domain.com/ correctly redirects to my/subfolder/index.php
Why is that?
it does not work because your last condition is not matching only the root but any uri that has / in it, which is basically everything. Try the following instead:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d [OR]
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^(.*)$ /my/subfolder/$1 [L,QSA]
Note that [NC] is not needed as you are not trying to match any alphabets, so "No Case" is not really needed.
Hope it helps.

.htaccess redirect main domain?

How can I redirect requests to mydomain.tld/somepage.ext to mydomain.tld/mydomain/somepage.ext? I have subdomains like subdomain.mydomain.tld that I don't want to be affected by this.
I can't seem to get it to work right. I'm trying this:
RewriteEngine on
RewriteCond %{HTTP_HOST} mysite.com
RewriteCond %{REQUEST_URI} !^/mysite
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) /mysite/$1
But it isn't redirecting anything at all.
I also want to exclude one or two folders from this rule.
This seems to be working...
RewriteEngine on
RewriteCond %{HTTP_HOST} mysite\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/mysite/ # but I don't see why this line is needed when I've used [L] below
RewriteCond %{REQUEST_URI} !^/ignored_folder/
RewriteRule .* /mysite/$0 [QSA,L]
At least for now.

Resources