RCA:未注意Curl-library Post 1024以上字節時的HTTP/1.1特性導致 HessianPHP 傳輸數據失敗


先列出 HessianPHP 的錯誤提示:

    CURL transport error: transfer closed with outstanding read data remaining


基礎知識背景:
1)“Expect: 100-continue”的來龍去脈:
    HTTP/1.1 協議里設計 100 (Continue) HTTP 狀態碼的的目的是,在客戶端發送 Request Message 之前,HTTP/1.1 協議允許客戶端先判定服務器是否願意接受客戶端發來的消息主體(基於 Request Headers)。
    即, Client 和 Server 在 Post (較大)數據之前,允許雙方“握手”,如果匹配上了,Client 才開始發送(較大)數據
    這么做的原因是,如果客戶端直接發送請求數據,但是服務器又將該請求拒絕的話,這種行為將帶來很大的資源開銷。
 
    協議對 HTTP/1.1 clients 的要求是:
如果 client 預期等待“100-continue”的應答,那么它發的請求必須包含一個 " Expect: 100-continue"  的頭域!
 
2)libcurl 發送大於1024字節數據時啟用“Expect:100-continue‘特性:

    這也就是 Laruence 在 2011 年撰文所寫的:

在使用 curl 做 POST 的時候,當要 POST 的數據大於 1024 字節的時候,curl 並不會直接就發起 POST 請求,而是會分為兩步:
1. 發送一個請求,包含一個 "Expect: 100-continue" 頭域,詢問 Server 是否願意接收數據;
2. 接收到 Server 返回的 100-continue 應答以后,才把數據 POST 給 Server;
這是 libcurl 的行為。

 

    zxgfa 在 2012年補充說:

 第一,libcurl 在發送大於 1024 字節的 POST 請求時采用了這種方法,但是相對的,它會引起請求延遲的加大。

第二,並不是所有的 web server 都能正確處理並應答“100-continue”,比如 lighttpd,就會返回417” Expectation Failed “,造成請求邏輯出錯。
鄭昀注1:lighttpd   1.4 版本有此嚴重問題,於1.5版本修復。
鄭昀注2:Resin 於 3.0.5 版本增加了對 Expect: 100-continue 的支持。)

 

3)PHP Curl-library 可以主動封禁此特性:
    有人在   PHP手冊::curl_setopt  下留言說:
    PHP curl 遵從 libcurl 的特性。由於不是所有 web servers 都支持這個特性,所以會產生各種各樣的錯誤。如果你遇到了,可以用下面的命令封禁"Expect"頭域:    
    <?php
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
    ?>
    pooy示范代碼如下所示:
    http://images.cnblogs.com/cnblogs_com/zhengyun_ustc/255879/o_clipboard%20-%20%e5%89%af%e6%9c%ac%20-%2038.png
    圖1 You can convince PHP's curl backend to stop doing the 100-continue-thing by setting an explicit request header
 

其他知識背景:

問題現象:

通信協議是 Hessian。
調用接口時所傳參數在某種極端條件下, POST 的數據長度超過 1024 字節,hessian 報錯“CURL transport error: transfer closed with outstanding read data remaining”。
 
解決:
修改hessian中 CURLOPT 項:
CURLOPT_HTTPHEADER => array("Content-Type: application/binary") 
改為
CURLOPT_HTTPHEADER => array("Content-Type: application/binary","Expect:") 

p.s.:
    有人認為改為 HTTP/1.0 協議即可繞過這個 100-continue 問題,但這只是工程師不願意搞清楚原理而示弱的表現。
 
參考資源:
1)2011,Laruence, Expect:100-continue
3)HTTP 1.1 RFC, Use of the 100 (Continue) Status
4)stackoverflow,2009, PHP HTTP POST fails when cURL data > 1024
6)lighttpd,2009, 'Expect' header gives HTTP error 417

贈圖幾枚:
請施主拿去:
http://ww2.sinaimg.cn/bmiddle/6e8138cfjw1e7vf8ouv2jj20c80gfabt.jpg
360度后空翻開球:
http://ww3.sinaimg.cn/bmiddle/61ecbb3djw1e7sad5gpmng205k034av6.gif
360無死角:
http://ww4.sinaimg.cn/bmiddle/6c55b8b5gw1e7i07zq3avj211s1kwqfv.jpg
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM