當使用 cURL POST 大於 1024 位元組的資料時,libcurl 預設啟用 Expect: 100-continue 機制:先發送含此 Header 的請求詢問伺服器是否願意接收實體,收到 100 Continue 回應後再傳送 Body。部分伺服器(如 Lighttpd、舊版 Nginx、某些代理)不支援或拒絕此機制,回傳 417 Expectation Failed,導致請求失敗。
Expect: 100-continue100 Continue417 或直接斷線參考 RFC 2616 Section 8.2.3。
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Expect:"));
設定空的 Expect: Header 會覆蓋 cURL 自動加入的 Expect: 100-continue,強制直接發送完整請求。
$ch = curl_init('https://api.example.com/endpoint');
$data = json_encode(['large_field' => str_repeat('x', 2000)]); // > 1KB
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Expect:' // 關鍵:禁用 100-continue
],
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception(curl_error($ch), curl_errno($ch));
}
curl_close($ch);
| 方案 | 優點 | 缺點 |
|---|---|---|
Expect: 空 Header | 簡單、相容性佳、無副作用 | 失去 100-continue 節省頻寬的優勢(極少數場景需求) |
CURLOPT_PROTOCOLS 限制 | 無 | 不解決核心問題 |
分塊傳輸 Transfer-Encoding: chunked | 標準機制 | 需伺服器支援、實作複雜 |
CURLOPT_POSTFIELDS 為字串(非陣列),陣列會發送 multipart/form-data 觸發不同邏輯417 狀態碼curl -v 抓包驗證請求 Header['headers' => ['Expect' => '']]一行配置解決棘手的 417 錯誤,建議所有對外 HTTP 客戶端預設加入。