How to find out if you're using HTTPS without $_SERVER['HTTPS']

Viewed 280426

I've seen many tutorials online that says you need to check $_SERVER['HTTPS'] if the server is connection is secured with HTTPS. My problem is that on some of the servers I use, $_SERVER['HTTPS'] is an undefined variable that results in an error. Is there another variable I can check that should always be defined?

Just to be clear, I am currently using this code to resolve if it is an HTTPS connection:

if(isset($_SERVER['HTTPS'])) {
    if ($_SERVER['HTTPS'] == "on") {
        $secure_connection = true;
    }
}
28 Answers

Chacha, per the PHP documentation: "Set to a non-empty value if the script was queried through the HTTPS protocol." So your if statement there will return false in many cases where HTTPS is indeed on. You'll want to verify that $_SERVER['HTTPS'] exists and is non-empty. In cases where HTTPS is not set correctly for a given server, you can try checking if $_SERVER['SERVER_PORT'] == 443.

But note that some servers will also set $_SERVER['HTTPS'] to a non-empty value, so be sure to check this variable also.

Reference: Documentation for $_SERVER and $HTTP_SERVER_VARS [deprecated]

The REAL answer: ready for copy-paste into a [config] script

/* configuration settings; X=edit may 10th '11 */
$pv_sslport=443; /* for it might be different, as also Gabriel Sosa stated */
$pv_serverport=80; /* X */
$pv_servername="mysite.com"; /* X */

/* X appended after correction by Michael Kopinsky */
if(!isset($_SERVER["SERVER_NAME"]) || !$_SERVER["SERVER_NAME"]) {
    if(!isset($_ENV["SERVER_NAME"])) {
        getenv("SERVER_NAME");
        // Set to env server_name
        $_SERVER["SERVER_NAME"]=$_ENV["SERVER_NAME"];
    }
}
if(!$_SERVER["SERVER_NAME"]) (
    /* X server name still empty? ... you might set $_SERVER["SERVER_NAME"]=$pv_servername; */
}

if(!isset($_SERVER["SERVER_PORT"]) || !$_SERVER["SERVER_PORT"]) {
    if(!isset($_ENV["SERVER_PORT"])) {
        getenv("SERVER_PORT");
        $_SERVER["SERVER_PORT"]=$_ENV["SERVER_PORT"];
    }
}
if(!$_SERVER["SERVER_PORT"]) (
    /* X server port still empty? ... you might set $_SERVER["SERVER_PORT"]=$pv_serverport; */
}

$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") :  (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");

$pv_URIprotocol is now correct and ready to be used; example $site=$pv_URIprotocol.$_SERVER["SERVER_NAME"]. Naturally, the string could be replaced with TRUE and FALSE also. PV stands for PortalPress Variable as it is a direct copy-paste which will always work. This piece can be used in a production script.

I know this answer is late, but I combined a bunch of answers and made a simple function that works for all use cases.

Try this:

function is_ssl(){
if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO']=="https"){ return true; }
elseif(isset($_SERVER['HTTPS'])){ return true; }
elseif($_SERVER['SERVER_PORT'] == 443){ return true; }
else{ return false; }
}

Then just use if, for example:

if(is_ssl()){
// WHAT TO DO IF IT IS SSL / HTTPS
}else{
// WHAT TO DO IF IT IS NOT SSL / HTTPS
}

This code works with Cloudflare, shared hosting providers, etc.

Enjoy.

I don't think that adding a port is good idea - specially when you got many servers with different builds. that just adds one more thing to remember to change. looking at doc's I think the last line of kaisers is quite good, so that:

if(!empty($_SERVER["HTTPS"]))
  if($_SERVER["HTTPS"]!=="off")
    return 1; //https
  else
    return 0; //http
else
  return 0; //http

seems like perfectly enough.

You could check $_SERVER['SERVER_PORT'] as SSL normally runs on port 443, but this is not foolproof.

This is how i find solve this

$https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0 ||
        !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
            strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0;

return ($https) ? 'https://' : 'http://';

I used the main suggestion here and got annoyed at the "PHP Notice" in the logs when HTTPS was not set. You can avoid it by using the null-coalescing operator "??":

if( ($_SERVER['HTTPS'] ?? 'off') == 'off' ) {
    // redirect
}

(Note: not available prior to php v7)

If you don't have control of the web server & don't know which variables have been set, upload this php to find out:

<?php
echo "<br>1 ".$_SERVER["HTTPS"];
echo "<br>2 ".$_SERVER["SERVER_PORT"];
echo "<br>3 ".$_SERVER["HTTP_X_FORWARDED_PROTO"];
echo "<br>4 ".$_SERVER["HTTP_X_FORWARDED_SSL"];
echo "<br>5 ".$_SERVER["HTTP_HTTPS"];
echo "<br>6 ".$_SERVER["REQUEST_SCHEME"];
?>

<html>
<body>
<br>
Just cruising
</body>
</html>

I use cloudflare for my systems. I had to access the $_SERVER['HTTP_CF_VISITOR'] value.

$isSsl = false; 
    if (isset($_SERVER['HTTP_CF_VISITOR'])) {
        $cfDecode = json_decode($_SERVER['HTTP_CF_VISITOR']);
        if (!empty($cfDecode) && !empty($cfDecode->scheme) && $cfDecode->scheme == 'https') {
            $isSsl = true;
        }
    }
var_dump($isSsl);

As per hobodave's post: "Set to a non-empty value if the script was queried through the HTTPS protocol."

if (!empty($_SERVER['HTTPS']))
{
    $secure_connection = true;
}
Related