Welcome to WebmasterWorld Guest from 54.198.164.83

Forum Moderators: Ocean10000 & incrediBILL & phranque

Force all HTTP to HTTPS

best redirect option

     
7:27 am on Nov 8, 2017 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:June 2, 2006
posts:2218
votes: 7


Hi,

Recently, I moved two sites to HTTPS, exclusively. I did one after the other, as the 1st move looked OK. I swear I tested multiple pages, and they all redirected as expected (aka page-to-page). This is what I used for global redirect:

RewriteCond %{HTTPS} !=on
RewriteRule ^ https://www.example.com/$1 [L,R=301]


Just some minutes ago, I got an email from WMT pointing to "Errors in hreflang tags" that should be fixed. I checked, and found that all HTTP requests were redirecting to the home page of the corresponding two sites. :o Hello? All worked some days ago.

So, I check my .htaccess, exclude global redirects, one by one. Then, I search the net (as I initially did) and I test "the other way" of global HTTP-to-HTTPS redirect, like this:

RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]


And the HTTP-to-HTTPS behaves as it should be.

Then, I kind of remember the notice about Apache update to 2.4.29, which happened some time yesterday.

Could that update really be a cause of this problem?

Can you help me understand the differences between these ways of global HTTP-to-HTTPS redirect:

RewriteCond %{HTTPS} !=on
RewriteRule ^ https://www.example.com/$1 [L,R=301]

vs.

RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

vs.

RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}


Please note that the first example worked when I tested it after the implementation.

At the end, what really is the best option to do all HTTP-to-HTTPS redirect? The one I use now (2nd) is from the Apache's website:

[wiki.apache.org...]

Thank you very much.
7:36 am on Nov 8, 2017 (gmt 0)

Moderator from US 

WebmasterWorld Administrator keyplyr is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Sept 26, 2001
posts:11135
votes: 662


Good job figuring out the issue.

I think it may be more dependent on how your host has set up the server. The upgrade may have been done with different settings than previous.

https://www.example.com is specific to your domain.

SERVER_NAME likely specifies your accout.

Seems in this case the account is what needs to be used.

You're using a VPS, correct?
9:52 am on Nov 8, 2017 (gmt 0)

Full Member

Top Contributors Of The Month

joined:Apr 11, 2015
posts: 306
votes: 21


RewriteRule ^ https://www.example.com/$1 [L,R=301]


This would never have worked as intended (regardless of server upgrades). The $1 backreference will always be empty, so this will always redirect to the home page (as you later found out).

The $1 backrefence will always be empty because you have no capturing groups in the RewriteRule pattern. It would have needed to be something like:

RewriteRule (.*) https://www.example.com/$1 [L,R=301]


The $1 then refers to whatever is captured by the (.*) subpattern.

Why did the earlier tests work... well, that's a puzzle. But be wary that 301 redirects are cached hard by the browser, so if you'd previously tested an alternative directive then you may have been seeing a cached response? Make sure the browser cache is clear before testing (test with the "object inspector" open and caching disabled). Also test with 302 (temporary) redirects so you don't end up caching an erroneous redirect.

what really is the best option to do all HTTP-to-HTTPS redirect?


Well, that's the thing, there is no single "best" option that will work on every server. It depends, on your set up.

Are you already canonicalising the www vs non-www? (This should often be done at the same time.)

Note that unless you have "UseCanonicalName On" set in the server config (which is not the default) then SERVER_NAME is the same as HTTP_HOST, ie. whatever hostname has been specified on the request. So, if you use SERVER_NAME (or HTTP_HOST) in the substitution then you are going to redirect to the same (ie. example.com to example.com and www.example.com to www.example.com). So, in this repsect, hardcoding the canonical hostname in the substitution (as you did in the first example) could be considered "better". For example:

RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]


However, if "UseCanonicalName On" is set in the server config, then SERVER_NAME refers to the value set in the ServerName directive (in the server config), so this probably would be OK (ie. canoncialise the hostname), but that still depends on how your server is configured. (And note that this is not the default option, so it must be explicitly set in the server config.)


Some comparisons with the 3 rules you posted...

!=on
!=on [NC]
!on


The net result of all these are the same. The value of the HTTPS variable is always lowercase (barring any server peculiarities), so the NC flag is entirely superfluous (and just adds complexity). The value is either "on" or "off", so the "=" is optional. (The "=" prefix makes it into a string comparison, instead of a regex, so it's arguably "better" for performance - but that is insignificant.)


RewriteRule ^ https://www.example.com/$1 [L,R=301]
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}


As mentioned above, the first one won't work as intended. The second one is OK, but (probably) doesn't canonicalise the hostname. The third one has a superfluous capturing group in the RewriteRule pattern and will result in a temporary (302) redirect, instead of a 301.

If you implemented this redirect directly in the server config, the directives using REQUEST_URI would work without alteration. However, if you are using a backreference then the directive would need to be modified to avoid a double slash. (Although if you were doing this in the server config then you probably shouldn't be using mod_rewrite for this anyway.) (By "server config", I'm referring to a server or virtualhost context, not a directory context.)
4:44 am on Nov 9, 2017 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:June 2, 2006
posts:2218
votes: 7


Thanks very much for replies.

I checked and UseCanonicalName is OFF. Now, is there any difference between these two:

RewriteRule (.*) https://www.example.com/$1 [L,R=301]

RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]


Why and when 1st or 2nd?

Thank you
7:40 pm on Nov 9, 2017 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:14608
votes: 598


If you wanted to, you could make up some benchmark tests and see which version is faster. But I seriously doubt there will be a significant difference--and even then, it would only be noticeable if you have a truly vast site. Use whichever form you're more comfortable working with.

And again, if you felt like it, you could add a [NS] flag so the server doesn't have to stop and evaluate conditions (which will always fail anyway) on internal requests such as for index.html.