PHP:比较百分比编码不同的 URI
Posted
技术标签:
【中文标题】PHP:比较百分比编码不同的 URI【英文标题】:PHP: comparing URIs which differ in percent-encoding 【发布时间】:2011-04-23 02:42:27 【问题描述】:在 php 中,我想比较两个相对 URL 是否相等。问题:URL 的百分比编码可能不同,例如
/dir/file+file
与 /dir/file%20file
/dir/file(file)
与 /dir/file%28file%29
/dir/file%5bfile
与 /dir/file%5Bfile
根据RFC 3986,服务器应该同等对待这些URI。但是如果我用==
来比较,我会得到一个不匹配的结果。
所以我正在寻找一个 PHP 函数,它将接受两个字符串并返回 TRUE
如果它们表示相同的 URI(在编码中区分相同字符的编码/解码变体、大写/小写十六进制数字字符,+
与 %20
用于空格),FALSE
(如果它们不同)。
我事先知道这些字符串中只有 ASCII 字符——没有 unicode。
【问题讨论】:
【参考方案1】:function uriMatches($uri1, $uri2)
return urldecode($uri1) == urldecode($uri2);
echo uriMatches('/dir/file+file', '/dir/file%20file'); // TRUE
echo uriMatches('/dir/file(file)', '/dir/file%28file%29'); // TRUE
echo uriMatches('/dir/file%5bfile', '/dir/file%5Bfile'); // TRUE
urldecode
【讨论】:
【参考方案2】:编辑:请查看@webbiedave 的回复。他的要好得多(我什至不知道 PHP 中有一个函数可以做到这一点.. 每天学习新东西)
您必须解析字符串以查找匹配 %##
的内容,以找到这些百分比编码的出现。然后从中获取数字,您应该能够传递它,以便 chr() 函数获取这些百分比编码的字符。重建字符串,然后你应该能够匹配它们。
不确定这是最有效的方法,但考虑到 URL 通常不会那么长,它应该不会对性能造成太大影响。
【讨论】:
【参考方案3】:我知道这里的这个问题似乎是由 webbiedave 解决的,但我有自己的问题。
第一个问题:编码字符不区分大小写。所以 %C3 和 %c3 都是完全相同的字符,尽管它们作为 URI 是不同的。所以两个 URI 都指向同一个位置。
第二个问题:folder%20(2) 和 folder%20%282%29 都是有效的 urlencoded URI,它们指向同一个位置,尽管它们是不同的 URI。
第三个问题:如果我去掉 url 编码的字符,我有两个位置具有相同的 URI,例如 bla%2Fblubb 和 bla/blubb。
那该怎么办呢?为了比较两个 URI,我需要对它们进行规范化,将它们拆分为所有组件,对所有路径和查询部分进行一次 urldecode,对它们进行 rawurlencode 并将它们粘合在一起,然后我可以比较它们。
这可能是标准化它的功能:
function normalizeURI($uri)
$components = parse_url($uri);
$normalized = "";
if ($components['scheme'])
$normalized .= $components['scheme'] . ":";
if ($components['host'])
$normalized .= "//";
if ($components['user']) //this should never happen in URIs, but still probably it's anything can happen thursday
$normalized .= rawurlencode(urldecode($components['user']));
if ($components['pass'])
$normalized .= ":".rawurlencode(urldecode($components['pass']));
$normalized .= "@";
$normalized .= $components['host'];
if ($components['port'])
$normalized .= ":".$components['port'];
if ($components['path'])
if ($normalized)
$normalized .= "/";
$path = explode("/", $components['path']);
$path = array_map("urldecode", $path);
$path = array_map("rawurlencode", $path);
$normalized .= implode("/", $path);
if ($components['query'])
$query = explode("&", $components['query']);
foreach ($query as $i => $c)
$c = explode("=", $c);
$c = array_map("urldecode", $c);
$c = array_map("rawurlencode", $c);
$c = implode("=", $c);
$query[$i] = $c;
$normalized .= "?".implode("&", $query);
return $normalized;
现在您可以将 webbiedave 的功能更改为:
function uriMatches($uri1, $uri2)
return normalizeURI($uri1) === normalizeURI($uri2);
应该可以。是的,它比我想要的要复杂得多。
【讨论】:
以上是关于PHP:比较百分比编码不同的 URI的主要内容,如果未能解决你的问题,请参考以下文章
在 react-router 中使用百分比( % )登录:id
RFC3986 - 哪些 pchars 需要进行百分比编码?