DiegoP.
DiegoP.

Reputation: 45737

Get the full URL in PHP

I use this code to get the full URL:

$actual_link = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];

The problem is that I use some masks in my .htaccess, so what we see in the URL is not always the real path of the file.

What I need is to get the URL, what is written in the URL, nothing more and nothing less—the full URL.

I need to get how it appears in the Navigation Bar in the web browser, and not the real path of the file on the server.

Upvotes: 975

Views: 4063946

Answers (27)

T.Todua
T.Todua

Reputation: 56371

Examples for: https://www.site.xyz/fold/my.php?var=bla#555

Notice 1:

  • the hashtag # part was added manually in below php example snippet only for theoretical & illustrational purposes, however Server-Side languages (including PHP) are unable to detect them, because hashtags parts are only recognized in Client-Side browser/javascript...*

Notice 2:

  • DIRECTORY_SEPARATOR returns \ for Windows-OS, while UNIX returns /.
========== PATHINFO (use for filepathes, not urls) ==========

$x = PATHINFO ($url);
$x['dirname']              🡺 https://www.site.xyz/fold
$x['basename']             🡺                           my.php?var=bla#555 // unsafe!
$x['extension']            🡺                              php?var=bla#555 // unsafe!
$x['filename']             🡺                           my

========== PARSE_URL (use for urls, not filepathes) ==========

$x = PARSE_URL ($url);
$x['scheme']               🡺 https
$x['host']                 🡺         www.site.xyz
$x['path']                 🡺                     /fold/my.php
$x['query']                🡺                                  var=bla
$x['fragment']             🡺                                          555

Global variable $_SERVER

$_SERVER["DOCUMENT_ROOT"]  🡺 /home/user/public_html
$_SERVER["SERVER_ADDR"]    🡺 143.34.112.23
$_SERVER["SERVER_PORT"]    🡺 80 (or 443, etc..)
$_SERVER["REQUEST_SCHEME"] 🡺 https                           
$_SERVER["SERVER_PROTOCOL"]🡺 <same>
$_SERVER['HTTP_HOST']      🡺        www.site.xyz
$_SERVER["SERVER_NAME"]    🡺           <same>
$_SERVER["REQUEST_URI"]    🡺                    /fold/my.php?var=bla
$_SERVER["QUERY_STRING"]   🡺                                 var=bla

__FILE__                   🡺 /home/user/public_html/fold/my.php
$_SERVER["SCRIPT_FILENAME"]🡺 <same>                              // Note! it will show entry file's path, if `my.php` is not called directly.
__DIR__                    🡺 /home/user/public_html/fold
dirname(__FILE__)          🡺 <same>
$_SERVER["REQUEST_URI"]    🡺                       /fold/my.php?var=bla  // Note! it will show entry file's path, if `my.php` is not called directly.
parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH)🡺  /fold/my.php
$_SERVER["PHP_SELF"]       🡺                       /fold/my.php  // Note! it will show entry file's path, if `my.php` is not called directly.
// detect https
$is_HTTPS = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS']!=='off') || $_SERVER['SERVER_PORT']==443);            //in some cases, you need to add this condition too: if ('https'==$_SERVER['HTTP_X_FORWARDED_PROTO']) 

PHP Functions

dirname($url)              🡺 https://www.site.xyz/fold/
basename($url)             🡺                           my.php
debug_backtrace()          🡺 SHOWS FULL TRACE OF ALL INCLUDED FILES




< For WordPress >

// (Let's say, if WordPress is installed in subdirectory:  http://site.xyz/sub/)
home_url()                      🡺 http://site.xyz/sub/        // If is_ssl() is true, then it will be "https"
get_stylesheet_directory_uri()  🡺 http://site.xyz/sub/wp-content/themes/THEME_NAME  [same: get_bloginfo('template_url') ]
get_stylesheet_directory()      🡺 /home/user/public_html/sub/wp-content/themes/THEME_NAME
plugin_dir_url(__FILE__)        🡺 http://site.xyz/sub/wp-content/themes/PLUGIN_NAME
plugin_dir_path(__FILE__)       🡺 /home/user/public_html/sub/wp-content/plugins/PLUGIN_NAME/

Upvotes: 287

ax.
ax.

Reputation: 59927

Have a look at $_SERVER['REQUEST_URI'], i.e.

$actual_link = "https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

(Note that the double quoted string syntax is perfectly correct.)

If you want to support both HTTP and HTTPS, you can use

$actual_link = (empty($_SERVER['HTTPS']) ? 'http' : 'https') . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

⚠️ This code has security implications because the client and the server can set HTTP_HOST and REQUEST_URI to arbitrary values. It is absolutely necessary to sanitize both values and do proper input validation (CWE-20). They must not be used in any security context.

Upvotes: 2545

Avatar
Avatar

Reputation: 15186

HTTP_HOST and REQUEST_URI must be in quotes, otherwise it throws an error in PHP 7.2

Use:

$actual_link = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

If you want to support both HTTP and HTTPS:

$actual_link = (isset($_SERVER['HTTPS']) ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

⚠️ Using this code has security implications because the client can set HTTP_HOST and REQUEST_URI to arbitrary values. It is absolutely necessary to sanitize both values and do input validation.

Having said this, it is best to determine the link server side without relying on the URL of the browser.

Upvotes: 17

Web-Developer-Nil
Web-Developer-Nil

Reputation: 89

I've made this function to handle the URL:

 <?php
     function curPageURL()
     {
         $pageURL = 'http';
         if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
         $pageURL .= "://";
         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;
     }
 ?>

Upvotes: 8

PhonPanom
PhonPanom

Reputation: 405

I used this statement.

$base = "http://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]$my_web_base_path";
$url = $base . "/" . dirname(dirname(__FILE__));

Upvotes: 3

hpaknia
hpaknia

Reputation: 3108

Use:

$base_dir = __DIR__; // Absolute path to your installation, ex: /var/www/mywebsite
$doc_root = preg_replace("!{$_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']); # ex: /var/www
$base_url = preg_replace("!^{$doc_root}!", '', $base_dir); # ex: '' or '/mywebsite'
$base_url = str_replace('\\', '/', $base_url);//On Windows
$base_url = str_replace($doc_root, '', $base_url);//On Windows
$protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https';
$port = $_SERVER['SERVER_PORT'];
$disp_port = ($protocol == 'http' && $port == 80 || $protocol == 'https' && $port == 443) ? '' : ":$port";
$domain = $_SERVER['SERVER_NAME'];
$full_url = "$protocol://{$domain}{$disp_port}{$base_url}"; # Ex: 'http://example.com', 'https://example.com/mywebsite', etc. 

Source: PHP Document Root, Path and URL detection

Upvotes: 2

OzzyCzech
OzzyCzech

Reputation: 10342

Here is my solution - code is inspired by Tracy Debugger. It was changed for supporting different server ports. You can get full current URL including $_SERVER['REQUEST_URI'] or just the basic server URL. Check my function:

function getCurrentUrl($full = true) {
    if (isset($_SERVER['REQUEST_URI'])) {
        $parse = parse_url(
            (isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') .
            (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '')) . (($full) ? $_SERVER['REQUEST_URI'] : null)
        );
        $parse['port'] = $_SERVER["SERVER_PORT"]; // Setup protocol for sure (80 is default)
        return http_build_url('', $parse);
    }
}

Here is test code:

// Follow $_SERVER variables was set only for test
$_SERVER['HTTPS'] = 'off'; // on
$_SERVER['SERVER_PORT'] = '9999'; // Setup
$_SERVER['HTTP_HOST'] = 'some.crazy.server.5.name:8088'; // Port is optional there
$_SERVER['REQUEST_URI'] = '/150/tail/single/normal?get=param';

echo getCurrentUrl();
// http://some.crazy.server.5.name:9999/150/tail/single/normal?get=param

echo getCurrentUrl(false);
// http://some.crazy.server.5.name:9999/

Upvotes: 12

Jonathon Hill
Jonathon Hill

Reputation: 3495

Same technique as the accepted answer, but with HTTPS support, and more readable:

$current_url = sprintf(
    '%s://%s/%s',
    isset($_SERVER['HTTPS']) ? 'https' : 'http',
    $_SERVER['HTTP_HOST'],
    $_SERVER['REQUEST_URI']
);

The above gives unwanted slashes. On my setup Request_URI has leading and trailing slashes. This works better for me.

$Current_Url = sprintf(
   '%s://%s/%s',
   isset($_SERVER['HTTPS']) ? 'https' : 'http',
   $_SERVER['HTTP_HOST'],
   trim($_SERVER['REQUEST_URI'],'/\\')
);

Upvotes: 21

Timo Huovinen
Timo Huovinen

Reputation: 55623

Short version to output link on a webpage

$url =  "//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";

$escaped_url = htmlspecialchars( $url, ENT_QUOTES, 'UTF-8' );
echo '<a href="' . $escaped_url . '">' . $escaped_url . '</a>';

Here are some more details about the issues and edge cases of the //example.com/path/ format

Full version

function url_origin( $s, $use_forwarded_host = false )
{
    $ssl      = ( ! empty( $s['HTTPS'] ) && $s['HTTPS'] == 'on' );
    $sp       = strtolower( $s['SERVER_PROTOCOL'] );
    $protocol = substr( $sp, 0, strpos( $sp, '/' ) ) . ( ( $ssl ) ? 's' : '' );
    $port     = $s['SERVER_PORT'];
    $port     = ( ( ! $ssl && $port=='80' ) || ( $ssl && $port=='443' ) ) ? '' : ':'.$port;
    $host     = ( $use_forwarded_host && isset( $s['HTTP_X_FORWARDED_HOST'] ) ) ? $s['HTTP_X_FORWARDED_HOST'] : ( isset( $s['HTTP_HOST'] ) ? $s['HTTP_HOST'] : null );
    $host     = isset( $host ) ? $host : $s['SERVER_NAME'] . $port;
    return $protocol . '://' . $host;
}

function full_url( $s, $use_forwarded_host = false )
{
    return url_origin( $s, $use_forwarded_host ) . $s['REQUEST_URI'];
}

$absolute_url = full_url( $_SERVER );
echo $absolute_url;

This is a heavily modified version of http://snipplr.com/view.php?codeview&id=2734 (Which no longer exists)

URL structure:

scheme://username:password@domain:port/path?query_string#fragment_id

The parts in bold will not be included by the function

Notes:

  • This function does not include username:password from a full URL or the fragment (hash).
  • It will not show the default port 80 for HTTP and port 443 for HTTPS.
  • Only tested with http and https schemes.
  • The #fragment_id is not sent to the server by the client (browser) and will not be added to the full URL.
  • $_GET will only contain foo=bar2 for an URL like /example?foo=bar1&foo=bar2.
  • Some CMS's and environments will rewrite $_SERVER['REQUEST_URI'] and return /example?foo=bar2 for an URL like /example?foo=bar1&foo=bar2, use $_SERVER['QUERY_STRING'] in this case.
  • Keep in mind that an URI = URL + URN, but due to popular use, URL now means both URI and URL.
  • You should remove HTTP_X_FORWARDED_HOST if you do not plan to use proxies or balancers.
  • The spec says that the Host header must contain the port number unless it is the default number.

Client (Browser) controlled variables:

  • $_SERVER['REQUEST_URI']. Any unsupported characters are encoded by the browser before they are sent.
  • $_SERVER['HTTP_HOST'] and is not always available according to comments in the PHP manual: http://php.net/manual/en/reserved.variables.php
  • $_SERVER['HTTP_X_FORWARDED_HOST'] gets set by balancers and is not mentioned in the list of $_SERVER variables in the PHP manual.

Server controlled variables:

  • $_SERVER['HTTPS']. The client chooses to use this, but the server returns the actual value of either empty or "on".
  • $_SERVER['SERVER_PORT']. The server only accepts allowed numbers as ports.
  • $_SERVER['SERVER_PROTOCOL']. The server only accepts certain protocols.
  • $_SERVER['SERVER_NAME'] . It is set manually in the server configuration and is not available for IPv6 according to kralyk.

Related:

What is the difference between HTTP_HOST and SERVER_NAME in PHP?
Is Port Number Required in HTTP "Host" Header Parameter?
https://stackoverflow.com/a/28049503/175071

Upvotes: 486

smarteist
smarteist

Reputation: 1421

    public static function getCurrentUrl($withQuery = true)
    {
        $protocol = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
        or (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
        or (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
        or (isset($_SERVER['SERVER_PORT']) && intval($_SERVER['SERVER_PORT']) === 443) ? 'https' : 'http';

        $uri = $protocol . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

        return $withQuery ? $uri : str_replace('?' . $_SERVER['QUERY_STRING'], '', $uri);
    }

Upvotes: 4

function full_path()
{
    $s = &$_SERVER;
    $ssl = (!empty($s['HTTPS']) && $s['HTTPS'] == 'on') ? true:false;
    $sp = strtolower($s['SERVER_PROTOCOL']);
    $protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : '');
    $port = $s['SERVER_PORT'];
    $port = ((!$ssl && $port=='80') || ($ssl && $port=='443')) ? '' : ':'.$port;
    $host = isset($s['HTTP_X_FORWARDED_HOST']) ? $s['HTTP_X_FORWARDED_HOST'] : (isset($s['HTTP_HOST']) ? $s['HTTP_HOST'] : null);
    $host = isset($host) ? $host : $s['SERVER_NAME'] . $port;
    $uri = $protocol . '://' . $host . $s['REQUEST_URI'];
    $segments = explode('?', $uri, 2);
    $url = $segments[0];
    return $url;
}

Note: I just made an update to Timo Huovinen's code, so you won't get any GET parameters in the URL. This URL is plain and removes things like ?hi=i&am=a&get.

Example:

http://www.example.com/index?get=information

will be shown as:

http://www.example.com/index

This is fine unless you use GET paramaters to define some specific content, in which case you should use his code! :-)

Upvotes: 25

Akshit Ahuja
Akshit Ahuja

Reputation: 337

$page_url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

For more: How to get the full URL of a page using PHP

Upvotes: -1

Coder
Coder

Reputation: 3103

Here is the basis of a more secure version of the accepted answer, using PHP's filter_input function, which also makes up for the potential lack of $_SERVER['REQUEST_URI']:

$protocol_https = filter_input(INPUT_SERVER, 'HTTPS', FILTER_SANITIZE_STRING);
$host = filter_input(INPUT_SERVER, 'HTTP_HOST', FILTER_SANITIZE_URL);
$request_uri = filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL);
if(strlen($request_uri) == 0)
{
    $request_uri = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL);
    $query_string = filter_input(INPUT_SERVER, 'QUERY_STRING', FILTER_SANITIZE_URL);
    if($query_string)
    {
        $request_uri .= '?' . $query_string;
    }
}
$full_url = ($protocol_https ? 'https' : 'http') . '://' . $host . $request_uri;

You could use some different filters to tweak it to your liking.

Upvotes: 4

honyovk
honyovk

Reputation: 2747

Here's a solution using a ternary statement, keeping the code minimal:

$url = "http" . (($_SERVER['SERVER_PORT'] == 443) ? "s" : "") . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

This is the smallest and easiest way to do this, assuming one's web server is using the standard port 443 for HTTPS.

Upvotes: 71

Abbas Arif
Abbas Arif

Reputation: 390

Very simple use:

function current_url() {
    $current_url  = ( $_SERVER["HTTPS"] != 'on' ) ? 'http://'.$_SERVER["SERVER_NAME"] :  'https://'.$_SERVER["SERVER_NAME"];
    $current_url .= ( $_SERVER["SERVER_PORT"] != 80 ) ? ":".$_SERVER["SERVER_PORT"] : "";
    $current_url .= $_SERVER["REQUEST_URI"];

    return $current_url;
}

Upvotes: 2

ninja
ninja

Reputation: 473

You can make use of HTTP_ORIGIN as illustrated in the snippet below:

if ( ! array_key_exists( 'HTTP_ORIGIN', $_SERVER ) ) {
    $this->referer = $_SERVER['SERVER_NAME'];
} else {
    $this->referer = $_SERVER['HTTP_ORIGIN'];
}

Upvotes: 1

Ralph Rezende Larsen
Ralph Rezende Larsen

Reputation: 93

Use this one-liner to find the parent folder URL (if you have no access to http_build_url() that comes along with pecl_http):

$url = (isset($_SERVER['HTTPS']) ? 'https://' : 'http://').$_SERVER['SERVER_NAME'].str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname(dirname(__FILE__)));

Upvotes: 6

HappyCoder
HappyCoder

Reputation: 6155

Simply use:

$uri = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']

Upvotes: 38

thecodedeveloper.com
thecodedeveloper.com

Reputation: 3240

I have used the below code, and it is working fine for me, for both cases, HTTP and HTTPS.

function curPageURL() {
  if(isset($_SERVER["HTTPS"]) && !empty($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] != 'on' )) {
        $url = 'https://'.$_SERVER["SERVER_NAME"];//https url
  }  else {
    $url =  'http://'.$_SERVER["SERVER_NAME"];//http url
  }
  if(( $_SERVER["SERVER_PORT"] != 80 )) {
     $url .= $_SERVER["SERVER_PORT"];
  }
  $url .= $_SERVER["REQUEST_URI"];
  return $url;
}

echo curPageURL();

Demo

Upvotes: 3

Madan Sapkota
Madan Sapkota

Reputation: 26071

This works for both HTTP and HTTPS.

echo 'http' . (($_SERVER['HTTPS'] == 'on') ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Output something like this.

https://example.com/user.php?token=3f0d9sickc0flmg8hnsngk5u07&access_level=application

Upvotes: 1

Andreas
Andreas

Reputation: 2837

Clear code, working in all webservers (Apache, nginx, IIS, ...):

$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Upvotes: 19

Luke Mlsna
Luke Mlsna

Reputation: 481

You can use http_build_url with no arguments to get the full URL of the current page:

$url = http_build_url();

Upvotes: 6

UWU_SANDUN
UWU_SANDUN

Reputation: 1193

I think this method is good..try it

if($_SERVER['HTTP_HOST'] == "localhost"){
    define('SITEURL', 'http://' . $_SERVER['HTTP_HOST']);
    define('SITEPATH', $_SERVER['DOCUMENT_ROOT']);
    define('CSS', $_SERVER['DOCUMENT_ROOT'] . '/css/');
    define('IMAGES', $_SERVER['DOCUMENT_ROOT'] . '/images/');
}
else{
    define('SITEURL', 'http://' . $_SERVER['HTTP_HOST']);
    define('SITEPATH', $_SERVER['DOCUMENT_ROOT']);
    define('TEMPLATE', $_SERVER['DOCUMENT_ROOT'] . '/incs/template/');
    define('CSS', $_SERVER['DOCUMENT_ROOT'] . '/css/');
    define('IMAGES', $_SERVER['DOCUMENT_ROOT'] . '/images/');
}

Upvotes: 0

php developer
php developer

Reputation: 79

Try this:

print_r($_SERVER);

$_SERVER is an array containing information such as headers, paths, and script locations. The entries in this array are created by the web server. There is no guarantee that every web server will provide any of these; servers may omit some, or provide others not listed here. That said, a large number of these variables are accounted for in the » CGI/1.1 specification, so you should be able to expect those.

$HTTP_SERVER_VARS contains the same initial information, but is not a superglobal. (Note that $HTTP_SERVER_VARS and $_SERVER are different variables and that PHP handles them as such)

Upvotes: 6

Daniel Gillespie
Daniel Gillespie

Reputation: 535

My favorite cross platform method for finding the current URL is:

$url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

Upvotes: 48

Vaibhav Jain
Vaibhav Jain

Reputation: 505

This is the solution for your problem:

//Fetch page URL by this

$url = $_SERVER['REQUEST_URI'];
echo "$url<br />";

//It will print
//fetch host by this

$host=$_SERVER['HTTP_HOST'];
echo "$host<br />";

//You can fetch the full URL by this

$fullurl = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
echo $fullurl;

Upvotes: 7

Amarjit
Amarjit

Reputation: 311

This is quite easy to do with your Apache environment variables. This only works with Apache 2, which I assume you are using.

Simply use the following PHP code:

<?php
    $request_url = apache_getenv("HTTP_HOST") . apache_getenv("REQUEST_URI");
    echo $request_url;
?>

Upvotes: 8

Related Questions