I want to force redirect HTTP to HTTPS via htaccess. Of course I looked for a tons of solutions here, but nothing helps. On other hosting this solution works but not here.
If I try it this way:
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
It will redirect to HTTPs, but then it says the page is not working, TOO many redirects.
But I have nothing more in my htaccess, so why too many redirects?
Another solution that works not:
RewriteCond %{HTTP:HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) https://www.example.com/$1 [R=301,QSA]
Here is the dump of $_SERVER
:
HTTP:
PHP_FCGI_CHILDREN: 0
SCRIPT_NAME: /test2.php
REQUEST_URI: /test2.php
QUERY_STRING:
REQUEST_METHOD: GET
SERVER_PROTOCOL: HTTP/1.0
GATEWAY_INTERFACE: CGI/1.1
REDIRECT_URL: /test2.php
REMOTE_PORT: 50086
SCRIPT_FILENAME: /hosting/www/.../test2.php
SERVER_ADMIN: admin@...
REQUEST_SCHEME: http
DOCUMENT_ROOT: /hosting/www/example.com/
REMOTE_ADDR: 178.41.4.145
SERVER_PORT: 80
SERVER_ADDR: 178.238.37.248
SERVER_NAME: www.example.com
SERVER_SOFTWARE: Apache
SERVER_SIGNATURE:
HTTP_ACCEPT_LANGUAGE: sk,en;q=0.9,en-GB;q=0.8,en-US;q=0.7,cs;q=0.6
HTTP_ACCEPT_ENCODING: gzip, deflate
HTTP_ACCEPT: text/html,application/xhtml xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.50
HTTP_UPGRADE_INSECURE_REQUESTS: 1
HTTP_CACHE_CONTROL: max-age=0
HTTP_CONNECTION: close
HTTP_HOST: www.example.com
HTTP_AUTHORIZATION:
BACKEND_NAME: httpd1
HOSTNAME: lucy.onebit.cz
UNIQUE_ID: Yg_Luo5QXSFkFIZSmZji5AAAAMk
REDIRECT_STATUS: 200
REDIRECT_BACKEND_NAME: httpd1
REDIRECT_HOSTNAME: lucy.onebit.cz
REDIRECT_UNIQUE_ID: Yg_Luo5QXSFkFIZSmZji5AAAAMk
PHP_SELF: /test2.php
REQUEST_TIME_FLOAT: 1645202362.2178
REQUEST_TIME: 1645202362
URL: /test2.php
STATUS: 200
And HTTPS:
PHP_FCGI_CHILDREN: 0
SCRIPT_NAME: /test2.php
REQUEST_URI: /test2.php
QUERY_STRING:
REQUEST_METHOD: GET
SERVER_PROTOCOL: HTTP/1.0
GATEWAY_INTERFACE: CGI/1.1
REDIRECT_URL: /test2.php
REMOTE_PORT: 51668
SCRIPT_FILENAME: /hosting/www/example.com/www/test2.php
SERVER_ADMIN: admin@...
REQUEST_SCHEME: http
DOCUMENT_ROOT: /hosting/www/example.com/
REMOTE_ADDR: 178.41.4.145
SERVER_PORT: 443
SERVER_ADDR: 178.238.37.248
SERVER_NAME: www.example.com
SERVER_SOFTWARE: Apache
SERVER_SIGNATURE:
HTTP_ACCEPT_LANGUAGE: sk,en;q=0.9,en-GB;q=0.8,en-US;q=0.7,cs;q=0.6
HTTP_ACCEPT_ENCODING: gzip, deflate, br
HTTP_SEC_FETCH_DEST: document
HTTP_SEC_FETCH_USER: ?1
HTTP_SEC_FETCH_MODE: navigate
HTTP_SEC_FETCH_SITE: none
HTTP_ACCEPT: text/html,application/xhtml xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.50
HTTP_UPGRADE_INSECURE_REQUESTS: 1
HTTP_SEC_CH_UA_PLATFORM: "Windows"
HTTP_SEC_CH_UA_MOBILE: ?0
HTTP_SEC_CH_UA: " Not A;Brand";v="99", "Chromium";v="98", "Microsoft Edge";v="98"
HTTP_CONNECTION: close
HTTP_HOST: www.example.com
HTTP_AUTHORIZATION:
BACKEND_NAME: httpd1
HOSTNAME: lucy.onebit.cz
HTTPS: on
force_response_1_0: 1
downgrade_1_0: 1
ssl_unclean_shutdown: 1
nokeepalive: 1
Front_End_Https: on
UNIQUE_ID: Yg_L4xNbf-I51ics4Sn1UQAAAdM
REDIRECT_STATUS: 200
REDIRECT_BACKEND_NAME: httpd1
REDIRECT_HOSTNAME: lucy.onebit.cz
REDIRECT_HTTPS: on
REDIRECT_force_response_1_0: 1
REDIRECT_downgrade_1_0: 1
REDIRECT_ssl_unclean_shutdown: 1
REDIRECT_nokeepalive: 1
REDIRECT_Front_End_Https: on
REDIRECT_UNIQUE_ID: Yg_L4xNbf-I51ics4Sn1UQAAAdM
PHP_SELF: /test2.php
REQUEST_TIME_FLOAT: 1645202403.7653
REQUEST_TIME: 1645202403
HTTP_FRONT_END_HTTPS: on
URL: /test2.php
STATUS: 200
CodePudding user response:
But I think, the problem is with Mod rewrite disabled.
If mod_rewrite was disabled (and .htaccess
overrides are enabled) then you'd get a 500 Internal Server Error, not a redirect loop.
You'll get a redirect loop if another service is managing the SSL connection with the client (eg. front-end proxy, load balancer, CDN, etc.) and your application server is connecting via insecure HTTP to this other service. (Not uncommon.)
Check the HTTP request headers reaching your application server, do you see an X-Forwarded-Proto
header? This would indicate the application server is behind a front-end proxy that manages the SSL connection. In which case, you could do something like the following instead:
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
NB: Test first with 302 (temporary) redirects to avoid potential caching issues.
You will need to clear your browser cache before testing.
However, this could also be host-specific. Some shared hosts set an HTTPS
environment variable (not to be confused with the HTTPS
Apache server variable as used in your first example), so you could also try something like the following:
RewriteCond %{ENV:HTTPS} =off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
UPDATE: Based on the output from the PHP $_SERVER
superglobal, try the following instead:
RewriteCond %{ENV:HTTPS} !on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Reasoning behind this... there is no HTTPS
array index at all when requesting over HTTP and it is set to on
when requesting over HTTPS. This must be an environment variable (set by the host), not an Apache server variable, since a server variable would always be set.
Aside: The two conditions in the rules above (ie. %{HTTP:X-Forwarded-Proto} =http
and %{ENV:HTTPS} =off
) would simply fail (since neither of these are set) and the rule would do nothing.
NB: You must test first with a 302 (temporary) redirect and ensure the browser cache is clear before testing.