src/HTTP2.php
public function absoluteURI($url = null, $protocol = null, $port = null)
    {
        // filter CR/LF
        $url = str_replace(array("\r", "\n"), ' ', $url);

        // Mess around protocol and port with already absolute URIs
        if (preg_match('!^([a-z0-9]+)://!i', $url)) {
            if (empty($protocol) && empty($port)) {
                return $url;
            }
            if (!empty($protocol)) {
                $url = $protocol .':'. end($array = explode(':', $url, 2));
            }
            if (!empty($port)) {
                $url = preg_replace(
                    '!^(([a-z0-9]+)://[^/:]+)(:[\d]+)?!i',
                    '\1:'. $port,
                    $url
                );
            }
            return $url;
        }

        $host = 'localhost';
        if (!empty($_SERVER['HTTP_HOST'])) {
            list($host) = explode(':', $_SERVER['HTTP_HOST']);
        } elseif (!empty($_SERVER['SERVER_NAME'])) {
            list($host) = explode(':', $_SERVER['SERVER_NAME']);
        }

        if (empty($protocol)) {
            if (isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on')) {
                $protocol = 'https';
            } else {
                $protocol = 'http';
            }
            if (!isset($port) || $port != intval($port)) {
                $port = 80;
                if (isset($_SERVER['SERVER_PORT'])) {
                    $port = $_SERVER['SERVER_PORT'];
                }
            }
        }

        if ($protocol == 'http' && $port == 80) {
            unset($port);
        }
        if ($protocol == 'https' && $port == 443) {
            unset($port);
        }

        $server = $protocol.'://'.$host.(isset($port) ? ':'.$port : '');

        $uriAll = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI']
                                                 : $_SERVER['PHP_SELF'];
        if (false !== ($q = strpos($uriAll, '?'))) {
            $uriBase = substr($uriAll, 0, $q);
        } else {
            $uriBase = $uriAll;
        }
        if (!strlen($url) || $url{0} == '#') {
            $url = $uriAll.$url;
        } elseif ($url{0} == '?') {
            $url = $uriBase.$url;
        }
        if ($url{0} == '/') {
            return $server . $url;
        }

        // Adjust for PATH_INFO if needed
        if (isset($_SERVER['PATH_INFO']) && strlen($_SERVER['PATH_INFO'])) {
            $path = dirname(substr($uriBase, 0, -strlen($_SERVER['PATH_INFO'])));
        } else {
            /**
             * Fixes bug #12672 PHP_SELF ending on / causes incorrect redirects
             *
             * @link http://pear.php.net/bugs/12672
             */
            $path = dirname($uriBase.'-');
        }

        if (substr($path = strtr($path, '\\', '/'), -1) != '/') {
            $path .= '/';
        }

        return $server . $path . $url;
    }
public function absoluteURI($url = null, $protocol = null, $port = null)
    {
        // filter CR/LF
        $url = str_replace(array("\r", "\n"), ' ', $url);

        // Mess around protocol and port with already absolute URIs
        if (preg_match('!^([a-z0-9]+)://!i', $url)) {
            if (empty($protocol) && empty($port)) {
                return $url;
            }
            if (!empty($protocol)) {
                $url = $protocol .':'. end($array = explode(':', $url, 2));
            }
            if (!empty($port)) {
                $url = preg_replace(
                    '!^(([a-z0-9]+)://[^/:]+)(:[\d]+)?!i',
                    '\1:'. $port,
                    $url
                );
            }
            return $url;
        }

        $host = 'localhost';
        if (!empty($_SERVER['HTTP_HOST'])) {
            list($host) = explode(':', $_SERVER['HTTP_HOST']);
        } elseif (!empty($_SERVER['SERVER_NAME'])) {
            list($host) = explode(':', $_SERVER['SERVER_NAME']);
        }

        if (empty($protocol)) {
            if (isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on')) {
                $protocol = 'https';
            } else {
                $protocol = 'http';
            }
            if (!isset($port) || $port != intval($port)) {
                $port = 80;
                if (isset($_SERVER['SERVER_PORT'])) {
                    $port = $_SERVER['SERVER_PORT'];
                }
            }
        }

        if ($protocol == 'http' && $port == 80) {
            unset($port);
        }
        if ($protocol == 'https' && $port == 443) {
            unset($port);
        }

        $server = $protocol.'://'.$host.(isset($port) ? ':'.$port : '');

        $uriAll = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI']
                                                 : $_SERVER['PHP_SELF'];
        if (false !== ($q = strpos($uriAll, '?'))) {
            $uriBase = substr($uriAll, 0, $q);
        } else {
            $uriBase = $uriAll;
        }
        if (!strlen($url) || $url{0} == '#') {
            $url = $uriAll.$url;
        } elseif ($url{0} == '?') {
            $url = $uriBase.$url;
        }
        if ($url{0} == '/') {
            return $server . $url;
        }

        // Adjust for PATH_INFO if needed
        if (isset($_SERVER['PATH_INFO']) && strlen($_SERVER['PATH_INFO'])) {
            $path = dirname(substr($uriBase, 0, -strlen($_SERVER['PATH_INFO'])));
        } else {
            /**
             * Fixes bug #12672 PHP_SELF ending on / causes incorrect redirects
             *
             * @link http://pear.php.net/bugs/12672
             */
            $path = dirname($uriBase.'-');
        }

        if (substr($path = strtr($path, '\\', '/'), -1) != '/') {
            $path .= '/';
        }

        return $server . $path . $url;
    }
This function returns the absolute URI for the partial URL passed.
The current scheme (HTTP/HTTPS), host server, port, current script
location are used if necessary to resolve any relative URLs.

Offsets potentially created by PATH_INFO are taken care of to resolve
relative URLs to the current script.

You can choose a new protocol while resolving the URI.  This is
particularly useful when redirecting a web browser using relative URIs
and to switch from HTTP to HTTPS, or vice-versa, at the same time.

@param string  $url      Absolute or relative URI the redirect should
go to.
@param string  $protocol Protocol to use when redirecting URIs.
@param integer $port     A new port number.

@return string The absolute URI.
@author Philippe Jausions <Philippe.Jausions@11abacus.com>