How can I get the current page's full URL on a Windows/IIS server?

PhpIis

Php Problem Overview


I moved a WordPress installation to a new folder on a Windows/IIS server. I'm setting up 301 redirects in PHP, but it doesn't seem to be working. My post URLs have the following format:

http:://www.example.com/OLD_FOLDER/index.php/post-title/

I can't figure out how to grab the /post-title/ part of the URL.

$_SERVER["REQUEST_URI"] - which everyone seems to recommend - is returning an empty string. $_SERVER["PHP_SELF"] is just returning index.php. Why is this, and how can I fix it?

Php Solutions


Solution 1 - Php

Maybe, because you are under IIS,

$_SERVER['PATH_INFO']

is what you want, based on the URLs you used to explain.

For Apache, you'd use $_SERVER['REQUEST_URI'].

Solution 2 - Php

$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"];
}
return $pageURL;

Solution 3 - Php

##For Apache:

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


You can also use HTTP_HOST instead of SERVER_NAME as Herman commented. See this related question for a full discussion. In short, you are probably OK with using either. Here is the 'host' version:

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


###For the Paranoid / Why it Matters

Typically, I set ServerName in the VirtualHost because I want that to be the canonical form of the website. The $_SERVER['HTTP_HOST'] is set based on the request headers. If the server responds to any/all domain names at that IP address, a user could spoof the header, or worse, someone could point a DNS record to your IP address, and then your server / website would be serving out a website with dynamic links built on an incorrect URL. If you use the latter method you should also configure your vhost or set up an .htaccess rule to enforce the domain you want to serve out, something like:

RewriteEngine On
RewriteCond %{HTTP_HOST} !(^stackoverflow.com*)$
RewriteRule (.*) https://stackoverflow.com/$1 [R=301,L]
#sometimes u may need to omit this slash ^ depending on your server

Hope that helps. The real point of this answer was just to provide the first line of code for those people who ended up here when searching for a way to get the complete URL with apache :)

Solution 4 - Php

Solution 5 - Php

Use this class to get the URL works.

class VirtualDirectory
{
    var $protocol;
    var $site;
    var $thisfile;
    var $real_directories;
    var $num_of_real_directories;
    var $virtual_directories = array();
    var $num_of_virtual_directories = array();
    var $baseURL;
    var $thisURL;

    function VirtualDirectory()
    {
        $this->protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
        $this->site = $this->protocol . '://' . $_SERVER['HTTP_HOST'];
        $this->thisfile = basename($_SERVER['SCRIPT_FILENAME']);
        $this->real_directories = $this->cleanUp(explode("/", str_replace($this->thisfile, "", $_SERVER['PHP_SELF'])));
        $this->num_of_real_directories = count($this->real_directories);
        $this->virtual_directories = array_diff($this->cleanUp(explode("/", str_replace($this->thisfile, "", $_SERVER['REQUEST_URI']))),$this->real_directories);
        $this->num_of_virtual_directories = count($this->virtual_directories);
        $this->baseURL = $this->site . "/" . implode("/", $this->real_directories) . "/";
        $this->thisURL = $this->baseURL . implode("/", $this->virtual_directories) . "/";
    }

    function cleanUp($array)
    {
        $cleaned_array = array();
        foreach($array as $key => $value)
        {
            $qpos = strpos($value, "?");
            if($qpos !== false)
            {
                break;
            }
            if($key != "" && $value != "")
            {
                $cleaned_array[] = $value;
            }
        }
        return $cleaned_array;
    }
}

$virdir = new VirtualDirectory();
echo $virdir->thisURL;

Solution 6 - Php

Add:

function my_url(){
    $url = (!empty($_SERVER['HTTPS'])) ?
               "https://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] :
               "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
    echo $url;
}

Then just call the my_url function.

Solution 7 - Php

I use the following function to get the current, full URL. This should work on IIS and Apache.

function get_current_url() {

  $protocol = 'http';
  if ($_SERVER['SERVER_PORT'] == 443 || (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')) {
    $protocol .= 's';
    $protocol_port = $_SERVER['SERVER_PORT'];
  } else {
    $protocol_port = 80;
  }

  $host = $_SERVER['HTTP_HOST'];
  $port = $_SERVER['SERVER_PORT'];
  $request = $_SERVER['PHP_SELF'];
  $query = isset($_SERVER['argv']) ? substr($_SERVER['argv'][0], strpos($_SERVER['argv'][0], ';') + 1) : '';

  $toret = $protocol . '://' . $host . ($port == $protocol_port ? '' : ':' . $port) . $request . (empty($query) ? '' : '?' . $query);

  return $toret;
}

Solution 8 - Php

REQUEST_URI is set by Apache, so you won't get it with IIS. Try doing a var_dump or print_r on $_SERVER and see what values exist there that you can use.

Solution 9 - Php

The posttitle part of the URL is after your index.php file, which is a common way of providing friendly URLs without using mod_rewrite. The posttitle is actually therefore part of the query string, so you should be able to get it using $_SERVER['QUERY_STRING']

Solution 10 - Php

Use the following line on the top of the PHP page where you're using $_SERVER['REQUEST_URI']. This will resolve your issue.

$_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF'] . '?' . $_SERVER['argv'][0];

Solution 11 - Php

Oh, the fun of a snippet!

if (!function_exists('base_url')) {
	function base_url($atRoot=FALSE, $atCore=FALSE, $parse=FALSE){
		if (isset($_SERVER['HTTP_HOST'])) {
			$http = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http';
			$hostname = $_SERVER['HTTP_HOST'];
			$dir =  str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);

			$core = preg_split('@/@', str_replace($_SERVER['DOCUMENT_ROOT'], '', realpath(dirname(__FILE__))), NULL, PREG_SPLIT_NO_EMPTY);
			$core = $core[0];

			$tmplt = $atRoot ? ($atCore ? "%s://%s/%s/" : "%s://%s/") : ($atCore ? "%s://%s/%s/" : "%s://%s%s");
			$end = $atRoot ? ($atCore ? $core : $hostname) : ($atCore ? $core : $dir);
			$base_url = sprintf( $tmplt, $http, $hostname, $end );
		}
		else $base_url = 'http://localhost/';

		if ($parse) {
			$base_url = parse_url($base_url);
			if (isset($base_url['path'])) if ($base_url['path'] == '/') $base_url['path'] = '';
		}

		return $base_url;
	}
}

It has beautiful returns like:

// A URL like http://stackoverflow.com/questions/189113/how-do-i-get-current-page-full-url-in-php-on-a-windows-iis-server:

echo base_url();	// Will produce something like: http://stackoverflow.com/questions/189113/
echo base_url(TRUE);	// Will produce something like: http://stackoverflow.com/
echo base_url(TRUE, TRUE); || echo base_url(NULL, TRUE); //Will produce something like: http://stackoverflow.com/questions/

// And finally:
echo base_url(NULL, NULL, TRUE);
// Will produce something like:
//		array(3) {
//			["scheme"]=>
//			string(4) "http"
//			["host"]=>
//			string(12) "stackoverflow.com"
//			["path"]=>
//			string(35) "/questions/189113/"
//		}

Solution 12 - Php

I have used the following code, and I am getting the right result...

<?php
    function currentPageURL() {
        $curpageURL = 'http';
        if ($_SERVER["HTTPS"] == "on") {
            $curpageURL.= "s";
        }
        $curpageURL.= "://";
        if ($_SERVER["SERVER_PORT"] != "80") {
            $curpageURL.= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
        } 
        else {
            $curpageURL.= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
        }
        return $curpageURL;
    }
    echo currentPageURL();
?>

Solution 13 - Php

Everyone forgot http_build_url?

http_build_url($_SERVER['REQUEST_URI']);

When no parameters are passed to http_build_url it will automatically assume the current URL. I would expect REQUEST_URI to be included as well, though it seems to be required in order to include the GET parameters.

The above example will return full URL.

Solution 14 - Php

In my apache server, this gives me the full URL in the exact format you are looking for:

$_SERVER["SCRIPT_URI"]

Solution 15 - Php

Reverse Proxy Support!

Something a little more robust. Note It'll only work on 5.3 or greater.

/*
 * Compatibility with multiple host headers.
 * Support of "Reverse Proxy" configurations.
 *
 * Michael Jett <mjett@mitre.org>
 */
 
function base_url() {

    $protocol = @$_SERVER['HTTP_X_FORWARDED_PROTO'] 
              ?: @$_SERVER['REQUEST_SCHEME']
              ?: ((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ? "https" : "http");

    $port = @intval($_SERVER['HTTP_X_FORWARDED_PORT'])
          ?: @intval($_SERVER["SERVER_PORT"])
          ?: (($protocol === 'https') ? 443 : 80);
    
    $host = @explode(":", $_SERVER['HTTP_HOST'])[0]
          ?: @$_SERVER['SERVER_NAME']
          ?: @$_SERVER['SERVER_ADDR'];

    // Don't include port if it's 80 or 443 and the protocol matches
    $port = ($protocol === 'https' && $port === 443) || ($protocol === 'http' && $port === 80) ? '' : ':' . $port;
    
    return sprintf('%s://%s%s/%s', $protocol, $host, $port, @trim(reset(explode("?", $_SERVER['REQUEST_URI'])), '/'));
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCtrlDotView Question on Stackoverflow
Solution 1 - PhpVinko VrsalovicView Answer on Stackoverflow
Solution 2 - PhpTyler CarterView Answer on Stackoverflow
Solution 3 - PhpcwdView Answer on Stackoverflow
Solution 4 - PhpGregView Answer on Stackoverflow
Solution 5 - PhpSureshkumarView Answer on Stackoverflow
Solution 6 - PhpAveryView Answer on Stackoverflow
Solution 7 - PhpJrgnsView Answer on Stackoverflow
Solution 8 - PhpPeter BaileyView Answer on Stackoverflow
Solution 9 - PhpAdam HopkinsonView Answer on Stackoverflow
Solution 10 - PhpbeniwalView Answer on Stackoverflow
Solution 11 - PhpSpYk3HHView Answer on Stackoverflow
Solution 12 - PhpJoomla DevelopersView Answer on Stackoverflow
Solution 13 - PhpGajusView Answer on Stackoverflow
Solution 14 - PhpHüseyin YağlıView Answer on Stackoverflow
Solution 15 - Phpuser1949536View Answer on Stackoverflow