php - URL 中带有“И”和“Э”utf-16 符号的 PHP 7 fopen/file_get_contents 甚至无需调用服务器即可返回 HTTP 500(适用于 PHP8)
问题描述
当在 url 链接中使用两个大写西里尔字母“И”和“Э”之一时,会出现奇怪的行为:
file_get_contents("http://localhost/И")
fopen("http://localhost/И", "r")
两者都返回以下错误,但服务器甚至没有被调用:
failed to open stream: HTTP request failed! HTTP/1.1 500 Internal Server Error
有人知道这是已知问题吗?是否报告了错误?
似乎它在 PHP8 中已修复,但为什么会发生此错误?
PS。这与向请求添加标头无关(我尝试过)-甚至没有发生调用。
更新:检查了本地 nginx 日志,并且确实调用了服务器,这就是我对这两个符号所拥有的 - php 将 unicode 符号的第二部分视为“_”:
"GET /\xD0_ HTTP/1.0" 500 <---- php7-
"GET /\xD0\x98 HTTP/1.0" 404 <---- php8
更新 2:我发现不仅这两个符号在 PHP 7 中有这样的问题,而且在 UTF-8 表的十六进制代码中以“98”或“ad”结尾的每个符号,这里是其他符号的示例相同的行为:
file_get_contents("http://localhost/ϭ"); // cf ad
file_get_contents("http://localhost/Θ"); // ce 98
file_get_contents("http://localhost/Ҙ"); // d2 98
file_get_contents("http://localhost/ј"); // d1 98
file_get_contents("http://localhost/ѭ"); // d1 ad
file_get_contents("http://localhost/Ә"); // d3 ad
file_get_contents("http://localhost/‘"); // e2 80 98
file_get_contents("http://localhost/ĭ"); // c4 ad
file_get_contents("http://localhost/Ę"); // c4 98
解决方案
因为http://localhost/И
是格式错误的 URL,您需要对包含 127 以上代码点的路径组件进行 urlencode。您的浏览器以及可能的一些 HTTP 库透明地执行此操作,但在 PHP 中使用文件/流函数调用 URL 绝对不会。
// because this is what I copy/pasted off of SO, which is UTF8
$in_8 = 'И';
// your endianness may vary
$in_16 = mb_convert_encoding($in_8, 'UTF-16LE', 'UTF-8');
$url_8 = 'http://example.com/'.urlencode($in_8);
$url_16 = 'http://example.com/'.urlencode($in_16);
var_dump(
bin2hex($in_8),
$url_8,
bin2hex($in_16),
$url_16
);
输出:
string(4) "d098"
string(25) "http://example.com/%D0%98"
string(4) "1804"
string(25) "http://example.com/%18%04"
推荐阅读
- r - 如何让我的线条更贴合、更整洁?
- php - 恢复下拉列表中用户的值
- java - 检索 veterinary_care 和 pet_store Android Studio 的地点类型中的零结果
- java - Json 字段已触发 -- JDBC 类型没有方言映射:来自 nativeQuery 的 1111
- java - Swagger 与 Springboot 使用 java 注释添加个性化信息
- r - 动画叠加线图 R
- python - Google Sheets/Drive API 的权限不足错误:“提供的 OAuth 范围或 ID 令牌受众无效”
- reactjs - 删除并重新安装 create-react-app 会给我现有的项目带来问题吗?
- c# - 将xml标签序列化为c#字典
- webrtc - 浏览器引擎会限制 WebRTC 速度吗?