too many redirects in htaccess - apache

I want to accomplish the following:
redirect non-www to www for all users
redirect desktop users to www.example.com/homepage
redirect mobile users to www.example.com/m
hide /homepage and /m from url so users will see www.example.com only
Here is my htaccess code. I am having a lot of problems with it, like things not redirecting to /m, and iphone users see "too many redirects", and sometimes desktop users are taken to /m even though they should be taken to /homepage.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ /homepage/ [R=301]
</IfModule>
RewriteCond %{HTTP_USER_AGENT} ^.*iPad.*$
RewriteRule ^(.*)$ http://www.example.com/m [R=301]
RewriteCond %{HTTP_USER_AGENT} ^.*iPod.*$
RewriteRule ^(.*)$ http://www.example.com/m [R=301]
RewriteCond %{HTTP_USER_AGENT} ^.*iPhone.*$
RewriteRule ^(.*)$ http://www.example.com/m [R=301]
RewriteCond %{HTTP_USER_AGENT} ^.*iemobile.*$
RewriteRule ^(.*)$ http://www.example.com/m [R=301]
RewriteCond %{HTTP_USER_AGENT} ^.*blackberry.*$
RewriteRule ^(.*)$ http://www.example.com/m [R=301]
RewriteCond %{HTTP_USER_AGENT} ^.*Android.*$
RewriteRule ^(.*)$ http://www.example.com/m [R=301]

This will give you too many redirects because you're only looking at the user agent, not the URI that's being requested, so every time a mobile user agent matches you continually redirect them to www.example.com/m. You can also add all the user agents into a single regex to reduce the number of rules you need to maintain.
You need to add a condition to look at the REQUEST_URI. Something like to the following should do:
RewriteCond %{HTTP_USER_AGENT} ^.*(ip(ad|od|hone)|blackberry|iemobile|android).*$ [NC]
RewriteCond %{REQUEST_URI} !^/m/.*
RewriteRule ^.*$ http://www.example.com/m [R=301,L]

Related

Apache Redirect certain HTTPS requests to HTTP not working

Hi I have been working on this for a while and just know I am doing something stupid but just can not see it. What I want to do is to redirect certain pages so they are always shown using HTTPS and all other pages if they are requested through HTTPS they are redirected as HTTP.
I have done lots of searching around the issue and found accepted answers on Stackoverflow that just did not work for me. So here Is my .htaccess file.
RewriteCond %{HTTPS} on
RewriteCond ${REQUEST_URI} !(finance/enquiryForm)(.*)
RewriteCond ${REQUEST_URI} !(offerentry)(.*)
RewriteRule (.*) http://dev.staging.co.uk/$1 [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^(finance/enquiryForm|offerentry)(.*) https://dev.staging.co.uk/$1 [L,R=301]
What is currently happening is that the pages that I want to redirect from https to http work fine but the pages I want to show as HTTPS get a redirect loop and fail. If I comment out the top section the HTTPS pages I do want redirect fine. So how do I get the redirect loop to stop?
EDIT
The full .htaccess file with the codeigniter etc stuff.
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
<Files .*>
Order Deny,Allow
Deny From All
</Files>
#RewriteCond %{HTTPS} on
#RewriteCond ${REQUEST_URI} !/(finance/enquiryForm|offerentry) [NC]
#RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
#RewriteCond %{HTTPS} off
#RewriteCond ${REQUEST_URI} /(finance/enquiryForm|offerentry) [NC]
#RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
# Protect application and system files from being viewed
RewriteRule ^(fuel/install/.+|fuel/crons/.+|fuel/data_backup/.+|fuel/codeigniter/.+|fuel/modules/.+|fuel/application/.+|\.$
# Remove trailing slashes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} (.*)/$
RewriteCond %{REQUEST_URI} !fuel/.*$
RewriteRule ^(.*)/$ $1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [L]
</IfModule>
Options -Indexes
Try these rules based on THE_REQUEST variable:
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} !/(finance/enquiryForm|offerentry) [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} /(finance/enquiryForm|offerentry) [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
Test them in Chrome dev tool and see what redirects are you getting.
Try with:
RewriteCond %{HTTPS} on
RewriteCond ${REQUEST_URI} !(finance/enquiryForm|offerentry)
RewriteRule (.*) http://dev.staging.co.uk/$1 [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule (finance/enquiryForm|offerentry) https://dev.staging.co.uk%{REQUEST_URI} [NE,L,R=301]

Why this htaccess code results into a redirect loop?

Here I am stuck with my htaccess code. I have been trying to figure it out for the last 11 hours why am I getting a redirect loop for the below code.
Options -Indexes +FollowSymLinks
RewriteEngine on
#Check for no www or www
RewriteCond %{HTTP_HOST} ^dummysite.com$ [or]
RewriteCond %{HTTP_HOST} ^www.dummysite.com$ [NC]
RewriteRule . - [E=FIRSTPART:true]
# IE 6
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteCond %{ENV:FIRSTPART} true
RewriteRule ^(.*)$ https://www.dummysite.com/$1 [R=302,L]
Why the above code results into a redirect loop?
EDIT: What I actually want is that if the user is from IE6 then he should be redirected to http version with www as prefix no matter if he types www or not in the url. And on the other hand if the user is from any other browsers then he should be redirected to a https version with www as prefix no matter if he types www in the url or not.
The below code should solve your problem.
RewriteCond %{HTTP_HOST} ^dummysite.com$
RewriteCond %{HTTPS} (on|off)
RewriteRule ^(.*)$ http://www.dummysite.com/$1 [R=302,L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteRule ^(.*)$ https://www.dummysite.com/$1 [R=302,L]
It first sets your www version of url (if the url does not have www in the prefix else it skips the first rewriteurl)and then chances the protocol from http to https.
Let's look what happens when you go to dummysite.com/foo. RewriteCond %{HTTP_HOST} ^dummysite.com$ is true, and due to the or flag, the second condition is skipped. The rule sets an environment variable to true. It then checks the useragent. If that is not IE6 (or a client pretending it is IE6), and that environment variable is true, it redirects to https://www.dummysite.com/foo. Great!
But what happens now. The client does that request again. RewriteCond %{HTTP_HOST} ^dummysite.com$ is now false, but due to the or-flag, it will check the second condition. RewriteCond %{HTTP_HOST} ^www.dummysite.com$ [NC] is now true, so it sets the environment variable. And it redirects to the same url. Over, and over, and over, and over, until the client decides to not do any more requests.
You either seem to want to redirect the domain without www to the domain with www, which can be dome with this:
RewriteCond %{HTTP_HOST} ^dummysite.com$
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteRule ^(.*)$ https://www.dummysite.com/$1 [R=302,L]
or you want to redirect http to https, which can be done with this:
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
Edit:
If you want to do both things, do it in two steps. First "just" redirect to the www-version if that is necessary, while keeping the protocol the same. Then, in a second step, redirect to the appropriate protocol.
RewriteCond %{HTTP_HOST} !^www\.example\.com$
RewriteCond %{HTTPS}s (on(s)|off)
RewriteRule ^ http%2://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} MSIE\s6
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
If it's not IE6, what's to prevent that rule from getting applied over and over again (causing the redirect loop)?
Shouldn't you be checking that the first part is not true?
RewriteCond %{ENV:FIRSTPART} !true
EDIT: Since you seem to want to redirect to "www" no matter what with MSIE6, you must only do this when the "www" is missing. Otherwise, it has a "www", you redirect to the exact same domain, which has the "www", and you redirect again, etc.
Change the above rule to:
RewriteCond %{HTTP_USER_AGENT} MSIE\s6
RewriteCond %{HTTP_HOST} !^www [NC,OR]
RewriteCond %{HTTPS} on
RewriteRule ^(.*)$ http://www.dummysite.com/$1 [R=302,L]
else
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteCond %{ENV:FIRSTPART} true
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://www.dummysite.com/$1 [R=302,L]
RewriteCond %{HTTP_USER_AGENT} MSIE\s6
RewriteCond %{HTTP_HOST} ^dummysite\.com$ [OR,NC]
RewriteCond %{HTTPS} =on
RewriteRule ^ http://www.dummysite.com%{REQUEST_URI} [R]
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteCond %{HTTP_HOST} ^dummysite\.com$ [OR,NC]
RewriteCond %{HTTPS} =off
RewriteRule ^ https://www.dummysite.com%{REQUEST_URI} [R]
or this, since i'm not sure about and/or priority in RewriteCond set
RewriteCond %{HTTP_USER_AGENT} MSIE\s6
RewriteCond %{HTTP_HOST} ^dummysite\.com$ [OR,NC]
RewriteCond %{HTTP_USER_AGENT} MSIE\s6
RewriteCond %{HTTPS} =on
RewriteRule ^ http://www.dummysite.com%{REQUEST_URI} [R]
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteCond %{HTTP_HOST} ^dummysite\.com$ [OR,NC]
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteCond %{HTTPS} =off
RewriteRule ^ https://www.dummysite.com%{REQUEST_URI} [R]

Redirecting to https with wildcard urls (htaccess)

I have the following problem. I have a site where some pages must be redirected to the https-secured equivalent of the link.
I tried several things but in the end it seems that the server ends up in a loop redirecting :(
Now I redirect every page to the https page but that is not what I want to.
This is the code I use right now:
RewriteCond %{http_host} ^www.domain.nl
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://www.domain.nl/$1 [L,R=301]
I would like to have al urls starting with bo- have https.
examples:
http://www.domain.nl/bo-users -> redirects to https://www.domain.nl/bo-users
http://www.domain.nl/bo-groups -> redirects to https://www.domain.nl/bo-groups
but
http://www.domain.nl/about-us -> stays at http://www.domain.nl/about-us
It is clear to me I need some wildcards in the rewrite condition for all urls startin with bo-.
We are using apache on the server.
Hope someone can send me in the right direction.
Thanks,
Frank
Update after the tips from Anubhava.
I current;y have this htaccess but I can't get it working (even when clearing the cache in my browser)
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www.domain\.nl$ [NC]
RewriteCond %{HTTPS} on
RewriteRule !^bo- http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NC,NE]
RewriteCond %{HTTP_HOST} ^www.domain\.nl$ [NC]
RewriteCond %{HTTPS} off
RewriteRule ^bo- https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NC,NE]
#rewrites een url to www.
RewriteCond %{HTTP_HOST} ^[a-z0-9-]+\.[a-z]{2,6}$ [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$0 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Hope for some extra help!
Thanks,
Frank
I just opened another call. The initial answer worked fine!
Use this rule:
# force HTTPS for bo- URIs
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.nl$ [NC]
RewriteCond %{HTTPS} off
RewriteRule ^bo- https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NC,NE]
# force HTTP for non bo- URIs
RewriteCond %{HTTP_HOST} ^www.domain\.nl$ [NC]
RewriteCond %{HTTPS} on
RewriteRule !^bo- http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NC,NE]

htaccess RewriteCond to let requests for website.com/m/... stay untouched

From a phone, if the user tries to access website.com, they are redirected to mobile.website.com. However, mobile.website.com makes AJAX requests to website.com, so I make all requests go through website.com/m/.... This isn't working:
# redirect phones/tablets to mobile site
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|ipad|iphone|ipod|iemobile|opera mobile|palmos|webos|googlebot-mobile" [NC]
RewriteCond %{HTTP_HOST} !mobile\.website\.com [NC]
RewriteCond %{REQUEST_URI} !^/m/ [NC]
RewriteRule ^(.*)$ http://www.mobile.website.com/$1 [L,R=302]
Specifically the line:
RewriteCond %{REQUEST_URI} !^/m/ [NC]
It should cancel the rewrite rule if the url matches website.com/m/.... Any ideas?
Thanks!
Change your code with this:
# redirect phones/tablets to mobile site
RewriteCond %{HTTP_USER_AGENT} (android|blackberry|ipad|iphone|ipod|iemobile|opera [NC]mobile|palmos|webos|googlebot-mobile) [NC]
RewriteCond %{HTTP_HOST} !mobile\.website\.com$ [NC]
RewriteRule ^(?!m/).*$ http://www.mobile.website.com%{REQUEST_URI} [L,R,NC]
Also if this still doesn't work then please post matching lines from your Apache's access.log and error.log.

Some Problem with htaccess!

How can I redirect my users from example.com / or www.example.com to new.example.com
but I dont want to redirect some specific urls like:
www.example.com/test.php
api.example.com/testo.php
www.example.com/forum/index.php
I did:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^(.*)$ http://new.example.com/$1 [R=301,L]
but what is the rules for urls?
One way to do this is to create additional rules earlier in the .htaccess file for the specific URLs that just redirect to themselves (internally, not using a 3XX response), and then use the L flag so no later rules are processed for those URLs.
For example:
RewriteEngine on
# don't redirect these
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^(/test.php)$ \1 [L]
RewriteCond %{HTTP_HOST} ^api.example.com$
RewriteRule ^(/testo.php)$ \1 [L]
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^(/forum/index.php)$ \1 [L]
# redirect these
RewriteCond %{HTTP_HOST} ^example.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^(.*)$ http://new.example.com/$1 [R=301,L]
I'm not sure if your "don't redirect" requirements included the hostname. If not, then just remove the RewriteCond lines.