2010-06-03 30 views
25

我正在寫一個簡單的HTTP服務器,它將接受大部分來自cURL的PUT請求作爲客戶端,而我在處理Expect: 100-continue標題時遇到了一些問題。如何處理「100個繼續」HTTP消息?

據我瞭解,服務器應該讀頭,發回連接上一個HTTP/1.1 100 Continue響應,讀取流達價值上Content-Length,然後發回真正的響應代碼(通常HTTP/1.1 200 OK但任何其他有效的HTTP答案應該這樣做)。

那麼,這正是我的服務器所做的。問題是,顯然,如果我發送100 Continue答案,cURL將無法報告任何後續的HTTP錯誤代碼,並假定上傳成功。例如,如果由於內容的性質(發生基本數據檢查)而導致上傳被拒絕,我希望呼叫客戶端檢測問題並採取相應措施。

我錯過了一些明顯的東西嗎?

編輯:這裏是捲曲的示例輸出與輔助頭包含錯誤:

> PUT /test1%2Epdf HTTP/1.1 
> Authorization: Basic xxxx 
> User-Agent: curl/7.20.0 (i386-pc-win32) libcurl/7.20.0 OpenSSL/0.9.8l zlib/1.2.3 
> Host: localhost 
> Accept: */* 
> Content-Length: 24 
> Expect: 100-continue 
> 
< HTTP/1.1 100 Continue 
< HTTP/1.1 415 Unsupported Media Type 
< Connection: close 
< Content-Type: text/xml 
< Content-Length: 289 
< 
+0

是不是你需要'HTTP/1.1 100 Continue'後的空白行? – YOU 2010-06-03 09:57:34

+1

有一個。它沒有被記錄的事實似乎是cURL的顯示問題。 – Stephane 2010-06-03 13:57:54

+0

只是爲了澄清,發回一個完全有效的HTTP響應('HTTP/1.1 100 Continue \ r \ n \ r \ n')不只是字符串HTTP HTTP 1.1繼續。 cURL客戶端將等待,直到它收到這兩個序列,如果它放棄,它將輸出(以詳細模式)消息「完成等待100-繼續」。 – bishop 2016-06-02 17:59:23

回答

9

如果您使用的libcurl編寫你的客戶端程序,請確保您的CURLOPT_FAILONERROR選項設置爲1。例如,在C,你會做這樣的事情:

curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L); 

按照libcurl的documentation,此選項 「講述了庫失敗默默如果HTTP返回代碼等於或大於400大」

此外,文檔中明確指出「默認操作是正常返回頁面,忽略該代碼。」

如果您使用的是curl命令行工具,只需在您的curl命令中添加-f--fail即可導致與上述類似的行爲。這也在捲曲man page中描述。

注意,這兩種方法都沒有安全保障,如在文檔中明確提出:

"This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407)."

+0

我正在使用命令行工具,但-f標誌似乎不影響工具的行爲方式。自從我編寫自己的客戶端以來,我已經解決了這個問題,能夠正確處理這些失敗的上傳。感謝您的答案,但 – Stephane 2011-11-09 11:18:22

6

其實應該有真正的頭後100繼續頭

所以,我通常不喜歡這樣的客戶端。

$contents=curl_exec($ch); 

list($header, $contents) = explode("\r\n\r\n", $contents , 2); 
if(strpos($header," 100 Continue")!==false){ 
    list($header, $contents) = explode("\r\n\r\n", $contents , 2); 
} 
+0

好吧,我在代碼100回答後發送了一個真正的標題。雖然,cURL似乎並不在乎。 – Stephane 2010-06-03 09:46:04

3

嘗試後100繼續線(見RFC 2616, Section 6)添加一個空行(CRLF),

+0

它似乎缺少的線是一個錯誤。我已經檢查了代碼,在「100 continue」之後有一個空行 – Stephane 2010-06-03 13:56:54

19

我知道這是舊的,但這裏是我的「100繼續」

理解你的服務器應該根據客戶端的頭單獨驗證請求,即如果請求無效,不要發送「100繼續」,而是實際的http錯誤,而不是403.這應該防止客戶發佈我理解的是到服務器的全部往返點(即客戶端等待「100繼續」)的數據。

如果您正在驗證實際發佈的數據,那麼您需要在此處應用更高級別的協議,即發送包裝在有效HTTP響應內容中的錯誤。是的,這似乎是限制,我不假定它的協議限制;更可能是客戶混淆不得不多次處理服務器響應。

+3

感謝您的答案。你是對的:這是一個古老的問題,但你得到它非常正確。我真正的問題是,「100」不是成功的錯誤代碼:客戶端應該總是檢查實際響應中包含的返回碼。顯然,這不是cURL正在做的事情。 – Stephane 2012-01-17 14:24:51

+0

「這應該阻止客戶發佈數據」 - 這可能是RFC中最被誤解的部分。缺少100-繼續不會阻止客戶端繼續,RFC明確指出客戶端可能會繼續發送請求主體。實際上,處理回覆的唯一有效方式是發送主體或斷開連接。 – 2015-09-07 13:37:49

+0

如果有人對curl郵件列表感興趣,可以通過curl/web服務器解釋這種誤解的其他有用的背景:[有關POST和PUT的詳細信息,請參見100-繼續](https://curl.haxx.se/mail/lib-2004- 08/0002.html) – paperclip 2016-05-03 16:24:04

4

闡述你的答案,並仍然使用PHP作爲一個例子:

這可能是多個100 Continue頭可以被接受。我用下面慢慢通過接口兼容,並刪除每個100 Continue反應,如果他們存在:

<?php 
// a little setup first 
$ch = curl_init(); 
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
curl_setopt($ch,CURLOPT_HEADER,1); 
// etc... 
$str = curl_exec($ch); 

// the goods 
$delimiter = "\r\n\r\n"; // HTTP header delimiter 
// check if the 100 Continue header exists 
while (preg_match('#^HTTP/[0-9\\.]+\s+100\s+Continue#i',$str)) { 
    $tmp = explode($delimiter,$str,2); // grab the 100 Continue header 
    $str = $tmp[1]; // update the response, purging the most recent 100 Continue header 
} // repeat 

// now we just have the normal header and the body 
$parts = explode($delimiter,$str,2); 
$header = $parts[0]; 
$body = $parts[1]; 
?> 
+0

它救了我,謝謝! – Aidin 2016-02-17 03:25:38