Short version to output link on a webpage
$url = "//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
$escaped_url = htmlspecialchars( $url, ENT_QUOTES, 'UTF-8' );
echo '' . $escaped_url . '';
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
.
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:
HTTP_HOST vs. SERVER_NAME
Is Port Number Required in HTTP "Host" Header Parameter?
https://stackoverflow.com/a/28049503/175071