使用 cURL POST 資料時,若資料長度超過 1024 位元組,libcurl 會自動啟用 Expect: 100-continue 機制:
Expect: 100-continue 標頭的請求,詢問伺服器是否願意接收資料100 Continue 回應後,才發送實際 POST 主體此行為符合 HTTP/1.1 規範(RFC 2616 Section 8.2.3),但部分伺服器(如 Lighttpd、舊版 Nginx、某些代理)不支援或拒絕回應 100 Continue,導致請求掛起或回傳 417 Expectation Failed。
在 curl_setopt 中設定空的 Expect: 標頭,禁用此機制:
<?php
$ch = curl_init('https://api.example.com/endpoint');
$postData = json_encode(['large' => 'data...']); // 超過 1024 bytes
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Expect:' // 關鍵:空值覆蓋預設的 Expect: 100-continue
],
]);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception('cURL 錯誤: ' . curl_error($ch));
}
curl_close($ch);
?>
CURLOPT_HTTPHEADER 允許覆蓋 libcurl 自動產生的標頭'Expect:'(冒號後無值)會發送 Expect: 空標頭,依 HTTP 規範視為「不期望 100-continue 回應」libcurl 內建閾值為 1024 位元組,無直接 API 修改。若必須保留 100-continue 機制,需確保目標伺服器正確支援。
<?php
function postWithCurl($url, $data, $headers = [], $timeout = 30) {
$ch = curl_init($url);
$defaultHeaders = [
'Content-Type: application/json',
'Expect:', // 預設禁用 100-continue
];
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => is_array($data) ? json_encode($data) : $data,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $timeout,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_HTTPHEADER => array_merge($defaultHeaders, $headers),
CURLOPT_SSL_VERIFYPEER => true, // 生產環境請保持 true
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
]);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($errno) {
throw new Exception("cURL 錯誤 ($errno): $error");
}
if ($info['http_code'] >= 400) {
throw new Exception("HTTP 錯誤 {$info['http_code']}: $response");
}
return $response;
}
// 使用範例
try {
$result = postWithCurl('https://api.example.com/items', [
'name' => '大量資料測試',
'description' => str_repeat('x', 2000), // 故意超過 1024 bytes
]);
echo $result;
} catch (Exception $e) {
error_log($e->getMessage());
}
?>
極少數情況:
對於 99% 的 API 串接場景,**建議預設禁用**以避免相容性問題。