anon445699
anon445699

Reputation:

PHP Get Site URL Protocol - http vs https

I've written a little function to establish the current site url protocol but I don't have SSL and don't know how to test if it works under https. Can you tell me if this is correct?

function siteURL()
{
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $domainName = $_SERVER['HTTP_HOST'].'/';
    return $protocol.$domainName;
}
define( 'SITE_URL', siteURL() );

Is it necessary to do it like above or can I just do it like?:

function siteURL()
{
    $protocol = 'http://';
    $domainName = $_SERVER['HTTP_HOST'].'/'
    return $protocol.$domainName;
}
define( 'SITE_URL', siteURL() );

Under SSL, doesn't the server automatically convert the url to https even if the anchor tag url is using http? Is it necessary to check for the protocol?

Thank you!

Upvotes: 231

Views: 309721

Answers (19)

Rob Stocki
Rob Stocki

Reputation: 156

I know this is an old question but I came across this today since I needed to test for this in my site. It seems the answers above are needlessly complicated. To establish the site protocol, all you have to do is test $_SERVER['HTTPS']

If the protocol is using HTTPS, then $_SERVER['HTTPS'] will return 'on'. If not, the variable will remain empty. For example:

test if HTTPS is being used. If it is, the echo will return '$SSL_test: on'. If not HTTPS, '$SSL_test' will remain empty.

$SSL_test = $_SERVER['HTTPS'];

echo '<p>$SSL_test: '.$SSL_test.'</p>';
    
if($SSL_test == true) {
    echo 'You\'re using SSL';
} else {
    echo 'You\'re not using SSL';
} 

You can use the above to easily and cleanly test for HTTPS and implement accordingly. :)

Upvotes: 3

Aranxo
Aranxo

Reputation: 1183

Also late to the party, but here is a much shorter version of Rid Iculous's answer using the Null Coalescing Operator:

$is_ssl = in_array($_SERVER['HTTPS'] ?? '', ['on', 1]) ||
          ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') == 'https';
$protocol = $is_ssl ? 'https://' : 'http://';

Or:

$protocol = in_array($_SERVER['HTTPS'] ?? '', ['on', 1]) ||
            ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') == 'https' ?
            'https://' : 'http://';

Upvotes: 1

Jon
Jon

Reputation: 840

I know I'm a bit late to this party, but if you much prefer not using $_SERVER as it's strongly discouraged, and even deactivated on some PHP frameworks; and you have an apache web server, you can use it's native command thusly: -

$protocol = apache_getenv('HTTPS') ? 'https:' : 'http:';

Upvotes: 0

koalaok
koalaok

Reputation: 5720

I think the complete func should look like :

function siteURL()
{
    $protocol =  "http://";
    if (
        //straight
        isset($_SERVER['HTTPS']) && in_array($_SERVER['HTTPS'], ['on', 1])
        ||
        //proxy forwarding
        isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'
    ) {
        $protocol = 'https://';
    }

    $domainName = $_SERVER['HTTP_HOST'];
    return $protocol . $domainName;
}

Notes:

  • you should look also for HTTP_X_FORWARDED_PROTO (e.g. if proxy server)
  • relying on 443 port is not safe (https could be served on different port)
  • REQUEST_SCHEME not reliable

Upvotes: 1

ivoputzer
ivoputzer

Reputation: 6469

I know it's late, although there is a much more convenient way to solve this kind of problem! The other solutions are quite messy; this is how I would do it:

$protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === 0 ? 'https://' : 'http://';

...or even without condition if you prefer:

$protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,strpos( $_SERVER["SERVER_PROTOCOL"],'/'))).'://';

Have a look at $_SERVER["SERVER_PROTOCOL"]

Upvotes: 90

Guillaume
Guillaume

Reputation: 463

Extracted from CodeIgniter :

if ( ! function_exists('is_https'))
{
    /**
     * Is HTTPS?
     *
     * Determines if the application is accessed via an encrypted
     * (HTTPS) connection.
     *
     * @return  bool
     */
    function is_https()
    {
        if ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
        {
            return TRUE;
        }
        elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
        {
            return TRUE;
        }
        elseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
        {
            return TRUE;
        }

        return FALSE;
    }
}

Upvotes: 7

Scotty G
Scotty G

Reputation: 424

Here is how I do it ... it is a shorthand if else version of Rid Iculous's answer ...

$protocol = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] === 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ? 'https' : 'http';

Upvotes: 2

Jhoel Rhocher
Jhoel Rhocher

Reputation: 1

it's the best solution of https or http use this :

<?php
$protocol = '//';  
$site_url = $protocol.$_SERVER["HTTP_HOST"];
?>

But can't display https or http, so it only use to link your site content like image, etc.

if want to redirect your site in https, add this code in .htaccess file :

<IfModule mod_rewrite.c>
 RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
 RewriteRule ^(.*)$ https://www.your-domain.com$1 [L]
</IfModule>

Change www.your-domain.com with your dowmain name.

Upvotes: 0

Eugene Zakharenko
Eugene Zakharenko

Reputation: 147

For any system except IIS this is quite enough to define site self URL:

$siteURL='http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['HTTP_HOST'].'/';

or

$siteURL='http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['SERVER_NAME'].'/';

depends on what you exactly want: HTTP_HOST vs. SERVER_NAME

Upvotes: 7

Harshit
Harshit

Reputation: 721

In case of proxy the SERVER_PORT may not give the correct value so this is what worked for me -

$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 || $_SERVER['HTTP_X_FORWARDED_PORT'] == 443) ? "https://" : "http://"

Upvotes: 5

Saurabh Chandra Patel
Saurabh Chandra Patel

Reputation: 13586

$protocal = 'http';
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || $_SERVER['HTTPS'] == 'on') {$protocal = 'https';}


echo $protocal;

Upvotes: 3

Pedro Lobito
Pedro Lobito

Reputation: 98861

I've tested the most voted answer and it didn't work for me, I ended up using:

$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';

Upvotes: 3

shashik493
shashik493

Reputation: 810

Use this server variable to get the protocol details:

 $scheme = $_SERVER['REQUEST_SCHEME'] . '://';
 echo $scheme; //it gives http:// or https://

Note that this server variable is unreliable. For more information take a look at: Is $_SERVER['REQUEST_SCHEME'] reliable?

Upvotes: 5

softcod.com
softcod.com

Reputation: 570

short way

$scheme = $_SERVER['REQUEST_SCHEME'] . '://';

Upvotes: 29

alex
alex

Reputation: 5721

Because testing port number is not a good practice according to me, my solution is:

define('HTTPS', isset($_SERVER['HTTPS']) && filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN));

The HTTPSconstant returns TRUE if $_SERVER['HTTPS'] is set and equals to "1", "true", "on" or "yes". Returns FALSE otherwise.

Upvotes: 7

miyuru
miyuru

Reputation: 1201

made a function using the Rid Iculous's answer which worked on my system.

function site_protocol() {
    if(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&  $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')  return $protocol = 'https://'; else return $protocol = 'http://';
}

Hope it helps

Upvotes: 2

Anoop K
Anoop K

Reputation: 281

Some changes:

function siteURL() {
  $protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || 
    $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
  $domainName = $_SERVER['HTTP_HOST'];
  return $protocol.$domainName;
}

Upvotes: 28

Rid Iculous
Rid Iculous

Reputation: 3952

This works for me

if (isset($_SERVER['HTTPS']) &&
    ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
    isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
    $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $protocol = 'https://';
}
else {
  $protocol = 'http://';
}

Upvotes: 112

profitphp
profitphp

Reputation: 8334

It is not automatic. Your top function looks ok.

Upvotes: 75

Related Questions