Mobile app version of vmapp.org
Login or Join
Jessie594

: Why does my .htaccess file only partially force HTTPS and WWW? I have the domain https://www.example.com and this is how I prefer that users reach my site as well, using both HTTPS and WWW.

@Jessie594

Posted in: #301Redirect #Htaccess #Https

I have the domain www.example.com and this is how I prefer that users reach my site as well, using both HTTPS and
In my .htaccess file I try and force everyone to use this set up with the following code

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ www.example.com/ [R=301,L]


Which seems to work fine, all users that type example.com will get directed to the HTTPS version with the www sub domain.

BUT! If a user were to enter example.com OR www.example.com they are not redirected to the HTTPS version, what can be causing this?

I'm working on preparing the SEO for that domain as well and SEMRush actually gives me two listings per finding, one for the http version of the site and one for the https version of the site, I'm guessing this has something to do with the redirection issues as well.

UPDATE

This is my entire .htaccess file as it looks after your last suggested changes:

RewriteEngine On
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} =goodies.no [NC]
RewriteRule (.*) www.goodies.no/ [R=301,L]
#RewriteCond %{HTTP_HOST} ^goodies.no [NC] #RewriteCond %{SERVER_PORT} 80 #RewriteRule ^(.*)$ www.goodies.no/ [R=301,L]

# compress text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript

# Or, compress certain file types by extension:
<files *.svg>
SetOutputFilter DEFLATE
</files>
<files *.js>
SetOutputFilter DEFLATE
</files>
<files *.ttf>
SetOutputFilter DEFLATE
</files>
<files *.jpg>
SetOutputFilter DEFLATE
</files>
<files *.png>
SetOutputFilter DEFLATE
</files>

## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType text/html "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 1 month"
</IfModule>
## EXPIRES CACHING ##


I just commented out the part that used to work, and as you can see there are some compression and caching rules there as well.

UPDATE#2 (ACTUALLY UPDATE 3, NEW TEST.PHP FILE)

here is the contents of test.php file which is now available at goodies.no/test.php
<?php

$ip = getenv('SERVER_PORT');
echo "the first variable (SERVER_PORT) is ".$ip;


$ap = getenv('HTTPS');
echo " the second variable (HTTPS) is ".$ap;

$dp = getenv('ENV_HTTPS');
echo " the third (ENV_HTTPS) variable is "$.dp

?>


This only outputs the text "the variable is" and nothing else. Am I way off.... I get the feeling that I'm way off .. :/

10.01% popularity Vote Up Vote Down


Login to follow query

More posts by @Jessie594

1 Comments

Sorted by latest first Latest Oldest Best

 

@Jamie184

You need to change your logic. Your conditions are implicitly AND'd (the default), they should be OR'd instead. So, currently the RewriteRule is only processed if the HTTP_HOST is "example.com" AND the SERVER_PORT is 80. You need it to trigger on either of these conditions, so you need to add an OR flag on the first condition.

For example:

RewriteCond %{HTTP_HOST} ^example.com$ [NC,OR]
RewriteCond %{SERVER_PORT} 80
RewriteRule (.*) www.example.com/ [R=301,L]


(No need for string anchors ie. ^ and $ if you are capturing the whole pattern.)

UPDATE: Alternatively, check the HTTPS server variable, instead of SERVER_PORT. For example:

RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} =example.com [NC]
RewriteRule (.*) www.example.com/ [R=301,L]


What that says is... for every request that is not HTTPS or is for example.com (ie. no www) then redirect to www.example.com.
Alternatively, you can implement this as two separate rules:

RewriteCond %{HTTPS} !on
RewriteRule (.*) www.example.com/ [R=301,L]

RewriteCond %{HTTP_HOST} =example.com [NC]
RewriteRule (.*) www.example.com/ [R=301,L]


DEBUGGING: Test what these server variables contain on your server. You can (temporarily) replace the above redirect with the following:

RewriteCond %{SERVER_PORT} (.*)
RewriteRule ^ - [E=ENV_SERVER_PORT:%1]

RewriteCond %{HTTPS} (.*)
RewriteRule ^ - [E=ENV_HTTPS:%1]


This will create two environment variables (ENV_SERVER_PORT and ENV_HTTPS) that should be available to your server-side script (eg. PHP). Check what these contain. (eg. in PHP echo getenv('ENV_SERVER_PORT');)

Under HTTP you would expect... ENV_SERVER_PORT to be 80 and ENV_HTTPS to be "off".

Under HTTPS you would expect... ENV_SERVER_PORT to be 443 (default) and ENV_HTTPS to be "on".

Solution

It would seem that the SERVER_PORT and HTTPS Apache server variables are not available. This suggests that you have a front end proxy (or load balancer) that is handling the request.

The related (but not exactly the same - despite having the same name) PHP superglobals SERVER_PORT and HTTPS (specifically $_SERVER['SERVER_PORT'] and $_SERVER['HTTPS']) are, however, being set (by PHP). But SERVER_PORT is always 80 when served over HTTP and HTTPS (this also suggests a front-end proxy). The HTTPS PHP superglobal is, however, correctly set to "on" when served over HTTPS. But we want to avoid doing this redirection in our code (less efficient, more chance of error).

From your server output, it looks like there is an X-Proto HTTP request header (identified by the HTTP_X_PROTO index in the $_SERVER superglobal array) being set (most probably by the proxy server) when served over HTTPS (it is set to the string "SSL"), but when served over a plain HTTP connection this header is not set. We should be able to check for this in .htaccess. Try the following:

RewriteCond %{HTTP:X-Proto} !SSL [OR]
RewriteCond %{HTTP_HOST} =example.com [NC]
RewriteRule (.*) www.example.com/ [R=301,L]


For all requests that do not have an X-Proto HTTP request header set to the string "SSL" or the apex domain is requested then redirect to HTTPS with the www subdomain.

10% popularity Vote Up Vote Down


Back to top | Use Dark Theme