I got involved sorting out an interesting problem this week. A user (not one of my clients) had implemented SSL on his server, but his Opencart secure pages (Login, My Account etc) were displaying without any css being applied. This manifested in part because the
href attribute on the secure page was displayed as http://
not https://
.
Now, this value is controlled within Opencart by checking the value of $_SERVER['HTTPS']
, set by the server. If this value is set, then Opencart sets the
href as https://
. If it isn’t it doesn’t.
All well and good, but in this case (123-reg) the server is set up with SSL Reversed Proxy & Load Balanced SSL Proxy, and this results in the server setting $_SERVER['HTTP_X_FORWARDED_SSL']
instead of $_SERVER['HTTPS']
– which is why the problem manifests.
The fix is relatively straightforward in that the checks need to be repointed at the new $_SERVER index. This can be fixed by changing /catalog/controller/common/header.php, catalog/model/tool/image.php for basic stores, more files dependent on the payment gateways. However, it’s simpler I think to make a modification to /system/library/request.php. This is straightforward since Opencart creates its own server variable (accessed through $this->request->server
, so this can be changed independently of $_SERVER
. Here’s a vQmod example:
<modification> <id>Reverse Proxy Handler</id> <version>for OC 1.5.6</version> <vqmver>2.2.1</vqmver> <author>Simon Battersby www.simonbattersby.com</author> <file name="/system/library/request.php"> <operation> <search position="replace" ><![CDATA[$this->server = $_SERVER;]]></search> <add><![CDATA[ if(isset($_SERVER['HTTP_X_FORWARDED_SSL']) && !isset($_SERVER['HTTPS'])){ $https = array('HTTPS'=>$_SERVER['HTTP_X_FORWARDED_SSL']); } else { $https = array(); } $this->server = array_merge($_SERVER,$https); ]]></add> </operation> </file> </modification>
All this is doing is checking if $_SERVER['HTTP_X_FORWARDED_SSL']
is set instead of $_SERVER['HTTPS']
, and if it is set, adding the value ‘HTTPS’ to Opencart’s local server setting. If you use this, let me know if it works throughout, as I don’t have access to a reverse proxy SSL server.
Sup man. I stumbled on your blog while making a mass proxy switch and your request.php with array_merge idea is pretty cool. Just thought i would fill you in as to why your theory didnt work in a broader scope of headers.
So HTTP_X_FORWARDED_SSL returns “on” which works great. HTTPS needs the word “on” to make OC functional in a proxy. Your theory is 100% correct and works as you deduced….but only because of the word “on” in that header.
Other headers do not always return “on”. Its a mix of “on” and “https”. In the array var ($https) you should pass the word “on” instead of the contents of the header. Sure HTTP_X_FORWARDED_SSL *should* always return “on”…but to future-proof your thought (in case they change it), or to work with other headers, make it pass the literal word “on” in your array row.
Also a subthought, i was unable to make $this->server re-write REMOTE_ADDR without literally setting $_SERVER[‘REMOTE_ADDR’] = $_SERVER[‘HTTP_X_FORWARDED_FOR’] before the line for $this->server = $_SERVER. Not sure if this is just buggy or if thats how _ADDR works.
Anyways, thanks for your insight in this thought and the cool array_merge idea. Keep coding my friend!
You can use free CloudFlare to test reverse proxy. Even includes a free SSL for further non-https-on-server HTTPS constant tweaking. If it works there, just bend the other headers to make a stack