2009-08-25 41 views
1

我們正在建立在C#中爲我們的應用程序,它存在於使用IIS7來承載我們的應用程序HTTP之上的綜合集成測試框架。模擬不正確的Content-Length頭的HTTP在C#

作爲我們集成測試的一部分,我們希望測試傳入的請求,這將導致EndOfStreamExceptions(「無法讀取超出流末端」),當客戶端發送HTTP標頭時,會發出一個HTTP標頭,作爲機構的一部分進行傳播。我們想測試這種情況下的錯誤恢復代碼,所以我們需要模擬這些請求。

我正在尋找一個.NET基於Fx的套接字庫或自定義的HttpWebRequest替換,它特別允許開發人員模擬這些條件以添加到我們的集成測試套件中。有誰知道任何這樣的圖書館?一個腳本化的解決方案也可以。

回答

4

在調用GetRequestStream(或BeginGetRequestStream)之前設置ContentLength屬性,然後將較少的字節寫入該流。如果您在獲取請求流後嘗試設置它,ContentLength將拋出。如果你沒有設置ContentLength,HttpWebRequest將緩衝頭部,直到流被關閉,以便它可以適當地設置ContentLength(或者,你可以使用SendChunked,但這對你不適用)。如果您希望對此進行最大限度的控制,請手動創建一個malormed請求或兩個請求,然後打開一個套接字到服務器上的端口80,並將請求寫入TCP流,然後讀取響應並檢查連接以查看它是否已關閉。

但是:我不認爲這個測試是一個好主意。問題如下:

客戶端向服務器發送請求。它聲稱內容將是100字節。然後它發送90個字節,然後停止發送,並保持連接打開。服務器讀取90個字節,然後等待剩下的時間,因爲客戶端說要發送100個字節。現在,客戶端發送第二個請求。服務器將如何處理新請求的前10個字節?

答案是,服務器會假定這些字節是前一個請求的一部分,並將它們視爲這樣,然後在啓動後10個字節開始讀取「新」請求,這顯然會導致格式錯誤的標題。服務器不會那樣,所以它會發送一個4xx錯誤,然後關閉連接。它關閉連接的原因是因爲它現在無法知道發送給它的數據是什麼意思,也無法恢復。另外,連接的關閉不會很優美,會突然發生,另一端提交第二個請求的HttpWebRequest(如果他們排隊等待,則排在第三或第四個請求)會拋出一個WebException,表示基礎連接已關閉,並讓您猜測原因。

這種情況導致連接被Expect 100-continue頭關閉,並且服務器返回100-繼續,然後是4xx,例如需要Auth時。即使它拒絕了請求,它仍然必須假定下一個字節是同一個請求的一部分,因爲它已經承諾通過發送100-continue來接收這些字節。如果它不服務該請求,或者客戶端想要取消請求並提交一個新請求(推測使用auth憑證),那麼它必須關閉連接並打開一個新連接。

最後,使用TCP測試網絡流中的EndOfStreamException對我來說根本沒有任何意義。 TCP不標記流的「結束」,它只是在寫入套接字時才發送數據。沒有「EOF」,沒有辦法檢測數據是否全部被傳輸,除非你知道需要多少數據。除非連接被關閉,否則TCP並不真正擁有「結束」,在這種情況下,根據您正在操作的堆棧中的哪個位置,您將得到一個WebException或一個SocketException。在協議中的任何傳輸錯誤都在winsock中處理。如果沒有更多的數據發送,連接的一端最終會向另一端發送一個保持連接,以確保連接實際上仍然打開,並且一臺主機不會丟棄它。如果Keepalive超時,連接將被關閉,並且您下次嘗試從中讀取時可能會收到WebException。鑑於所有這些工作如何,我只是不明白你將如何從這個測試中獲得任何價值。只需發送格式錯誤的請求並確保相應地處理錯誤,並將適當的4xx消息發送回客戶端並正確關閉連接即可。

0

我不知道任何這樣的庫,但在我看來,這將是對接收方非常簡單,如果這是你在哪裏編碼。

簡單地檢索整個的WebRequest,截斷儘可能多或儘可能少,只要你想,然後轉發給他人。您可能需要在此過程中創建WebRequest的新副本,而不是在原地截斷,但它應該仍然很簡單。

+0

我們的集成測試模擬客戶端。我們無法對接收方進行任何更改以方便測試。 – cfeduke 2009-08-25 16:35:31

0

您不能只將客戶端上的HttpWebRequest.ContentLength屬性設置爲比數據的實際大小更小或更大的值嗎?

0

如果你想模擬任何這樣的事情,你違反了HTTP協議,那麼你將不得不編寫自己的代碼來做到這一點。 HttpWebRequest不允許你做這樣的事情。

相關問題