Is there a smarter/better way to do HTTPS / WWW Rewrites? - apache

I wrote an .htaccess script that appears to work. However I'm new to Apache and often times I find out later that something I put together should have been constructed differently or with better semantics.
The goal of my code is to make sure that www and HTTPS are always present in the url. I'm using 302 for testing purposes. Put simply is this code jacked up? Is there something painfully obvious that I should change?
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.example.com%{REQUEST_URI} [R=302,L]
</IfModule>

To enforce https and www , you can use this :
RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www
RewriteCond %{HTTP_HOST} ^(www\.)?(.+)$
RewriteRule ^ https://www.%2%{REQUEST_URI} [NE,L,R]
This will redirect http://example.com or https://example.com to https://www.example.com

Related

How to force SSL and WWW in one redirect?

I'm wanting to minimise redirects whilst forcing https and www.
Trying to get...
http://example.com
...to go straight to...
https://www.example.com
... in one redirect. Not three, two, or even the 19 I had at one stage! I'm stuck at having one redirect for the www. bit, and then another redirect for the https bit.
Currently have this in my .htacess:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301]
I was about to concede defeat, feeling that it's not possible to combine two rules into one... but then I discovered Amazon.com have it implemented! Wondering how? Does this involve doing something outside of .htacess?
Screenshot of Amazon.com and their straight-to-the-point redirect
To force https and www in one redirect, you can use
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www [OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]
Try it like this,
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Force HTTPS and WWW in .htaccess

I start reading about a similar topic at this page .htaccess - how to force "www." in a generic way? and the solution was not, well almost what I am looking to do.
The problem : I need the user to be on HTTPS and on WWW to make my application working properly. But if some one click on a html link like:
www.example.com
The user will fall on my website with this :
https://www.www.example.com/
Here is my current .htaccess file.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://www.%{SERVER_NAME}/$1 [R=301,L]
</IfModule>
Is there any way to detect that the user already entered the WWW or is there a best practice to get the result I am looking for?
Thank you.
You are getting this behavior because http -> https rule is adding www\. in target URL without checking if URL is already starting with www.
You should replace both of your rules with this single rule and as a bonus avoid multiple redirects:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]

htaccess https to https subfolder

I'm creating a puzzle/challenge website that requires there to be two different sets of served files, depending on whether or not the user typed http: or https:
It doesn't seem like I can just redirect all HTTPS traffic using my web-host to a subfolder, so I've been trying to edit the htaccess file, but I keep ending up with infinite redirects.
What I'm trying to do:
http://www.example.com/secure -> http://www.example.com
https://www.example.com -> https://www.example.com/secure
When I setup redirects, after chrome times out, I get https://www.example.com/secure/secure/secure/secure/secure/secure/secure ...
The redirects I've setup are:
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule .* https://www.example.com/secure [NC,L,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^secure/ http://www.example.com/ [NC,L,R=301]
Neither rule seems to work, but the first rule seems to loop forever. Can anyone explain what I'm doing wrong?
The RewriteCond %{HTTPS} on portion may not work for all web servers. Some of servers are using RewriteCond %{HTTP:X-Forwarded-Proto} https.
I think you should do :
RewriteEngine On
RewriteCond %{HTTPS} on [OR]
RewriteCond %{HTTP:X-Forwarded-Proto} https
RewriteCond %{REQUEST_URI} !^/secure
RewriteRule ^(.*)$ https://www.example.com/secure [NC,L,R=301]
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{REQUEST_URI} ^/secure
RewriteRule ^(.*)$ http://www.example.com/ [NC,L,R=301]

htaccess redirect to https://www

I have the following htaccess code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond !{HTTPS} off
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
I want my site to be redirected to https://www. with HTTPS, and enforcing the www. subdomain,
but when I access http://www. (without HTTPS), it does not redirect me to https://www with HTTPS.
To first force HTTPS, you must check the correct environment variable %{HTTPS} off, but your rule above then prepends the www. Since you have a second rule to enforce www., don't use it in the first rule.
RewriteEngine On
RewriteCond %{HTTPS} off
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
# [NC] is a case-insensitive match
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
About proxying
When behind some forms of proxying, whereby the client is connecting via HTTPS to a proxy, load balancer, Passenger application, etc., the %{HTTPS} variable may never be on and cause a rewrite loop. This is because your application is actually receiving plain HTTP traffic even though the client and the proxy/load balancer are using HTTPS. In these cases, check the X-Forwarded-Proto header instead of the %{HTTPS} variable. This answer shows the appropriate process
Michals answer worked for me, albeit with one small modification:
Problem:
when you have a single site security certificate, a browser that tries to access your page without https:// www. (or whichever domain your certificate covers) will display an ugly red warning screen before it even gets to receive the redirect to the safe and correct https page.
Solution
First use the redirect to the www (or whichever domain is covered by your certificate) and only then do the https redirect. This will ensure that your users are not confronted with any error because your browser sees a certificate that doesn't cover the current url.
#First rewrite any request to the wrong domain to use the correct one (here www.)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#Now, rewrite to HTTPS:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
If you are using CloudFlare or a similar CDN you will get an infinite loop error with the %{HTTPS} solutions provided here. If you're a CloudFlare user you'll need to use this:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
BAD SOLUTION AND WHY!
Don't ever use the solution below because when you are using their code that is something like:
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.example.com%{REQUEST_URI} [L,R=301]
The browser goes to:
http://example.com
Then redirects to:
https://example.com
Then redirects to:
https://www.example.com
This is too much request to the server.
Most of the answers even accepted one has this problem.
BEST SOLUTION AND THE ANSWER
This code has an [OR] condition to prevent dual changes at url!
RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.example.com%{REQUEST_URI} [R=301,L]
This is the best way I found for Proxy and not proxy users
RewriteEngine On
### START WWW & HTTPS
# ensure www.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# ensure https
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
### END WWW & HTTPS
There are a lot of solutions out there. Here is a link to the apache wiki which deals with this issue directly.
http://wiki.apache.org/httpd/RewriteHTTPToHTTPS
RewriteEngine On
# This will enable the Rewrite capabilities
RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e. http://www.example.com/foo/ to https://www.example.com/foo/
# The leading slash is made optional so that this will work either in httpd.conf
# or .htaccess context
To redirect http:// or https:// to https://www you can use the following rule on all versions of apache :
RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,L,R]
Apache 2.4
RewriteEngine on
RewriteCond %{REQUEST_SCHEME} http [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,L,R]
Note that The %{REQUEST_SCHEME} variable is available for use since apache 2.4 .
If you are on CloudFlare, make sure you use something like this.
# BEGIN SSL Redirect
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# END SSL Redirect
This will save you from the redirect loop and will redirect your site to SSL safely.
P.S. It is a good idea to if check the mod_rewrite.c!
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
Notes: Make sure you have done the following steps
sudo a2enmod rewrite
sudo service apache2 restart
Add Following in your vhost file, located at /etc/apache2/sites-available/000-default.conf
<Directory /var/www/html>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
Require all granted
</Directory>
Now your .htaccess will
work and your site will redirect to http:// to https://www
Similar to Amir Forsati's solution htaccess redirect to https://www but for variable domain name, I suggest:
RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%2%{REQUEST_URI} [R=301,L]
Set in your .htaccess file
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
I used the below code from this website, it works great https://www.freecodecamp.org/news/how-to-redirect-http-to-https-using-htaccess/
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [R,L]
Hope it helps
I try first answer and it doesnt work...
This work:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

generic non-www to www, and non-http to https

I have the following code for my .htaccess file that I've picked up from here and tried adapting it as I understand from .htaccess, yet I can't seem to get it to work (or maybe the browser has cached it but I can't seem to clear it).
Options -Indexes
Options +FollowSymlinks
<IfModule mod_rewrite.c>
########## FORCE SSL ##########
RewriteEngine On
RewriteBase /
# Non-secure requests to www.domain.com should redirect to https://www.domain.com
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.%{HTTP_HOST} [NC]
RewriteRule ^(.*)$ https://www\.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# All secure (HTTPS) traffic should redirect to https://www.domain.com
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} !^www\.%{HTTP_HOST} [NC]
RewriteRule ^(.*)$ https://www\.%{HTTP_HOST}/$1 [L,R=301]
</IfModule>
I want to make it as generic a possible so I can simply copy and paste it to any site I make so no need to edit it each time - I guess I could also do this in PHP but I think it would be good if .htaccess is also there.
Another point is, can .htaccess be read if i were to go to www.domain.com/.htaccess or do I need to cover that in a 'deny all' kind of thing?
The second argument to the RewriteCond must be a regex, so it cannot contain a variable.
Try adding the following to your .htaccess file in place of the rules you had
#capture top level domain (.com or .co.uk)
RewriteCond %{HTTP_HOST} ([-_a-zA-Z0-9]+\.([a-zA-Z]{2,5}|co\.uk))$ [NC]
RewriteCond %{HTTP_HOST} (www\.)?(.+)$ [NC]
RewriteRule ^ - [E=MY_TLD:%2]
# Non-secure requests to www.domain.com should redirect to https://www.domain.com
RewriteCond %{HTTPS} off
RewriteRule ^ https://www\.%{ENV:MY_TLD}%{REQUEST_URI} [L,R=301]
# All secure (HTTPS) traffic should redirect to https://www.domain.com
RewriteCond %{HTTPS} on
#if host does not start with www
RewriteCond %{HTTP_HOST} !^www\.[-_a-zA-Z0-9]+\.([a-zA-Z]{2,5}|co\.uk)$ [NC]
RewriteRule ^ https://www\.%{ENV:MY_TLD}%{REQUEST_URI} [L,R=301]
Shortest version would be:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} (www\.)?(.+)$ [NC]
RewriteRule ^ https://www\.%2%{REQUEST_URI} [L,R=301]
Only (somewhat) downside would be that subdomain.example.com gets redirected to www.subdomain.example.com