25

I want to redirect all www.domain.com requests to domain.com with PHP, basically:

if (substr($_SERVER['SERVER_NAME'], 0, 4) === 'www.')
{
    header('Location: http://' . substr($_SERVER['SERVER_NAME'], 4)); exit();
}

However I do want to maintain the requested URL like in SO, for e.g.:

http://www.stackoverflow.com/questions/tagged/php?foo=bar

Should redirect to:

http://stackoverflow.com/questions/tagged/php?foo=bar

I don't want to rely on .htaccess solutions, and I'm unsure which $_SERVER vars I'd have to use to make this happen. Also, preserving the HTTPS protocol would be a plus.

How should I do this?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Alix Axel
  • 151,645
  • 95
  • 393
  • 500

3 Answers3

50

Try this:

if (substr($_SERVER['HTTP_HOST'], 0, 4) === 'www.') {
    header('Location: http'.(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on' ? 's':'').'://' . substr($_SERVER['HTTP_HOST'], 4).$_SERVER['REQUEST_URI']);
    exit;
}
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • Thanks. How could I modify your code to also redirect https to http, since I don't currently have a certificate? So I'm trying to redirect www to non www and https to http simultaniously – Kyle Vassella Nov 22 '17 at 17:58
  • I tried having two of these, one for www->non and one for https (without a www) to http, but page fails to load due to too many redirects (once one if statement takes effect, it's now valid for the other if statement so it redirects too many times)...trying to get it all in one go but no luck yet. – Kyle Vassella Nov 22 '17 at 20:43
  • My code for 'example.com': `if (substr($_SERVER['HTTP_HOST'], 0, 4) === 'exam') { header('Location: http://' . substr($_SERVER['HTTP_HOST'], 0).$_SERVER['REQUEST_URI']); exit; }` //followed by the second if statement:// `if (substr($_SERVER['HTTP_HOST'], 0, 4) === 'www.') { header('Location: http://' . substr($_SERVER['HTTP_HOST'], 4).$_SERVER['REQUEST_URI']); exit; }` – Kyle Vassella Nov 22 '17 at 20:43
13
$pageURL = (@$_SERVER["HTTPS"] == "on") ? "https://" : "http://";
if ($_SERVER["SERVER_PORT"] != "80")
{
    $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} 
else 
{
    $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
header('Location: '. $pageURL);

Would redirect the user to the exact same page, www. intact.

So, to get rid of the www. , we just replace one line:

$pageURL = (@$_SERVER["HTTPS"] == "on") ? "https://" : "http://";
if ($_SERVER["SERVER_PORT"] != "80")
{
    $pageURL .= substr($_SERVER['SERVER_NAME'], 4).":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} 
else 
{
    $pageURL .= substr($_SERVER['SERVER_NAME'], 4).$_SERVER["REQUEST_URI"];
}
return $pageURL;

And that should work.

By the way, this is the method that is recommended by Google, as it keeps https:// intact, along with ports and such if you do use them.


As Gumbo pointed out, he uses $_SERVER['HTTP_HOST'] as it comes from the headers instead of the server, thus $_SERVER['SERVER_*'] is not as reliable. You could replace some$_SERVER['SERVER_NAME'] with $_SERVER['HTTP_HOST'], and it should work the same way.

Tyler Carter
  • 60,743
  • 20
  • 130
  • 150
1

if (((isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') || (isset($_SERVER["HTTPS"]) && strtolower($_SERVER["HTTPS"])=="on"))) {
           $https = 1;
} else {
            $https = 0;
}
if (substr($_SERVER['HTTP_HOST'], 0, 4) !== 'www.') {
            header('location:', ($https?'https://':'http://') .'www.' .                                                                   $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
}