事情的起因是这样的,对接某个接口,一个POST
请求的请求体比较大(注:跟系统和curl
的版本有关,有的并不会发送Except
请求头),curl
默认给我发送了Expect
请求头,事前我并不知道,但一直没调通,对方就提出要看看我的HTTP
报文。
糟糕,你让我手写一个HTTP
请求报文,我分分钟就能写出来,不就这么简单么:
POST /xxx HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
name=lwlinux
你让我获取curl
的请求报文,突然就觉得有点懵,我还真找不到直接的接口来获取,不管是curl
命令还是使用了curl
库的php
,它都没有。只能采取折中的办法,curl
有个-v
选项,但--trace-ascii curl.trace.log
保存到文件中显然更适合处理,换成php
中的curl
,则对应以下代码:
<?php
$verboseFile = __DIR__. '/curl.trace.log';
$verboseFd = fopen($verboseFile, 'w+');
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $verboseFd);
一个完整的示例代码如下:
<?php
$url = 'http://nginx/programming_practice/php/snippets/php.php';
$body = http_build_query(['name' => str_repeat('lwlinux', 200)]);
$verboseFile = __DIR__. '/curl.trace.log';
$verboseFd = fopen($verboseFile, 'w+');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $verboseFd);
$resp = curl_exec($ch);
$respInfo = curl_getinfo($ch);
$curlError = curl_error($ch);
$curlErrno = curl_errno($ch);
curl_close($ch);
fclose($verboseFd);
var_dump(
'verbose ==============================================',
file_get_contents($verboseFile),
'request ==============================================',
$body,
'response ==============================================',
$resp,
'respInfo ==============================================',
$respInfo,
'curlError ==============================================',
$curlError,
'curlErrno ==============================================',
$curlErrno
);
以上代码输出片段如下,忽略一些多余的内容,应该大概能看懂吧。
* Expire in 0 ms for 6 (transfer 0x400160b760)
* Expire in 1 ms for 1 (transfer 0x400160b760)
* Expire in 0 ms for 1 (transfer 0x400160b760)
* Expire in 1 ms for 1 (transfer 0x400160b760)
* Trying 172.18.0.6...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x400160b760)
* Connected to nginx (172.18.0.6) port 80 (#0)
> POST /programming_practice/php/snippets/php.php HTTP/1.1
Host: nginx
Accept: */*
Content-Length: 1027
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue
* Expire in 1000 ms for 0 (transfer 0x400160b760)
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Server: nginx/1.19.2
< Date: Wed, 25 Dec 2024 01:30:42 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/7.4.10
<
* Connection #0 to host nginx left intact
看到了吧,POST /programming_practice/php/snippets/php.php HTTP/1.1
之后就是完整的请求头,只需要字符串操作一下就可以获取。当然curl
命令的-v
参数输出的样式看起来会相对舒服。记住,不是所有curl
命令都会发送Expect
请求头,这个是由curl
版本和系统决定的。
有没有Expect
不是重点,重点是学会怎么查看curl
的请求报文,这样对于调试接口会有很大的帮助。
curl
虽说方便,但也有用着不舒服的地方;php
也是,获取原始请求报文和响应报文这方面,确实令人不愉快。