如何获取已发送的PHP curl请求的信息

76

我正在尝试调试一个针对webservice 'getToken'端点的curl请求。

我不太确定URL和身份验证信息是否被正确地写入了curl句柄中。

我尝试使用curl_getinfo($ch, CURLINFO_HEADER_OUT);来捕获发送的请求,但它并没有给我很多信息。是否有一种方式可以获得关于实际curl请求的更深入诊断信息?

以下是代码:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");       
curl_setopt($ch, CURLOPT_HEADER, 1); // just getting header to see if we got an auth token
curl_setopt($ch, CURLOPT_FILE, $fh);
curl_setopt($ch, CURLOPT_NOBODY, 1); 
curl_setopt($ch, CURLINFO_HEADER_OUT, 1); // capture the header info
curl_setopt($ch, CURLOPT_VERBOSE, 1); // turn verbose on    
// execute the curl request 

$rh = fopen("request.txt", "w"); // open request file handle
$verbose = fopen('php://temp', 'rw+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);

curl_exec($ch); // execute request

$sent_request = curl_getinfo($ch, CURLINFO_HEADER_OUT);
fwrite($rh, $sent_request); // save the request info
fclose($rh);
!rewind($verbose);
$verboseLog = stream_get_contents($verbose);

echo "Verbose information:\n<pre>", htmlspecialchars($verboseLog), "</pre>\n";

就目前为止,所有的都运作正常,但每次都返回401错误——API管理员向我保证我使用的用户名/密码是正确的。

我在想是否我的URL值有问题,或者没有发送正确的用户名/密码,但是这些信息没有被保存在请求数据中:

HEAD /export/auth HTTP/1.1
Authorization: Basic Y2FpcmRzdW5mYTpENWlAaVM4cw==
Host: webservices.mycompany.com
Accept: */*

你可以看到用户名/密码并没有被记录(我认为是出于安全考虑)。我想终端URL是host值加上HEAD值的开头,所以是webservices.mycompany.com/export/auth

“详细信息”语句没有输出。我也不确定为什么!

谢谢帮助。

编辑:根据评论者immulatin提供的Php - Debugging Curl添加了详细模式。


你可以将 verbose 设置为 true:https://dev59.com/questions/z2865IYBdhLWcg3wkPSD - immulatin
我首先要检查的是,我会使用最少的参数进行更简单的请求,并手动输入所有变量值(url、登录名、密码)。像这样的奇怪错误通常是由于输入格式不正确,例如额外的空格等造成的。 - Ranty
我认为这篇旧帖子可能会有用。https://dev59.com/UXNA5IYBdhLWcg3wrf83 - nik.longstone
4个回答

108
如果您将CURLINFO_HEADER_OUT设置为true,则出站标头可在由curl_getinfo()返回的数组中找到,在request_header键下:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://foo.com/bar");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "someusername:secretpassword");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

curl_exec($ch);

$info = curl_getinfo($ch);
print_r($info['request_header']);

这会打印出:

GET /bar HTTP/1.1
Authorization: Basic c29tZXVzZXJuYW1lOnNlY3JldHBhc3N3b3Jk
Host: foo.com
Accept: */*

请注意,身份验证详细信息已进行base64编码:

echo base64_decode('c29tZXVzZXJuYW1lOnNlY3JldHBhc3N3b3Jk');
// prints: someusername:secretpassword

请注意,用户名和密码需要进行百分号编码以转义可能包含的URL保留字符(/?&:等):

curl_setopt($ch, CURLOPT_USERPWD, urlencode($username).':'.urlencode($password));

1
7年过去了,这条评论仍然非常有帮助,正是我所需要的。 - Beee
curl_getinfo() 必须在 curl_exec() 之后使用。 - udith

6
在关闭curl处理器之前必须添加curl_getinfo()
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/bar");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "someusername:secretpassword");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_exec($ch);
$info = curl_getinfo($ch);
print_r($info['request_header']);
curl_close($ch);

5
curl_getinfo() 必须在 curl_exec() 之后使用,所以你的代码是错误的! - Nabi K.A.Z.
而且这些代码行已经被切换了,答案也得到了纠正,并且有效性得到了提高 :-) - Erenor Paz

4
您也可以使用代理工具,例如Charles,通过将代理详细信息传递到curl_setopt_array方法中的CURLOPT_PROXY来捕获出站请求标题、数据等。
例如:
$proxy = '127.0.0.1:8888';
$opt = array (
    CURLOPT_URL => "http://www.example.com",
    CURLOPT_PROXY => $proxy,
    CURLOPT_POST => true,
    CURLOPT_VERBOSE => true,
    );

$ch = curl_init();
curl_setopt_array($ch, $opt);
curl_exec($ch);
curl_close($ch);

2
请求会以详细信息的形式打印在 request.txt 文件中。
$ch = curl_init();
$f = fopen('request.txt', 'w');
curl_setopt_array($ch, array(
CURLOPT_URL            => $url, 
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_VERBOSE        => 1,
CURLOPT_STDERR         => $f,
));
$response = curl_exec($ch);
fclose($f);
curl_close($ch);

您也可以使用curl_getinfo()函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接