I currently have the following in a htaccess file which redirects certain requests to the requested domain's individual folder if the file does not exist in the root..
RewriteRule ^contact/?$ ASSETS/%{HTTP_HOST}/contact.php
RewriteCond %{REQUEST_URI} !^/ASSETS/%{HTTP_HOST}/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /ASSETS/%{HTTP_HOST}/$1
RewriteCond %{HTTP_HOST} ^(www.)?%{HTTP_HOST}$
RewriteRule ^(/)?$ ASSETS/%{HTTP_HOST}/index.php [L]
Which works fine when my domain folders are named like /ASSETS/www.domain1.com, /ASSETS/www.domain2.com etc
However, I've built a lot of my code already with the assumption that the folders will be labeled /ASSETS/domain1.com etc (domain name, minus the www.)
I'm thinking there is a way to get the domain name from %{HTTP_HOST} into a new variable and strip out the www. part (like an str_replace or something), but all the answers I have found are around a basic redirect all to www. or no www. which isn't going to work as I still want users to access the site from the forced www. version.
I was previously running the rules for each domain individually with a RewriteCond %{HTTP_HOST} ^(www.)?domain1.com$ but there are so many domains now, it's not feasible to do it for each one.
Hope you can help! Thanks in advance.
You can capture the needed host part with a RewriteCond and use it as %1 in the RewriteRule
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$
RewriteRule ^$ ASSETS/%1/index.php [L]
An alternative solution at the file system level (without htaccess) might be symbolic links. Instead of extracting the necessary host part, have symbolic links to the real directory, e.g.
- ASSETS -+-domain1.com (directory)
|
+-www.domain1.com -> domain1.com (symbolic link)
|
+-domain2.com (directory)
|
+-www.domain2.com -> domain2.com (symbolic link)
To illustrate the different back references, see another example
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$
RewriteRule ^foo/(.+)$ $1/%1/index.php [L]
Here we have a $1, which takes the capture group from the RewriteRule pattern foo/(.+).
And we have a %1, which takes the capture group from the previous RewriteCond (?:www\.)?(.+).
Note that (?:...) is a non-capturing group. This is why we use %1 instead of %2.
Related
BEFORE I installed SSL things were working perfectly!! Here is the code I have in my root webserver .htaccess file:
Options +MultiViews
RewriteEngine On
RewriteCond %{HTTP_HOST} andrea\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://andrea.com/$1 [R,L]
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
It works and it does exactly what I want it to do. So if I go to for example:
www.andrea.com/account
it accesses "www.andrea.com/account.php". Which is what I want.
I do however have a folder in root called "products". There is another ".htaccess" file in that folder and I don't know which of these 2 must be changed to make the following thing below work.
When you go to this url:
http:____/products/view/Hello/Goodbye
I want it to access "view.php" in the 'products' folder and in that php file I could do this:
$id = $_GET["id"]; // This would have "Hello"
$cat = $_GET["cat"]; // This would have "Goodbye"
And this works well when I use this htaccess in the "products" folder:
RewriteEngine on
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2
The problem with this code above is, if I go to:
http:____/products/Hello/Goodbye
I want it to access the "index.php" that is in "products" folder. But instead it goes to "view.php" instead!! It's like the htaccess code above forced all to go to view.php (which should only be done if I have the "view/____" in the url.
I want the url above to go to "index.php" in the "products" folder and in that file I should be able to access ID and CAT variables.
Any ideas of what to change in my .htaccess file? Sorry I spent over 2 hours I don't understand a single line at the bottom of my code but it doesn't work :/
Options +MultiViews
First off, you should disable MultiViews. In my answer to your earlier question, my suggestion to use MultiViews was strictly an "alternative" method in the context of your question. You cannot use both methods (mod_rewrite and MultiViews) to work with extensionless URLs. And since you are now wanting to do more things and pass parameters, MultiViews will only create conflicts. (MultiViews will likely "win" and no parameters get passed.)
Also, do you specifically need the additional .htaccess file in the /products subdirectory? It will be (arguably) easier to have a single .htaccess file in the document root. This will avoid having to repeat the HTTP to HTTPS redirect (although you've not actually included an HTTP to HTTPS redirect in the subdirectory .htaccess file?).
# /products/.htaccess
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2
This directive matches both view/Hello/Goodbye and Hello/Goodbye, which explains why everything is being written to your view.php script. However, it's not actually doing what you say either - which is puzzling. If you request /products/view/Hello/Goodbye then it will rewrite the request to /products/view.php?id=view&cat=Hello/Goodbye - which is not the intention (unless MutliViews is enabled, in which case no parameters will be passed at all).
You need to actually check for views in the requested URL-path before attempting to rewrite to views.php. And if views is not present then rewrite to index.php instead. This "conditional branching" can be achieved by simply arranging the directives in the order of "more specific" rules first.
For example, in your root .htaccess file try the following. (And remove the /products/.htaccess file altogether.)
# Ensure that MultiViews is disabled
Options -MultiViews
RewriteEngine On
# HTTP to HTTPS canonical redirect
RewriteCond %{HTTP_HOST} example\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule (.*) https://example.com/$1 [R=301,L]
# Abort early if the request already maps to (or looks like) a file or directory
RewriteCond %{REQUEST_URI} \.\w{2,4}$ [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# 1. Rewrite "/products/view/<id>/<cat>" to "/products/view.php?id=<id>&cat=<cat>
RewriteRule ^(products/view)/([^/]*)/?(.*) $1.php?id=$2&cat=$3 [L]
# 2. Rewrite "/products/<id>/<cat>" to "/products/index.php?id=<id>&cat=<cat>
RewriteRule ^(products)/([^/]*)/?(.*) $1/index.php?id=$2&cat=$3 [L]
# 3. Extensionless URLs for other requests
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
The order of the 3 rules above is important. The most specific rule is first. Including the L flag to prevent further (unnecessary) processing.
Note that, as per your original directives, for a request of the form /products/view/Hello/Goodbye (or /products/Hello/Goodbye), the Hello/Goodbye part is entirely optional and will naturally result in the id and cat URL parameters being set, but empty.
Also, as per your original directives, a request of the form /products/view/Hello/Goodbye/foo/bar/baz will result in the cat URL parameter being set to Goodbye/foo/bar/baz (anything that follows the initial path segment).
You do not necessarily need to check that a request maps to a file or directory (which is relatively expensive) if you make your regex more specific and only match what you need to match. For example, your regex /([^/]*)/?(.*) currently match pretty much anything. But if your <id> and <cat> variables can only consist of lowercase letters (for example) then this could avoid the need for the filesystem checks.
Other notes:
Do you need to check the hostname in the HTTP to HTTPS redirect? Do you host multiple domains? Otherwise the condition that checks against the HTTP_HOST server variable is not required.
You can use the following rule to rewrite /products/Hello/Goodbye to /products/index.php .
RewriteRule ^Hello/GoodBye/?$ /product/index.php?id=hello&cat=Goodbye [L,NC]
Here is your complete /product/.htaccess .
RewriteEngine on
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
#rewrite /products/Hello/GoodBye to /products/index.php
RewriteRule ^Hello/GoodBye/?$ /products/index.php?id=Hello&cat=Goodbye [L,NC]
###################
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2
I use a hostmonster account to host several websites. Each site lives in a subdirectory of my public_html folder in order to keep me sane when administering the sites. So for example my primary domain lives in public_html/joshorndorff.com
I have set up my .htaccess file in my public_html folder to redirect traffic into the appropriate subdirectory as suggested by https://my.hostmonster.com/cgi/help/347
# .htaccess main domain to subdirectory redirect
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?joshorndorff.com$
RewriteCond %{REQUEST_URI} !^/joshorndorff.com/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /joshorndorff.com/$1
RewriteCond %{HTTP_HOST} ^(www.)?joshorndorff.com$
RewriteRule ^(/)?$ joshorndorff.com/index.php [L]
Then in my subdirectory I use the drupal default .htaccess as uncomment the lines that redirect to the www. subdomain. The relevant lines from the subdirectory are:
RewriteCond %{HTTP_HOST} ^joshorndorff\.com$ [NC]
RewriteRule ^(.*)$ http://www.joshorndorff.com/$1 [L,R=301]
This all works fine, but there are two problems I still have.
When I type www.joshorndorff.com/joshorndorff.com/index.php no rewriting happens and the domain name and subdirectory (which is named the same as the domain name) both show up in the address bar
When I enter my static ip address (67.20.112.212) in the address bar I am not redirected to my site, but rather I see the index.html that I put in public_html for testing purposes/
I've read the excellent tutorial on mod_rewrite at http://www.addedbytes.com/articles/for-beginners/url-rewriting-for-beginners/ but still can't get either of the two issues fixed. I would love any suggestions or working code, but even more would love to understand why
RewriteRule ^joshorndorff.com/ / [NC]
does not do what I expect.
Thanks so much!
-Josh Orndorff
In the examples I provided below I replaced your domain with example.com.
# 1
The way you have the rewrite condition/rule written this is expected behavior. To prevent it from happening, you need to add another condition/rule set that matches the specific subdirectory and rewrites it. This must be added before your other rule within the Drupal .htaccess file in your subdirectory.
Otherwise, you're basically telling it to match the domain name, and pass everything else as your first variable: $1, including the subdirectory.
Here is an example using example.com/example.com/index.php:
RewriteCond %{HTTP_HOST} ^example\.com\/example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
# 2
Your second issue, browsing by IP, is happening because your rewrite rules only matches your domain name.
If you want to redirect the IP to your site's domain name, you would need match the host, in your case the IP address, then rewrite to your domain:
RewriteCond %{HTTP_HOST} !^(.*)$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
If you truly want browsing by IP to work, you could do something like this:
RewriteCond %{HTTP_HOST} !^(.*)$ [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]
Please note that in addressing #2, you would have to adapt the rules I showed in #1 for use with IP address, and still match the subdirectory. Additionally, my examples aren't exact replacements for your rules, but should show enough for you to adapt it fairly easily. You might be able to just add your URI and file conditions to #1, but I did not test it specifically.
I have set up CakePHP on shared hosting, within a sub-directory (cakeDomain). Using htaccess in the root directory (mainDomain), I have pointed another domain to it (cakeDomain), like so:
# /.htaccess
# cakeDomain redirect rules
RedirectMatch 301 ^/cakeDomain/$ http://cakeDomain.com/
# handle domain root and skip subfolders
RewriteCond %{HTTP_HOST} cakeDomain.com
RewriteCond %{REQUEST_URI} !^/cakeDomain/
RewriteCond %{REQUEST_URI} \..+$
RewriteRule ^(.*)$ cakeDomain/$1 [L]
# add trailing slash to subfolders (eg abc to: abc/)
RewriteCond %{HTTP_HOST} cakeDomain.com
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} [^/]$
RewriteRule ^(.*)$ $1/ [L,R=301]
# handle files in subfolders
RewriteCond %{HTTP_HOST} cakeDomain.com
RewriteCond %{REQUEST_URI} !^/cakeDomain/
RewriteRule ^(.*)$ cakeDomain/$1/ [L]
RewriteCond %{HTTP_HOST} www.mainDomain.com/cakeDomain/
RewriteRule %{HTTP_HOST} www.cakeDomain.com [L]
Visiting mainDomain.com/cakeDomain correctly redirects you to cakeDomain.com
CakePHP's files are stored as so:
/cakeDomain/app/...
/cakeDomain/lib/...
/cakeDomain/...
etc.
Visiting cakeDomain.com brings up the correct front page but all of the links have the installed directory prepended to them:
cakeDomain.com/cakeDomain/controller/action/param1
Instead of:
cakeDomain.com/controller/action/param1
Any ideas how to fix this?
Please note, from my many searches, that it appears many people immediately suggest virtual hosts. This is not an option here; my hosting is a virtual host. I presume this solution requires htaccess and/or routing tricks. Thank-you in advance for any help you can provide.
Basically, you're putting website B (Cake) inside the public web directory of website A (Maindomain).
I would REALLY discourage you to do so because this way all 'private' CakePHP directories are also inside your public web directory (for example cakeDomain/app/tmp/logs/error.log). Please check properly if those locations are secured properly
Dou you have access to the directories 'outside' your public webfoot?
Having said that, this may be of help:
http://cookingwithcakephp.blogspot.nl/2008/04/installing-cakephp-into-subdirectory.html
I am dealing with following problem:
I have one main domain "example.com" and multiple subdomains:
one.example.com
two.example.com
three.example.com
etc. on server.
I have content for this subdomains in folders:
./one/ -> one.example.com
./two/ -> two.example.com
./three/ -> three.example.com
etc.
So to serve content from these folders to subdomains, I use following htaccess file:
RewriteCond %{HTTP_HOST} ^one.example.com [NC]
RewriteCond %{REQUEST_URI} !^/one/.*
RewriteRule ^(.*) /one/$1 [L]
It works fine, but my content for subdomains is also accessable from URL:
one.example.com/one/my-content
such as
one.example.com/my-content
etc. So it is duplicite.
This is one problem I need to solve.
Second is, that content for example.com is accessable from
whatever.example.com
(a.example.com, b.example.com etc.)
so again duplicite.
So my question is: how to redirect/disable URLs that are creating duplicite?
Thanks a lot, I've tried a lot of versions of code, but with no effect.
I solved this issue by redirecting all requests to a subdomain to that folder and all requests to the base domain to another, like this:
RewriteCond %{HTTP_HOST} ^one\. [NC]
RewriteRule (.*) /one$1 [L]
RewriteCond %{HTTP_HOST} ^two\. [NC]
RewriteRule (.*) /two$1 [L]
RewriteRule (.*) /zero$1
It seems to work, but I'm having my URL modified on the browser too. How do I avoid this from happening?
For your first issue, you can add a rule, that redirects any requests to that folder and withing that directory to a page that does not exists (so that it throuws a 404 error)
RewriteCond %{HTTP_HOST} ^one\.example\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} ^one/
RewriteRule . /notexists.html [L]
For your second issue, this should not happen since when you ask for a.example.com/folder/file.html it gets redirected internaly to a.example.com/a/folder/file.html (there is no way to get the content in the parent directory of 'a' )
I have two websites pointing to the same folder location. They are served via different scripts. Below is the code that I inserted in my .htaccess to make that happen. Things work fine except one problem... the domains are always served by the mentioned file, even if a resource is available - I am not able to access images, css, js folders etc.
RewriteCond %{HTTP_HOST} xyz.com
RewriteRule ^(.*)$ xyz.php [QSA,L]
RewriteCond %{HTTP_HOST} pqr.com
RewriteRule ^(.*)$ pqr.php [QSA,L]
Add these lines before your rules for domain names, e.g.:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# do not do anything for already existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
RewriteCond %{HTTP_HOST} =xyz.com
RewriteRule .* xyz.php [L]
RewriteCond %{HTTP_HOST} =pqr.com
RewriteRule .* pqr.php [L]
I have also made some small changes to your rules -- they will work a little bit faster:
No need for QSA flag if you are not manipulating with query string
No need for ^(.*)$ if you are not planing to capture it and use in target URL
=xyz.com searches for exact match (fast simple string comparison) while your xyz.com searches for this text in domain name using more expensive regex. Obviously, if you have some subdomains as well served by the same code (e.g. both xyz.com and www.xyz.com) then better keep what you have already.