I have been asked to help with an OpenCart installation on shared hosting with some redirection requirements.

Some of the redirects were already present and I'm not sure if they are required for OpenCart.

The new requirement is to redirect from HTTP to HTTPS.

When I add a command to redirect from HTTP to HTTPS the browser reports an error that redirects are not working correctly. This command has always worked on other sites before. I am guessing that there is a conflict with one or more of the other redirect commands.

These are the existing redirect commands with the comments on what they do:

# Redirect oldexample.co.uk to example.co.uk
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www\.)oldexample\.co.uk$ [NC]
RewriteRule ^ https://www.example.co.uk%{REQUEST_URI} [L,R=301]

# If your opencart installation does not run on the main web folder make sure you folder it does run in ie. / becomes /shop/ 
RewriteBase /
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteRule ^sitemap.xml$ index.php?route=feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=feed/google_base [L]
RewriteRule ^download/(.*) /index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]

The directive I add which causes redirects to break is:

#Redirect HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Why does this not work and how can get all of these redirect requirements to work together?

Additional requested information:

The result of curl --head http://example.co.uk

HTTP/1.1 301 Moved Permanently
date: Mon, 29 Nov 2021 18:17:10 GMT
server: Apache/2.4.51 (Unix)
location: https://www.example.co.uk/
content-type: text/html; charset=iso-8859-1

The result of curl --head http://www.example.co.uk

HTTP/1.1 301 Moved Permanently
date: Mon, 29 Nov 2021 19:20:47 GMT
server: Apache/2.4.51 (Unix)
location: https://www.example.co.uk/
content-type: text/html; charset=iso-8859-1

The result of curl --head https://www.example.co.uk is

HTTP/2 301 
date: Mon, 29 Nov 2021 19:20:54 GMT
server: Apache/2.4.51 (Unix)
location: https://www.example.co.uk/
content-type: text/html; charset=iso-8859-1

This I suppose is where a redirection loop occurs.

Output of print_r( $_SERVER, true) HTTP_ indices:

[HTTPS] => on
[HTTP_USER_AGENT] => Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:94.0) Gecko/20100101 Firefox/94.0
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
[HTTP_ACCEPT_LANGUAGE] => en-GB,en;q=0.5
[HTTP_DNT] => 1
[HTTP_ACCEPT_ENCODING] => gzip, deflate, br
[HTTP_SEC_FETCH_DEST] => document
[HTTP_SEC_FETCH_MODE] => navigate
[HTTP_CACHE_CONTROL] => max-age=0
[HTTP_TE] => trailers
[HTTP_HOST] => www.example.co.uk (changed)
[HTTP_COOKIE] => language=en; currency=GBP; PHPSESSID=(removed)
  • Where in that .htaccess file did you add that new rule? Did you add it above or below the other rules? Are there any subdirectories with their own .htaccess files involved? Nov 29, 2021 at 14:06
  • @StephenOstermiller I've tried adding it above and below the existing rules but always after RewriteEngine On Nov 29, 2021 at 14:12
  • 1
    Are you using a load balancer or CDN that is handling HTTPS for you? (As opposed to it being configured in Apache)? Nov 29, 2021 at 14:15
  • 1
    No, to the load balancer or CDN. No other .htaccess files besides one to create a password-protected directory. Nov 29, 2021 at 14:36
  • 2
    The response according to your CURL output is as if you don't have the #Redirect HTTP to HTTPS rule in place? There is no "redirect error" here (as reported by the browser)? The redirect to HTTPS in your first test is presumably the result of the non-www to www redirect present in your first code block. (?)
    – MrWhite
    Nov 29, 2021 at 18:54

1 Answer 1


The presence of the X-Proto HTTP request header would seem to imply you are behind some kind of proxy, that is perhaps managing the secure connection. Although the use of X-Proto is (very) non-standard, particularly with the given value.

Try the following immediately after your non-www to www redirect:

RewriteCond %{HTTP:X-Proto} !=SSL
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

You will need to clear your browser cache and test first with a 302 (temporary) redirect to avoid caching issues.

  • I've no idea about proxies but that worked. Thanks. Dec 5, 2021 at 0:16
  • Can you explain (in simple terms, if possible) why this prevented the original redirects from working? Dec 5, 2021 at 0:20
  • 2
    There is some piece of hardware like a load balancer sitting in front of your web server. It has the ssl certs installed on it and is handling the https then passing the request to the web server over http. It lets the web server know that the original request was https by adding that header. Your original rules were testing that the web server itself was receiving https requests, which must not actually be happening. Dec 5, 2021 at 0:29
  • 1
    ... so the HTTPS Apache server variable in the RewriteCond directive is always off, which results in a redirect loop. Not to be confused with the HTTPS index in the PHP $_SERVER superglobal array, which is generated by PHP and does not necessarily correspond directly with the HTTPS Apache server variable. $_SERVER['HTTPS'] could represent an environment variable of the same name. If so, then you may also be able to use RewriteCond %{ENV:HTTPS} !on instead. @authentictech
    – MrWhite
    Dec 6, 2021 at 1:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.