2010-08-10 103 views
6

我正在實現一種代理操作方法,該方法將傳入的Web請求轉發並轉發給另一個網頁,並添加一些標頭。操作方法爲GET請求工作文件,但我仍然努力轉發傳入的POST請求。複製Http請求InputStream

問題是我不知道如何正確地將請求正文寫入傳出的HTTP請求流。

這裏是我到目前爲止已經有一個縮短版:

//the incoming request stream 
var requestStream=HttpContext.Current.Request.InputStream; 
//the outgoing web request 
var webRequest = (HttpWebRequest)WebRequest.Create(url); 
... 

//copy incoming request body to outgoing request 
if (requestStream != null && requestStream.Length>0) 
      { 
       long length = requestStream.Length; 
       webRequest.ContentLength = length; 
       requestStream.CopyTo(webRequest.GetRequestStream())      
      } 

//THE NEXT LINE THROWS A ProtocolViolationException 
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse()) 
       { 
        ... 
       } 

當我打電話的GetResponse對即將離任的HTTP請求,我得到以下異常:

ProtocolViolationException: You must write ContentLength bytes to the request stream before calling [Begin]GetResponse. 

我不明白爲什麼會發生這種情況,因爲requestStream.CopyTo應該注意寫入正確的字節數。

任何建議,將不勝感激。

感謝,

阿德里安

+1

相關問題 - http://stackoverflow.com/questions/226784/how-to-create-a-simple-proxy-in-c – 2010-08-10 09:55:17

+0

@詹姆斯曼寧:感謝您的鏈接,但我已經過去了。我的代理適用於各種GET請求。這只是POST請求正文仍然給我的問題。 – 2010-08-10 10:19:54

+0

在繼續調用webRequest.GetResponse()之前,您是否嘗試過在webRequest.GetRequestStream()返回的流上調用Stream.Flush()? – 2010-08-10 11:41:36

回答

13

修改塊內if語句

long length = requestStream.Length; 
webRequest.ContentLength = length; 
requestStream.CopyTo(webRequest.GetRequestStream()) 

是,.NET是對此非常挑剔。解決問題的方法是同時刷新關閉該流。換句話說:

Stream webStream = null; 

try 
{ 
    //copy incoming request body to outgoing request 
    if (requestStream != null && requestStream.Length>0) 
    { 
     long length = requestStream.Length; 
     webRequest.ContentLength = length; 
     webStream = webRequest.GetRequestStream(); 
     requestStream.CopyTo(webStream); 
    } 
} 
finally 
{ 
    if (null != webStream) 
    { 
     webStream.Flush(); 
     webStream.Close(); // might need additional exception handling here 
    } 
} 

// No more ProtocolViolationException! 
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse()) 
{ 
    ... 
} 
+0

偉大的職位布賴恩。奇蹟般有效。但是,似乎.CopyTo()只支持.NET 4.0+ – Sage 2011-10-26 14:25:26

+0

謝謝。這解決了我的問題。一個問題:是否有理由在finally塊中使用Flush和Close,而不是將webStream封裝在使用塊中?是否有關於webRequest的副作用? – David 2012-07-06 03:40:28

+0

我敢肯定,刷新不會改變任何東西...... GetRequestStream返回一個ConnectStream的實例,這個類用一個空方法覆蓋Flush,所以調用Flush對它沒有任何影響。 – 2014-01-24 11:13:05

1

嘗試

webRequest.Method = "POST"; 
webRequest.ContentLength = requestStream.Length; 
webRequest.ContentType = "application/x-www-form-urlencoded"; 
Stream stream = webRequest.GetRequestStream(); 
requestStream.CopyTo(stream); 
stream.Close(); 
+0

我已經知道了(它在...部分)。正如我所說,這只是縮短版本。其他的東西雖然工作正常,所以我不認爲它與這個問題有關。 – 2010-08-10 10:18:06

2

答案@布賴恩的作品,但是,我發現,一旦requestStream.CopyTo(流)被調用,它會火了我的HttpWebResponse。這是一個問題,因爲我還沒有準備好發送請求。因此,如果任何人遇到沒有發送所有請求標題或其他數據的問題,那是因爲CopyTo正在觸發您的請求。