Detecting https in htaccess - all possibilites - .htaccess

RewriteRule .* - [E=protocol:http]
RewriteCond %{ENV:HTTPS} ^on$ [NC,OR]
RewriteCond %{ENV:REQUEST_SCHEME} ^https$ [NC,OR]
RewriteCond %{HTTPS} ^on$ [NC,OR]
RewriteCond %{REQUEST_SCHEME} ^https$ [NC,OR]
RewriteCond %{HTTP:X-Forwarded-Proto} ^https$ [NC]
RewriteRule .* - [E=protocol:https]
How it is possible that code above doesn't work? This code checking literally in every possible way whether it's http or https to store it to var.
But at the end protocol var has always http value. Doesn't matter if you type http://example.com or https://example.com

The only thing that is working for me is:
RewriteCond %{SERVER_PORT} ^443$
So weird that the most popular ways don't work.

Related

.htaccess https 301 redirect + mobile site redirect

I'm trying to set up a permanet 301 redirect from all non-https and www version of my site to the https version while at the same time having all the mobile traffic redirected to the mobile version located on a subdomain
After reading a few tutorials I was able to assemble this (which works) :
RewriteEngine on
RewriteBase /
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https:// site here [R=301,L,NE]
RewriteCond %{QUERY_STRING} (^|&)m=0(&|$)
RewriteRule ^ - [CO=mredir:0:https:// site here]
RewriteCond %{HTTP:x-wap-profile} !^$ [OR]
RewriteCond %{HTTP:Profile} !^$ [OR]
RewriteCond %{HTTP_USER_AGENT} "acs|alav|alca|amoi|audi|aste|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} "dang|doco|eric|hipt|inno|ipaq|java|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} "maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|opwv" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} "palm|pana|pant|pdxg|phil|play|pluc|port|prox|qtek|qwap|sage|sams|sany" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} "sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} "teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|w3cs|wap-|wapa|wapi" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} "wapp|wapr|webc|winw|winw|xda|xda-" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} "up.browser|up.link|windowssce|iemobile|mini|mmp" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} "symbian|midp|wap|phone|pocket|mobile|pda|psp" [NC]
RewriteCond %{HTTP_USER_AGENT} !macintosh [NC]
RewriteCond %{HTTP_HOST} !^m\.
RewriteCond %{QUERY_STRING} !(^|&)m=0(&|$)
RewriteCond %{HTTP_COOKIE} !^.*mredir=0.*$ [NC]
RewriteRule ^ https://m. site here [R,L]
RewriteCond %{HTTP_USER_AGENT} libwww-perl.*
RewriteRule .* – [F,L]
The script does works but the problem I have is it creates 2 landing page redirects(http,www ---> https AND https:// ---> https://m.) which slows down the process and has a bad effect on seo.
Could someone point me to a good solution to redirect all mobile traffic to https://m. AND everything else to https://...
I have also tried to use php headers to fix the issue but it creates the same problem
Any help is greatly appreciated!
Thank you!
Your .htacces does the redirect from http to https first. And then does the redirect for mobile traffic. Which result in two redirects for non-https mobile traffic.
If you do the mobile redirect first it should leave with only one redirect for all situations.

Revert to HTTP from HTTPS when there is no REQUEST_URI

I have a set of rewrite rules as follows which handle routing of requests over HTTP and HTTPS depending on the path:
# Force SSL for certain URLs
RewriteCond %{HTTPS} off
RewriteCond $1 ^(admin|checkout|client-area) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Force Non-SSL for other URLs
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_METHOD} !=POST
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Placeholder for requests without a URI here
RewriteCond $1 !^(admin|checkout|client-area) [NC]
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
However I have noticed that if a user navigates to /checkout for example, and then back to the home page (where there is no REQUEST_URI) the HTTPS protocol persists. I've tried adding the following:
RewriteCond %{REQUEST_URI} !^$
But to no avail. What am I doing wrong here?
Ok, I stumbled across a post here https://expressionengine.stackexchange.com/a/6510/389 which got me headed in the right direction. I needed to add another condition block as follows after those above:
# Force Non-SSL for the home page (only)
RewriteCond %{HTTPS} on
RewriteCond %{QUERY_STRING} !^ACT= [NC]
RewriteCond %{REQUEST_METHOD} !=POST
RewriteCond $1 ^$ [NC]
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
That seems to do it! :)

Force SSL, WWW and remove index.php htaccess

How can I achieve all of this using htaccess. Thus far I have -
To enforce SSL
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301]
And To remove index.php
RewriteCond %{THE_REQUEST} ^.*/index.php
RewriteRule ^(.*)index.php$ https://www.example.com/$1 [R=301,L]
it seems to work for the most part but when i enter something like - "example.com/index.php", i get an error. It is redirected to
https://www.example.com/https://www.example.com/
I know why its happening but can't figure out a rule to combine everything I need and make it work.
Going to take a guess, you're missing the L flag in the first rule:
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]
Without the L flag, the request gets marked as "redirect" but continues on to have the other rules processed. And by the result you're seeing, it looks like the 2 rules are interferring with each other.
But is there any way to reduce the redirects when I type example.com/index.php
Not sure if this will work, because I can't test it, but maybe something like this?
RewriteCond %{THE_REQUEST} ^.*/index.php [OR]
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^(.*?)(index\.php)?$ https://www.example.com/$1 [R=301,L]

Preserve HTTP/HTTPS protocol in .htaccess redirects

I have to redirect port 80 to 2368 in htaccess but I'd like to keep the requested protocol intact so that SSL doesn't break.
I currently have this:
RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
RewriteRule ^ http://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
which works correctly but I'd like the protocol to be taken from the %{HTTP_HOST} condition if possible.
Is there a way to get this to be more dynamic without hard coding domains and protocols?
It seems very slow as is.
The trick provided by Jon is a nice hack, but I am afraid it could break if you want to use more [OR] conditions, and if you use more backreferences you have to be careful which number to use (%1 or %2 or ..).
I think the most elegant, robust and clean solution for smart HTTP/HTTPS handling is to set a variable:
# initialization code - put only once at the beginning of .htaccess
RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ - [env=proto:http]
# simply use %{ENV:proto} in your rules:
RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
RewriteRule ^ %{ENV:proto}://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
The advantage also is that the initialization code needs to be run only once, so if you have more rewrite rules then the resultant code is much shorter and more elegant.
Note a common setup is https provided with cloudflare, in which case HTTPS is not 'on' on the server itself. In that case you need extra rules like (note order):
RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"' [OR]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ - [env=proto:http]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"https"' [OR]
RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ - [env=proto:https]
Starting with Apache 2.4 you can also use the variable %{REQUEST_SCHEME} to preserve the scheme:
RewriteRule "^" "%{REQUEST_SCHEME}://sub.domain.com:2368%{REQUEST_URI}" [P,QSA,L]
No need to meddle with any conditions this way.
Try adding a condition like:
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTPS}:s on:(s)
Which checks that either HTTPS is off or it's on and you can use a backreference to fetch the "s" character:
RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTPS}:s on:(s)
RewriteRule ^ http%1://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
So if HTTPS is off, %1 is blank and the protocol is http://. If HTTPS is on, then the "s" is grouped and the %1 backreference is an "s", thus the protocol is https://.
However, this is all assuming that port 2368 can handle both unencrypted and SSL/TLS.
Or, you might use the solution posted as an answer by Jon Lin and rewrite it to use one RewriteCond and then set a variable as suggested in the answer by TMS.
That would look like this:
RewriteCond %{HTTPS}s ^(on(s)|offs)$
RewriteRule ^ - [env=s:%2]
RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
RewriteRule ^ http%{ENV:s}://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
Or, if you prefer:
RewriteCond %{HTTPS}s ^(on(s)|offs)$
RewriteRule ^ - [env=proto:http%2]
RewriteCond %{HTTP_HOST} ^sub.domain.com$ [NC]
RewriteRule ^ %{ENV:proto}://sub.domain.com:2368%{REQUEST_URI} [P,QSA,L]
http to https redirection:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
</IfModule>
Non www to www redirection:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
</IfModule>
If you want to use both functionality, then place both above code chunks
appropriately.

Forcing http on homepage using .htaccess

I'm using .htaccess to force https on certain pages and http on other pages and it's working fine. But I need to force http on home page (example: http://website.com) and I don't know how to do that. I tried RewriteCond %{REQUEST_URI} ^/index.php/? but as I'm using drupal that didn't work.
This is the script I'm using:
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} ^/register/? [OR]
RewriteCond %{REQUEST_URI} ^/admin/?
RewriteRule ^(.*)$ https://website.com/$1 [R,L]
RewriteCond %{SERVER_PORT} 443
RewriteCond %{REQUEST_URI} ^/about-us/? [OR]
RewriteCond %{REQUEST_URI} ^/help/?
RewriteRule ^(.*)$ http://website.com/$1 [R,L]
Any help is appreciated
First, instead of RewriteCond %{SERVER_PORT}, you can use RewriteCond %{HTTPS}, which should be more reliable in detecting HTTPS.
The homepage has the RewriteRule pattern ^$. So the rule would be
RewriteCond %{HTTPS} =on
RewriteRule ^$ http://website.com [R,L]
When everything works as you expect, you can change R to R=301.

Resources