最近我开始遇到一段已经稳定了一段时间的代码的问题。它与 GameStop 建立连接以检索那里的页面。多年来工作正常,但现在返回超时。
起初我以为涉及某种 IP 或用户代理阻止。然而,我在 DigitalOcean 和 Vultr 上都启动了全新的机器,并且都遇到了同样的问题。尽管如此,所有机器都可以通过命令行使用 cURL 并正常检索页面。
奇怪的是,代码也可以在我的本地开发机器(Windows 机器)上运行。那么,不确定问题是否与在 Linux 上运行的 PHP 有关?
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'https://www.gamestop.com/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
//curl_setopt($ch, CURLOPT_SSLVERSION, 6); -explicitly use TLS v1.2
$html = curl_exec($ch);
$info = curl_getinfo($ch);
$error = curl_error($ch);
curl_close($ch);
echo '<pre>' . var_export($error, true) . '</pre>'
. '<pre>' . var_export($info, true) . '</pre>'
. 'HTML: <textarea>' . $html . '</textarea>';
?>
上面的代码在我尝试运行它的任何非本地环境中都会返回超时。在相同的环境中,可以通过命令行使用 cURL 获取页面。我发现了一些类似的问题,但大多数都指向 SSL/TLS 版本的问题。也尝试过对此进行测试(请参阅注释掉的行),但结果相同。
问题的一部分是,我不确定是否有真正的方法来调试来自服务器的超时,因为实际上任何事情都可能导致它。我一直在寻找的唯一真正线索是它可以在 Windows 机器上运行,并且可以在更高环境中的命令行上运行。任何帮助或见解将不胜感激!
编辑:也能够在 Windows Server 2016 VM 上重现该问题。
很可能是因为curl-cli自动添加用户代理标头,而libcurl/php则不会。
涉及某种 IP 或用户代理阻止。然而,我在 DigitalOcean 和 Vultr 上都安装了全新的机器,并且都遇到了同样的问题
在 DigitalOcean/Vultr 上设置 VM 不会自动使 libcurl 将用户代理标头添加到您的 https 请求中。可以通过以下方式完成:
curl_setop($ch,CURLOPT_USERAGENT,"curl/".(curl_version()["version"])); // User-Agent: curl/7.52.1
模仿curl-cli的用户代理字符串,或者类似的东西
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");
假装您是 Google Chrome 版本 71,在 Windows 7 x64 上运行。
许多网站(例如 Wikipedia.com)会阻止缺少 User-Agent 标头的 http 请求。
虽然它并没有真正解释为什么会发生这种情况,但我可以通过在 PHP 中使用 shell_exec 直接执行命令行 cURL,然后检索/处理结果来解决这个问题。