Symfony 3:控制器中Curl GET请求超时,命令行下正常
兄弟,这种本地脚本跑的好好的,一放到Symfony控制器里就掉链子的问题真的太磨人了!我之前也踩过类似的坑,给你捋几个大概率的排查方向,你挨个试试:
先抓具体错误!别瞎猜
你现在只知道请求没成功,但根本不知道问题出在哪。赶紧给你的curl代码加上错误捕获逻辑,把细节打出来:$url = 'https://haveibeenpwned.com/api/v3/breachedaccount/'.$email; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 开启 verbose 模式抓详细日志 curl_setopt($ch, CURLOPT_VERBOSE, true); $verboseLog = fopen('php://temp', 'w+'); curl_setopt($ch, CURLOPT_STDERR, $verboseLog); $response = curl_exec($ch); if ($response === false) { rewind($verboseLog); $errorDetails = stream_get_contents($verboseLog); // 把错误日志输出到Symfony日志或者直接打印(测试用) error_log($errorDetails); die('Curl错误:'.curl_error($ch)); } curl_close($ch);有了具体错误信息,你就能知道是SSL验证失败、连接超时还是权限问题,比瞎试效率高100倍。
检查Web服务器的网络权限
普通PHP脚本是你用CLI跑的,用的是你当前用户的网络权限;但Symfony跑在Apache/Nginx这些Web服务器进程下(比如www-data用户),这个用户可能被服务器防火墙限制了对外访问,甚至连域名解析都做不了。
你可以先在服务器上用Web服务器用户试试curl命令:sudo -u www-data curl https://haveibeenpwned.com/api/v3/breachedaccount/test@example.com如果这步也失败,那就是服务器网络的问题,得找运维开对外访问权限或者配置代理。
SSL证书验证的坑
haveibeenpwned用的是HTTPS协议,curl默认会验证SSL证书。你的CLI环境可能有正确的CA证书,但Web服务器的PHP环境里CA证书路径没配置对,直接导致验证失败。
可以先临时关闭验证(仅限测试!上线绝对不能这么干):curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);如果这样能成功,那就是CA证书的问题。正确的做法是给curl指定服务器上的CA证书路径,比如Ubuntu系统一般是:
curl_setopt($ch, CURLOPT_CAINFO, '/etc/ssl/certs/ca-certificates.crt');CentOS系统可能是
/etc/pki/tls/certs/ca-bundle.crt,具体看你服务器的配置。换Symfony HttpClient试试(更省心)
其实Symfony自带的HttpClient组件比原生curl更适配Symfony环境,还能自动处理很多配置问题(比如SSL、超时、日志),而且代码更简洁。你可以试试替换成这个:
首先确保HttpClient组件已安装(Symfony 4.3+默认自带),然后在控制器里这么写:use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Component\HttpFoundation\Request; class EmailCheckController extends AbstractController { public function check(HttpClientInterface $client, Request $request) { $email = $request->request->get('email'); // 注意:haveibeenpwned的API要求必须带User-Agent,不然会返回403! $response = $client->request('GET', 'https://haveibeenpwned.com/api/v3/breachedaccount/'.$email, [ 'headers' => [ 'User-Agent' => '你的Symfony应用名称', ], ]); $statusCode = $response->getStatusCode(); $data = $response->toArray(); // 后续处理返回数据 } }这里要重点提一句:haveibeenpwned的API强制要求请求头带User-Agent,之前你用curl的时候是不是没加这个?这很可能就是核心问题!
检查PHP版本和扩展一致性
有时候CLI用的PHP版本和Web服务器用的PHP版本不一样,比如CLI是PHP7.4,Web是PHP7.2,可能curl的配置或者扩展版本有差异。你可以在控制器里输出phpinfo()看看curl的配置,再和CLI下的php -i | grep curl对比一下,确认两者的curl环境一致。
内容的提问来源于stack exchange,提问作者VULCHOK

