如何查看HttpWebRequest类发送的原始HTTP请求?

我知道你们都会回答“使用像Fiddler这样的debugging代理服务器”,但事情并不那么简单。

这是我的情况:我有一些运行在服务器上的代码,在一个ASP.NET页面代码隐藏(aspx.cs)中,(除其他外)build立到另一个服务器的连接,抓取一些东西,然后格式化并将其返回给浏览器。

问题是另一个服务器做错了事情,所以我想能够传递一个debugging标志到页面(通过查询string,例如?debug = true),以便它将打印出完全原始的 HTTP请求它发送到其他服务器,以便我可以看到什么是错误的。 这个代码运行在几个地方,所以我希望能够在dev,staging或者production中传递这个标记,而不必去查看生产服务器是否可以和某个代理服务器通信等等

你会认为这样做很容易,对吧? 所以我觉得我疯了或什么东西,但我看了HttpWebRequest及其父类WebRequest的参考和 – 什么都没有。 没有可以做的。 你会认为微软会想到这一点。 最接近的是你可以访问“Headers”集合,但是当我尝试它时,它省略了一些非常重要的标题,比如“内容长度” – 所以它必须对我说谎(我知道这是谎言,因为我知道对于远程服务器返回200状态的事实 – 请求成功,它只是返回错误/不同/错误的数据)

这是要求的代码示例:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.whatever.com"); req.Method = ... whatever ...; ... other setup for the request ... /* At this point we are about to send the request. What does the raw HTTP request look like? */ HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); 

您可以使用System.Net跟踪机制来查看线路上发送的原始HTTP请求。 您也可以将您自己的tracelistener添加到stream程中。

我意识到这是一个老问题@feroze回答说要做到这一点,但没有详细介绍如何设置System.Net跟踪来实现这一点,因为这个问题是我的第一个谷歌search结果的主题,作为我们都是忙碌的人,我想我会救你们不必去追捕这些信息。

System.web对于debuggingHttpWebRequest非常强大,可以使用web.config轻松设置

 <configuration> <system.diagnostics> <trace autoflush="true" /> <sources> <source name="System.Net" maxdatasize="1024"> <listeners> <add name="MyTraceFile"/> <add name="MyConsole"/> </listeners> </source> </sources> <sharedListeners> <add name="MyTraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="System.Net.trace.log" /> <add name="MyConsole" type="System.Diagnostics.ConsoleTraceListener" /> </sharedListeners> <switches> <add name="System.Net" value="Verbose" /> </switches> </system.diagnostics> </configuration> 

在代码中使用简单的HttpWebRequest,并在Visual Studio中以debugging模式运行,以下信息将显示在debugging控制台中。

 System.Net Verbose: 0 : [6596] WebRequest::Create(https://example.com/service.asmx) System.Net Verbose: 0 : [6596] HttpWebRequest#62063506::HttpWebRequest(https://example.com/service.asmx#11234) System.Net Information: 0 : [6596] RAS supported: True System.Net Verbose: 0 : [6596] Exiting HttpWebRequest#11234::HttpWebRequest() System.Net Verbose: 0 : [6596] Exiting WebRequest::Create() -> HttpWebRequest#11234 System.Net Verbose: 0 : [6596] HttpWebRequest#11234 ::GetRequestStream() System.Net Verbose: 0 : [6596] ServicePoint#11234 ::ServicePoint(example.com:443) System.Net Information: 0 : [6596] Associating HttpWebRequest#11234with ServicePoint#11234 System.Net Information: 0 : [6596] Associating Connection#11234 with HttpWebRequest#11234 System.Net Information: 0 : [6596] Connection#11234 - Created connection from xxxx:xx to xxxx:xx. System.Net Information: 0 : [6596] TlsStream#11234 ::.ctor(host=example.com, #certs=0) System.Net Information: 0 : [6596] Associating HttpWebRequest#11234 with ConnectStream#11234 System.Net Verbose: 0 : [6596] Exiting HttpWebRequest#11234 ::GetRequestStream() -> ConnectStream#11234 System.Net Verbose: 0 : [6596] ConnectStream#7740977::Write() System.Net Verbose: 0 : [6596] Data from ConnectStream#11234::Write System.Net Verbose: 0 : [6596] 00000000 : 3C 73 6F 61 70 3A 45 6E-76 65 6C 6F 70 65 0D 0A : <soap:Envelope.. ...etc 

我发现这个特别有用,当试图找出web服务客户端错误的原因,事实certificate,我错过了一个头。

你可以使用像wireshark这样的networkingstream量嗅探器。

这不是一个debugging代理,但会嗅探所有stream量,并让您看到原始请求/响应。

在这里回答我自己的问题,因为我想到另一种方式去做。 基本上这个想法是 – 你把HttpWebRequest重新指向logging传入的原始HTTP请求的页面。 换句话说,根据此论坛post设置一个自定义的HTTP处理程序:

http://forums.asp.net/t/353955.aspx

然后改变HttpWebRequest中的URL来指向这个新的端点,但保持请求的所有其他元素相同。 把结果写到一个文件或者什么东西,你是金。

另一个build议。 实现自己的Web代理 ,并设置您的请求与WebRequest.Proxy使用它。 那么你应该能够从代理实例中提取stream量。

编辑:更新链接。

你说你认为.NET对你撒谎,你给的具体例子是HTTP响应中缺less头Content-Length

但是HTTP响应不需要头部Content-Length 。 事实上,如果响应的主体是dynamic的,并且如果它的长度是事先不知道的,那么很可能Content-Length标题将被省略!

我一定会错过一些东西,因为把原始的HTTP请求作为ASCII文本获取是非常简单的,只要你在Page_Init()中抓取它,它就会和Page_Load()不同。

 protected void Page_Init(object sender, EventArgs e) { //this gets the raw request as an ASCII String. byte[] biData = Request.BinaryRead(Request.TotalBytes); string sWholeRequestAsString = System.Text.Encoding.ASCII.GetString(biData); }