curl時設置Expect的必要性

原文:https://www.fanhaobai.com/2017/08/curl-expect-continue.html

curl 在項目中使用頻率較高,比如內部接口、第三方 api、圖片存儲服務等,但是我們在使用 curl 時可能并沒有注意到 Expect 這個請求頭信息,而 Expect 設置不正確,會導致不必要的一次 HTTP 請求,甚至可能會導致業務邏輯錯誤。

問題

在不設置 Expect 頭信息使用 curl 發送 POST 請求時,如果 POST 數據大于 1kb,curl 默認行為 如下:

  1. 先追加一個Expect: 100-continue請求頭信息,發送這個不包含 POST 數據的請求;
  2. 如果服務器返回的響應頭信息中包含Expect: 100-continue,則表示 Server 愿意接受數據,這時才 POST 真正數據給 Server;

通過 tcpdump 工具抓包 curl 客戶端網絡請求。查看 HTTP 請求響應頭以及數據:

$ tcpdump -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

請求信息內容:

23:04:15.498902 IP bogon.35808 > 10.16.**.***.http: Flags [P.], seq 1749154338:1749154696, ack 673671676, win 14600, length 358
E.....@.@.8...U.
......PhA."('i.P.9.]Q..POST /* HTTP/1.1
User-Agent: GuzzleHttp/6.2.1 curl/7.19.7
Content-Type: application/json
Host: *.t.ziroom.com
Content-Length: 24343
Expect: 100-continue

響應信息:

23:04:15.499869 IP 10.16.**.***.http > bogon.35808: Flags [P.], seq 1:26, ack 358, win 64240, length 25
E..A......2.
.....U..P..('i.hA..P.......HTTP/1.1 100 Continue

可見此時,curl 發送了一次不必要的 HTTP 請求,從系統性能上來說這是不允許的。另外,并不是所有的 Server 都會正確響應100-continue,反而會返回417 Expectation Failed,curl 端不會發起數據 POST 請求,則會造成業務邏輯錯誤,我們應該避免這種情況的發生。

解決辦法

如果查看過一些開源類庫(guzzle、qq第三方api,不過 solarium 并未支持),你就會發現他們在 curl 時已經注意到并解決這個問題了,只需 設置 Expect 請求頭為空 即可。

// qq第三方api
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

// guzzle的curl Adapter
if (!$request->hasHeader('Expect')) {
    $conf[CURLOPT_HTTPHEADER][] = 'Expect:';
}

再次 tcpdump 抓包,發現使用 curl 發送超過 1kb 的 POST 數據時,也并未出現 100-continue 的 HTTP 請求。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容