我知道你们都会回答“使用像 Fiddler 这样的调试代理服务器”,但这并不是那么简单。
这是我的情况:我有一些代码在服务器上运行,在 ASP.NET 页面代码隐藏 (aspx.cs) 中,它(除其他外)建立与另一台服务器的连接,获取一些内容,然后对其进行格式化并将其返回给浏览器。
问题是另一台服务器做错了,所以我希望能够将调试标志传递到页面中(通过查询字符串,例如?debug=true),以便打印出完全原始的 HTTP请求它发送到另一台服务器,这样我就可以看到到底出了什么问题。这段代码在几个地方运行,所以我希望能够在开发、登台或生产上传递这个标志并只看到请求,而不必弄清楚生产服务器是否可以与某个存在于某处的代理服务器通信, ETC。
你会认为这样做很容易,对吧?所以我觉得我疯了之类的,但我查看了 HttpWebRequest 及其父类 WebRequest 的参考资料,但什么也没有。没办法。你会认为微软会想到这一点。最接近的是您可以访问“标题”集合,但是当我尝试它时,它省略了一些非常重要的标题,例如“内容长度” - 所以它一定是对我“撒谎”(我知道它在撒谎,因为我知道对于远程服务器返回 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();
我意识到这是一个老问题。 @feroze's answer 说明了要做什么,但没有详细说明如何设置 System.Net
跟踪来实现它。
由于这个问题是我对该主题的查询的第一个谷歌结果,而且我们都是忙碌的人,我想我会让你们不必去寻找这些信息。
System.Web
对于调试 HttpWebRequest
非常强大,可以使用 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 中以调试模式运行,调试控制台中将显示以下信息:
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 x.x.x.x:xx to x.x.x.x: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 服务客户端错误的原因时特别有用。原来我错过了一个标题。
您可以使用 System.Net 跟踪机制来查看网络上发送的原始 HTTP 请求。您还可以将自己的跟踪侦听器添加到进程中。
您可以使用像 wireshark 这样的网络流量嗅探器。
这不是调试代理,但会嗅探所有流量并让您查看原始请求/响应。
localhost
流量。而是使用名为 RawCap 的工具将 localhost 流量捕获到文件,然后使用 Wireshark 对其进行分析。
在这里回答我自己的问题,因为我想到了另一种方法。基本上这个想法是——你将 HttpWebRequest 重新指向一个记录传入的原始 HTTP 请求的页面。换句话说,根据此论坛帖子设置自定义 HTTP 处理程序:
http://forums.asp.net/t/353955.aspx
然后只更改 HttpWebRequest 中的 URL 以指向这个新端点,但保持请求的所有其他元素相同。将结果写入文件或其他东西,你就可以了。
我知道这是一个老问题,但我处于无法控制应用程序配置文件的困境中,因此我需要一种简单的方法来通过代码启用跟踪,然后轻松访问原始请求/响应数据事件。所以我把这个自定义类 HttpRawTraceListener 放在一起,它可能对我所在位置的其他人有用:
https://github.com/jhilgeman/HttpRawTraceListener/blob/master/HttpRawTraceListener.cs
它的设计就像将文件添加到项目中一样简单,然后调用:
System.Diagnostics.HttpRawTraceListener.Initialize();
...开始跟踪。从那里,请求/响应将从跟踪消息中解析出来,然后通过 System.Diagnostics.HttpRawTraceListener.FinishedCommunication 事件提供。
它可能不是 100% 适合所有场景(例如,它不是代理,因此它不会捕获来自浏览器的 Web 请求),但它可以很好地捕获对 Web 服务的 HttpWebRequests 请求/响应,并且它可能如果您需要这样的东西,这是一个很好的起点。
initialized()
HttpRawTraceListener
并设置了 FinishedCommunication
但是当我执行 HttpClient().PostAsync()
时没有捕获任何内容:/ 我正在使用 .net framework 4.6.1
我建议您下载 Telerik Fiddler 以捕获传入/传出流量。
这里是一个简单的例子,如何通过该工具来做到这一点:
确保捕获流量已启用:打开浏览器并刷新页面,或者只是通过 HTTP 客户端发送请求。切换到 Fiddler 后,您应该会看到您的请求:在顶部尝试导航“Raw”选项卡。在下面的窗口中是您的原始请求
另一个建议。 Implement your own web proxy,并将您的请求设置为与 WebRequest.Proxy 一起使用。然后您应该能够从代理实例中提取流量。
编辑:更新链接。
您说您认为 .NET 对您撒谎,而您给出的具体示例是 HTTP 响应中缺少标头 Content-Length
。
但是 HTTP 响应不需要标头 Content-Length
。事实上,如果响应的主体是动态的,并且如果事先不知道它的长度,那么 Content-Length
标头很可能会被省略!
Content-Length
在许多情况下都不能给出,包括在使用分块传输编码时。目标服务器是否支持 HTTP/1.1?
不定期副业成功案例分享
<add name="MyTraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="System.Net.trace.log" traceOutputOptions="DateTime" />