重写规则中的西里尔字符导致404未找到错误

时间:2016-01-20 作者:Willington Vega

我有一个包含页面URI的重写规则:

(<page-uri>)/someaction/(\\d+)
如果页面的URI包含西里尔文字符,例如доска-объявлений, 规则存储为:

(%d0%b4%d0%be%d1%81%d0%ba%d0%b0-%d0%be%d0%b1%d1%8a%d1%8f%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b9)/someaction/(\\d+)
如果您转到包含指向与规则匹配的URL的链接的页面并单击该链接,浏览器将加载目标页面而不会出现问题,WordPress能够将规则与请求的URL匹配。

但是,在Safari(Mac)中,如果使用右键单击>复制链接复制URL,然后尝试通过将复制的URL粘贴到新选项卡来加载目标页面,则会出现404 Not Found错误。

在Safari中复制URL时,URL以百分比编码存储,字符用于表示西里尔文字符的八位字节,所有字符均为大写:

%D0%B4%D0%BE%D1%81%D0%BA%D0%B0-%D0%BE%D0%B1%D1%8A%D1%8F%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9/someaction/1
我无法在Chrome或Firefox(都是Mac)中重现这个问题,因为它们都使用小写字符来表示八位字节来存储URL。

带有百分比编码的URL是WordPress通过$_SERVER[\'REQUEST_URI\'] 变量问题是,负责将请求的URI与重写规则匹配的代码会进行区分大小写的比较(请参阅parse_request 中的方法/wp-includes/class-wp.php), 让WordPress无法接受我的规则

%D0%B4%D0%BE%D1%81%D0%BA%D0%B0-%D0%BE%D0%B1%D1%8A%D1%8F%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9
以及

%d0%b4%d0%be%d1%81%d0%ba%d0%b0-%d0%be%d0%b1%d1%8a%d1%8f%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b9
表示相同的字符序列。

当浏览器使用不同大小写的八位字节发送请求时,有人知道如何防止404未找到错误吗

1 个回复
SO网友:Willington Vega

我最终遵循了@KolyaKorobochkin的建议,添加了包含转义八位字节的重写规则的大小写版本。

$regular_page_uri = get_page_uri( $page->ID );

$uppercase_page_uri = preg_replace_callback(
    \'/%[0-9a-zA-Z]{2}/\',
    create_function( \'$x\', \'return strtoupper( $x[0] );\' ),
    $regular_page_uri
);
ThePercent Encode Capital Letter 插件使用类似的方法将每个URL中的八位字节转换为大写版本。然而,插件已经过时,可能无法在所有必要的地方进行转换。此外,我相信我正在开发的插件的大多数用户不会有带有编码八位字节的URL,所以运行preg_replace_callback 对于所有URL来说,都是不必要的工作。

建议使用大写字符表示八位字节进行百分比编码(请参阅RFC3986, 第2.1节)。因此,更好的解决方案是让WordPress更新utf8_uri_encode 函数使用它们来转义八位字节。我测试的大多数浏览器似乎都保持原来的大小写,而其他浏览器,如Safari,如果有机会的话,会将其转换为大写。

相关推荐