萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP cURL Expect: 100-continue 問題分析與解決方案

當使用 cURL POST 大於 1024 位元組的資料時,libcurl 預設啟用 Expect: 100-continue 機制:先發送含此 Header 的請求詢問伺服器是否願意接收實體,收到 100 Continue 回應後再傳送 Body。部分伺服器(如 Lighttpd、舊版 Nginx、某些代理)不支援或拒絕此機制,回傳 417 Expectation Failed,導致請求失敗。

問題原理

  1. cURL 偵測 POST Body > 1024 bytes
  2. 自動加入 Header:Expect: 100-continue
  3. 等待伺服器回應 100 Continue
  4. 伺服器不支援 → 回傳 417 或直接斷線
  5. cURL 不再發送 Body,請求失敗

參考 RFC 2616 Section 8.2.3。

解決方案:發送空 Expect Header 禁用機制

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
  • 若使用 Guzzle:['headers' => ['Expect' => '']]

一行配置解決棘手的 417 錯誤,建議所有對外 HTTP 客戶端預設加入。

copyright © 萬盛學電腦網 all rights reserved