htaccess rewrite multiple folders - .htaccess

hello here is my htaccess file :
RewriteEngine On
RewriteBase /
#REWRITE QUERY STRINGS!
RewriteCond %{REQUEST_URI} !^/(.*).php
RewriteCond %{REQUEST_URI} !^/(.*).html
RewriteCond %{REQUEST_URI} !^/(.*).js
RewriteCond %{REQUEST_URI} !^/(.*).css
RewriteCond %{REQUEST_URI} !^/(.*).png
RewriteCond %{REQUEST_URI} !^/(.*).bmp
RewriteCond %{REQUEST_URI} !^/(.*).jpg
RewriteCond %{REQUEST_URI} !^/(.*).gif
RewriteCond %{REQUEST_URI} !^/m
RewriteCond %{REQUEST_URI} !^/ar
RewriteCond %{REQUEST_URI} !^/fr
RewriteCond %{REQUEST_URI} !^/tr
RewriteCond %{REQUEST_URI} !^/en
RewriteRule ^(.*)$ /index.php?do=$1 [QSA]
now what this does is when I want to access : domain.com/home is like accessing domain.com/index.php?do=home which is great , but when I try to access french language for example : domain.com/fr/home it doesn't work but domain.com/fr/index.php?do=home works do you have any idea I can achieve this for tr language, arabic and english also.Thanks
PS: index.php file is located in fr , tr , ar and en folders

Try the folwoing code :
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !\.(php|html|js|css|png|bmp|jpg|gif)$
RewriteCond %{REQUEST_URI} !^/(m|ar|fr|tr|en)/
RewriteRule ^(.*)$ /index.php?do=$1 [QSA,L]
#three lines above summarize your original code and exclude all request
# for m,ar,fr,tr,en with / , it means when request to any directory
# of them
RewriteCond %{REQUEST_URI} ^/(m|ar|fr|tr|en)/(.*)$ [NC]
RewriteCond %{REQUEST_URI} !^/(m|ar|fr|tr|en)/index\.php [NC]
RewriteRule ^(.*)/(.*)$ $1/index.php?do=$2 [QSA,L]
# the three lines above will match any request passes the first rule
# and starts with any of your chosen directories and prevent any loop
If you want to exclude the same files extensions from the second rule you could add this line RewriteCond %{REQUEST_URI} !\.(php|html|js|css|png|bmp|jpg|gif)$ to it as well

You probably want to introduce a more general rewriting rule prior to your rule for the default language:
RewriteEngine On
RewriteBase /
RewriteRule ^/?([a-z]{2})/(.*)/?$ /index.php?lang=$1&do=$2 [END,QSA]
RewriteRule ^/?(.*)/?$ /index.php?do=$1 [END,QSA]
You may need to add some exceptions in form of RewriteConds or even switch to an explicit naming of possible language keys instead of the ([a-z]{2})...
If you experience an http status 500 ("internal server error") due to the END flag then chances are that you are using a very old version of the apache http server and need to use the L flag instead. Should work the same for this case.
And a general hint: you should always prefer to place such rules inside the http servers (virtual) host configuration instead of using dynamic configuration files (.htaccess style files). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only supported as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

Related

htacces 2 variables issues

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

Multilanguage htaccess file (LTD)

I want to have a multi language site. Now, I have 2 domains. The first one is the main domain. That is website.nl. And i have a domain alias, website.org. So the 2 domains share the same public_html folder.
What I want is that:
website.nl will use the file /index.php/$1 and
website.org will use the file /gb/index.php/$1 (So when the url is website.org/test you will use the file /gb/index.php/test (No url redirect)
I found on another topic on stackoverflow the following:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} website.org
RewriteRule ^(.*)$ /gb/index.php [L]
RewriteRule ^(.*)$ /index.php/$1 [L]
But this htaccess file won't work. I will get a 500 error. That's all.
Can someone see what's going wrong?
Your rules are looping, otherwise the 2 rules will mess with each other and loop indefinitely (e.g. requesting /foo will result in /index.php/index.php/index.php/index.php... etc thus returning 500). You need to add some conditions to stop the looping. Try changing the conditions and rules to:
RewriteCond %{HTTP_HOST} website.org
RewriteCond %{REQUEST_URI} !^/gb/index.php
RewriteRule ^(.*)$ /gb/index.php/$1 [L]
RewriteCond %{REQUEST_URI} !^/gb/index.php
RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule ^(.*)$ /index.php/$1 [L]

.htaccess setting to serve multiple domains

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.

.htaccess rewrite to subfolders for subdomains and the main domain

There's tons of resources online about using .htaccess to rewrite your subdomains and if need be, also rewrite your main domain to a subfolder. I have found plenty answers and most of them are exactly the same. I have been tediously testing these methods and I have the same problem in all cases.
Consider the wanted result:
maindomain.com : rewrite to /public_html/mainsite/
sub.maindomain.com : rewrite to /public_html/sub/
The fastest/cleanest way i have considered is the following:
RewriteEngine On
# Rewrite the main domain
RewriteCond %{HTTP_HOST} !sub.maindomain.com
RewriteCond %{REQUEST_URI} !^/mainsite
RewriteRule ^(.*)$ /mainsite/$1 [L]
# Rewrite the sub domain
RewriteCond %{HTTP_HOST} sub.maindomain.com
RewriteCond %{REQUEST_URI} !^/sub
RewriteRule ^(.*)$ /sub/$1 [L]
This works well except for 1 annoying issue; The line
RewriteCond %{REQUEST_URI} !^/mainsite
Basically prevents a rewrite loop, but if you browse to maindomain.com/mainsite/ it rewrites to /public_html/mainsite/ instead of /public_html/mainsite/mainsite/ hoping to raise a 404 not found. If i remove that line, i get a 500 server error as it goes into a loop :S
The issue is, that any one of these domains needs freedom of creating folders etc. and would like to ensure that there is absolute freedom in the sub-sub folders people create :S
Please could someone help here?
RewriteEngine On
# Rewrite the main domain
RewriteCond %{HTTP_HOST} !sub.maindomain.com
RewriteCond %{REQUEST_URI} !^/mainsite/.*
RewriteRule ^(.*)$ /mainsite/$1 [L]
# Rewrite the sub domain
RewriteCond %{HTTP_HOST} sub.maindomain.com
RewriteCond %{REQUEST_URI} !^/sub/.*
RewriteRule ^(.*)$ /sub/$1 [L]
You need to make it so that it does not match any file within the /mainsite directory not just the root (/mainsite). I would think you would need to do the same to the sub domain also.
actually try this if you are still looking for an answer
RewriteEngine On
# Rewrite the main domain
RewriteCond %{HTTP_HOST} !sub.maindomain.com
RewriteCond %{REQUEST_URI} !^/mainsite/.*
RewriteRule ^/mainsite/(.*)$ /mainsite/$1 [L]
# Rewrite the sub domain
RewriteCond %{HTTP_HOST} sub.maindomain.com
RewriteCond %{REQUEST_URI} !^/sub/.*
RewriteRule ^/sub/(.*)$ /sub/$1 [L]`

.htaccess - Force https, force to subfolder, force www, don't break site

I have been having a very difficult time editing my .htaccess file to do these three things together. I have been able to get each part separately but I just do not understand how the logic flow works to get them all to work.
This is the best I have been able to pull together using the demo at bluehost support
http://helpdesk.bluehost.com/index.php/kb/article/000347
I appreciate any help resolving this issue.
# Use PHP5 Single php.ini as default
AddHandler application/x-httpd-php5s .php
# Bluehost.com
# .htaccess main domain to subdirectory redirect
# Copy and paste the following code into the .htaccess file
# in the public_html folder of your hosting account
# make the changes to the file according to the instructions.
# Do not change this line.
RewriteEngine on
# Change yourdomain.com to be your main domain.
RewriteCond %{HTTP_HOST} ^(www.)?sampleurl.com$
# Change 'subdirectory' to be the directory you will use for your main domain.
RewriteCond %{REQUEST_URI} !^/folder/
# Don't change this line.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Change 'subdirectory' to be the directory you will use for your main domain.
RewriteRule ^(.*)$ /folder/$1
# Change yourdomain.com to be your main domain again.
# Change 'subdirectory' to be the directory you will use for your main domain
# followed by / then the main file for your folder, index.php, index.html, etc.
RewriteCond %{HTTP_HOST} ^(www.)?sampleurl.com$
RewriteRule ^(/)?$ folder/index.php
RewriteCond %{HTTP_HOST} ^sampleurl\.com$ [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{SERVER_PORT} 80
RewriteRule (.*) https://www.sampleurl.com/$1 [L]
# For security reasons, Option all cannot be overridden.
# Options All -Indexes
# Options ExecCGI Includes IncludesNOEXEC SymLinksIfOwnerMatch -Indexes
Update:
Well after a long time using the following I have run into issues.
IndexIgnore *
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !^/site/
RewriteRule (.*) https://www.example.com/site/$1 [L,R]
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/site/
RewriteRule (.*) https://www.example.com/$1 [L,R]
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{SERVER_PORT} 443
RewriteCond %{REQUEST_URI} !^/site/
RewriteRule (.*) https://www.example.com/site/$1 [L,R]
New Issues.
Bluehost has an application that quickly installs and updates open source applications like wordpress, joomla, phpbb etc. Well apparently my new super .htaccess file completely breaks their system. The only way I can run updates and installs is to move the .htaccess to .htaccess.bak until the upgrade or install is complete. Then move it back.
I can't create any .htaccess on other sites that I host in other directories. e.g. I have a master account that I store in /www/site/ that this script forces requests into. Unfortunately my other sites stored in /www/site2/ and /www/site3/ don't work well. First I have to create a blank .htaccess to prevent it from pulling the .htaccess above found in /www/. For some reason if I try to do anything like force www.site2.com I get 500 error's saying I am forcing too many redirects.
I have a theory that my solution above needs to be a little more specific, to make sure it only effects request sent to example.com. (I think the line with anything not containing /site/ is a little to broad).
I appreciate any support resolving this. Would save me a bit of headaches!
Update II:
I do not believe I have access to apache config. Only option I see in cpanel is apache handlers (not really sure what that section does).
I will submit a ticket to see what location the simplescripts server runs from. I believe it runs from "https://www.simplescripts.com". What edit would you recommend I add to ignore this domain?
My host bluehost starts you with a primary account and then subdomains. The primary account's location is set at user\www. Unfortunatly this gets messy when you try to host multiple domains. That is why I use .htaccess to force requests that hit that directory into the \site\ directory. Thus trapping the primary site into the \site\ directory.
I think the relocation issue I was having with one of my subdomains was due to wordpress trying to force a domain without www and then me writing an .htaccess file forcing www. That caused the infinite loop, not my .htaccess file this thread is about. If I can resolve the simplescripts issue I am gmoney ;)
I'd think something like this would work
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !^/folder/
RewriteRule (.*) https://www.example.com/folder/$1 [L,R]
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/folder/
RewriteRule (.*) https://www.example.com/$1 [L,R]
but I confess I haven't tested. You can add in all the don't redirect if the file exists, etc., if you want.
In case you haven't seen it, here is the mod_rewrite documentation.
edit:
In response to updated question:
The first thing I notice is that it appears you may have enough control over your setup to put the rewrites in the Apache config files (in the VirtualHost sections) instead of in htaccess files, that'll immediately solve your problem with your other sites.
The first problem, it sounds like you'll need to add RewriteCond to exclude whichever URLs the Bluehost software uses. Either that, or access the Bluehost software under a different VirtualHost (once you've put the rewrite stuff inside the VirtualHost blocks).
If you can't edit your Apache config, then the easiest fix for the other sites it to not make them a subdirectory (on the filesystem) of your main site. That's rather weird, anyway. Move your main site to a sub-directory of /www as well if need be.
Personally, I put all sites in /srv/www/com.site-name.www on my servers (that is, reverse order, with the top-level-domain first, it makes related stuff group together when sorted alphabetically. E.g., when you have www.example.com and static.example.com)
This seems to do everything I needed. Probably a shorter way to get this done but it works!
IndexIgnore *
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !^/folder/
RewriteRule (.*) https://www.example.com/folder/$1 [L,R]
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/folder/
RewriteRule (.*) https://www.example.com/$1 [L,R]
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{SERVER_PORT} 443
RewriteCond %{REQUEST_URI} !^/folder/
RewriteRule (.*) https://www.example.com/folder/$1 [L,R]

Resources