Hugh's Blog

PHP cURL Content Type

最近在用 PHP cURL 发送数据给接口,但是接口并没有收到数据,返回了错误信息。

使用 curl_getinfo 查看请求头,发现 Content-Type 的值是 multipart/form-data,而且后面的消息体也经过了编码,以 boundary= 开头,而接口要求的值是 application/x-www-form-urlencoded,就算把 header 改了但是消息体依然会经过编码,导致接口无法获取到数据,后来查找文档才发现跟 CURLOPT_POSTFIELDS 设定的值有关。

$ch = curl_init();

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);

$params = ['foo1' => 'bar1', 'foo2' => 'bar2'];

// curl_setopt($ch, CURLOPT_HTTPHEADER, [
//     'Content-Type: application/x-www-form-urlencoded;charset=utf-8'
// ]);

curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params); // multipart/form-data
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); // application/x-www-form-urlencoded

// 调试信息输出报文
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

curl_setopt($ch, CURLOPT_URL, 'http://www.test.com');

$response = curl_exec($ch);
$curlInfo = curl_getinfo($ch);

curl_close($ch);

print_r($curlInfo);

按照文档的说明:

Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart/form-data, while passing a URL-encoded string will encode the data as application/x-www-form-urlencoded.

CURLOPT_POSTFIELDS 的值为数组时 Content-Typemultipart/form-data,当值为字符串 (foo1=bar1&foo2=bar2) 时为 application/x-www-form-urlencoded

输出 curl 调试信息分别可以看到请求报文:

POST / HTTP/1.1
Host: www.test.com
Accept: */*
Content-Length: 240
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------7e1652a1bc2ef857
POST / HTTP/1.1
Host: www.test.com
Accept: */*
Content-Length: 19
Content-Type: application/x-www-form-urlencoded