要从相对 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 由几个不同的部分组成,但就本教程而言,我们最感兴趣的是路径,即主机名(如果存在)之后的部分。
- 要构造绝对 URL,我们首先需要确定 request_protocol:
$request_protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http');
上面的 one-liner 尝试建立用于当前请求的协议。
完成此操作后,应首先将其放在 URL 中。
即:https://[HTTP_HOST] /[路径]
剩下的部分可以在返回完成的 URL 时直接插入。
- 在下一步中,我们需要确保我们没有处理协议相对 URL。
这种类型的 URL 的工作方式类似于绝对 URL,只是没有指定协议。
如果我们的函数被提供了一个绝对 URL 或者一个协议相对 URL,我们应该只按原样返回 URL,而不修改它。
当打开一个协议相对 URL 时,客户端将使用在第一个请求中使用的相同协议。
我们可以使用 stripos 函数轻松检查这一点:
//If dealing with a Protocol Relative URL if (stripos($url, '//') === 0) { return $url; }
这将检查前两个字符是否为两个正斜杠“//”,如果是,则返回完整的 $url。
- 接下来,我们检查 URL 是否是相对于 root 的:
if (stripos($url, '/') === 0) { return $request_protocol . '://' . $_SERVER['HTTP_HOST'] . $url; }
如果 URL 是相对于 root 的,我们只需要添加协议和主机。
- 现在我们检查 URL 是否已经是绝对的,如果是,我们返回它。
为此,我们检查 URL 是否以“http”开头:
if (stripos($url, 'http') === 0) { return $url; }
当然,这仅适用于使用 HTTP 协议的 URL。
如果我们希望它与其他协议一起工作,我们可以使用正则表达式来代替。
- 最后我们处理相对 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/../,然后递归删除它们,直到找不到更多匹配项。
如果点段的数量不等于正常段的数量,则删除任何剩余的点段。