PHP:如何将相对 URL 转换为绝对 URL

要从相对 URL 构建绝对 URL,我们需要知道请求协议和主机名,然后我们可以将其添加到相对 URL 以生成绝对 URL。

我们还需要解析 URL 中的 ..(双点符号)。
双点表示客户端应该在父段中查找文件;每次出现“..”都应该在 URL 3 中移动“一个”。
我建议永远不要在 URL 中使用双点,因为它可能会让某些人感到困惑。
尽管如此,我们的函数在遇到这些段时仍然应该能够处理。

为了同时解析 URL 中的“..”声明,我在循环中使用了 preg_replace 来递归删除相关段。

解决方案:

function get_absolute_path($url) {
  //Determine request protocol
  $request_protocol = $request_protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
  //If dealing with a Protocol Relative URL
  if (stripos($url, '//') === 0) {
    return $url;
  }
  //If dealing with a Root-Relative URL
  if (stripos($url, '/') === 0) {
    return $request_protocol . '://' . $_SERVER['HTTP_HOST'] . $url;
  }
  //If dealing with an Absolute URL, just return it as-is
  if (stripos($url, 'http') === 0) {
    return $url;
  }
  //If dealing with a relative URL,
  //and attempt to handle double dot notation ".."
  do {
    $url = preg_replace('/[^\/]+\/\.\.\//', '', $url, 1, $count);
  } while ($count);
  //Return the absolute version of a Relative URL
  return $request_protocol . '://' . $_SERVER['HTTP_HOST'] . '/' . $url;
}

此功能仅适用于现场网址,如果我们想处理在外部资源中找到的网址,则需要修改。

处理 URL 段

URL 由几个不同的部分组成,但就本教程而言,我们最感兴趣的是路径,即主机名(如果存在)之后的部分。

  1. 要构造绝对 URL,我们首先需要确定 request_protocol:
$request_protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');

上面的 one-liner 尝试建立用于当前请求的协议。
完成此操作后,应首先将其放在 URL 中。
即:https://[HTTP_HOST] /[路径]

剩下的部分可以在返回完成的 URL 时直接插入。

  1. 在下一步中,我们需要确保我们没有处理协议相对 URL。
    这种类型的 URL 的工作方式类似于绝对 URL,只是没有指定协议。
    如果我们的函数被提供了一个绝对 URL 或者一个协议相对 URL,我们应该只按原样返回 URL,而不修改它。

当打开一个协议相对 URL 时,客户端将使用在第一个请求中使用的相同协议。

我们可以使用 stripos 函数轻松检查这一点:

//If dealing with a Protocol Relative URL
if (stripos($url, '//') === 0) {
  return $url;
}

这将检查前两个字符是否为两个正斜杠“//”,如果是,则返回完整的 $url。

  1. 接下来,我们检查 URL 是否是相对于 root 的:
if (stripos($url, '/') === 0) {
  return $request_protocol . '://' . $_SERVER['HTTP_HOST'] . $url;
}

如果 URL 是相对于 root 的,我们只需要添加协议和主机。

  1. 现在我们检查 URL 是否已经是绝对的,如果是,我们返回它。
    为此,我们检查 URL 是否以“http”开头:
if (stripos($url, 'http') === 0) {
  return $url;
}

当然,这仅适用于使用 HTTP 协议的 URL。
如果我们希望它与其他协议一起工作,我们可以使用正则表达式来代替。

  1. 最后我们处理相对 URL。
    可以在 URL 中使用双点符号“..”(也称为点段)来到达 URL 中的父段。
    每个段由正斜杠“/”分隔,类似于在硬盘分区上分隔目录的方式。

虽然在绝对 URL 中使用双点没有任何意义,但在某些浏览器中,它实际上似乎不管用。
但是,在这个函数中,我们将只处理包含在相对 URL 中的点。

为此,我们可以在 do while 循环中使用 preg_replace:

do {
  $url = preg_replace('/[^\/]+\/\.\.\//', '', $url, 1, $count);
} while ($count);
return $request_protocol . '://' . $_SERVER['HTTP_HOST'] . '/' . $url;

该模式匹配一个普通段,后跟一个双点段。
即:something/../,然后递归删除它们,直到找不到更多匹配项。

如果点段的数量不等于正常段的数量,则删除任何剩余的点段。

日期:2020-06-02 22:17:24 来源:oir作者:oir