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

发布于 2024-09-25 18:51:52 字数 942 浏览 8 评论 0 原文

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

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

问题是其他服务器正在做错误的事情,所以我希望能够将调试标志传递到页面中(通过查询字符串,例如?debug=true),以便它打印出 它发送到其他服务器的完全原始的 HTTP 请求,这样我就可以看到到底出了什么问题。该代码在多个地方运行,因此我希望能够在开发、登台或生产中传递此标志并仅查看请求,而不必弄清楚生产服务器是否可以与某处存在的某些代理服务器通信等等。

你会认为这很容易做到,对吧?所以我觉得我疯了或者什么的,但我查看了 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();

I know you are all going to answer "use a debugging proxy server like Fiddler" but it's not that simple.

Here's my situation: I have some code that runs on a server, in an ASP.NET page code-behind (aspx.cs), which (among other things) establishes a connection to another server, grabs some stuff, and then formats it and returns it to the browser.

The problem is that the other server is doing the wrong thing, and so I want to be able to pass a debugging flag into the page (via the query string, e.g. ?debug=true) so that it will print out the completely raw HTTP request that it is sending to the other server so I can see what the heck is wrong. This code is running in several places so I want to be able to just pass in this flag on dev, staging, or production and just see the request, without having to figure out whether the production servers can talk to some proxy server that exists somewhere, etc.

You would think that it would be easy to do this, right? So I feel like I'm crazy or something but I looked at the reference for HttpWebRequest and its parent class WebRequest and -- nothing. No can do. You would think Microsoft would have thought of this. The closest thing is that you can access the "Headers" collection but when I tried it, it omitted some really important headers like "content length" -- so it must be "lying" to me (I know it's lying, because I know for a fact that the remote server is returning a 200 status -- the request is successful, it's just returning bad/different/wrong data)

Here is the asked-for code example:

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();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

两人的回忆 2024-10-02 18:51:53

我建议您下载 Telerik Fiddler 来捕获传入/传出流量。

这里是如何使用该工具执行此操作的简单示例:

  1. 确保已启用捕获流量:
    输入图片这里的描述
  2. 打开浏览器并刷新页面,或者只是通过 HTTP 客户端发送请求。
    输入图片此处的描述
  3. 切换到 Fiddler 后,您应该会看到您的请求:
    输入图片此处描述
  4. 在顶部尝试导航“Raw”选项卡。
    输入图片此处描述
  5. 在下面的窗口中是您的原始请求
    输入图片此处描述

I suggest you to download Telerik Fiddler to capture incoming/outcoming traffic.

Over here is simple example how to do it by that tool:

  1. Be sure that the Capture Traffic is enabled:
    enter image description here
  2. Open browser and refresh the page, or just send request via HTTP client.
    enter image description here
  3. After that switch to the Fiddler, you should see your request:
    enter image description here
  4. At the top try to navigate “Raw” tab.
    enter image description here
  5. In the below window is your raw request
    enter image description here
何以心动 2024-10-02 18:51:53

另一个建议。 实现您自己的网络代理,并设置您要使用的请求它与 WebRequest.Proxy。然后您应该能够从代理实例中提取流量。

编辑:更新链接。

Another suggestion. Implement your own web proxy, and set your request to use it with WebRequest.Proxy. Then you should be able to extract the traffic from the proxy instance.

Edit: update for links.

情独悲 2024-10-02 18:51:53

您说您认为 .NET 在对您撒谎,您给出的具体示例是 HTTP 响应中缺少 Content-Length 标头。

但 HTTP 响应中不需要标头 Content-Length。事实上,如果响应正文是动态的,并且事先不知道其长度,那么 Content-Length 标头很可能会被省略!

You say that you think .NET is lying to you, and the specific example you give is that the header Content-Length is missing from the HTTP response.

But the header Content-Length is not required from an HTTP response. In fact, if the body of the response is in any dynamic, and if its length is not known in advance, then it is highly likely that the Content-Length header will be omitted!

触ぅ动初心 2024-10-02 18:51:53

该答复不包含请求内容。 (但如果您需要诊断连接问题,它仍然可能有帮助)。

.NET Core 中 System.Net 代码的跟踪日志记录可以通过创建一个继承自 System.Diagnostics.Tracing.EventListener 的类来捕获,

请参阅 https://github.com/dotnet/runtime/issues/64977 了解详细信息+原始建议。

示例:

private class SystemNetEventListener : EventListener
{
  protected override void OnEventSourceCreated(EventSource eventSource)
  {
    // take anything from System.Net
    if (eventSource.Name?.StartsWith("Private.InternalDiagnostics.System.Net.") == true)
    {
      EnableEvents(eventSource, EventLevel.LogAlways);
    }
  }

  protected override void OnEventWritten(EventWrittenEventArgs eventData)
  {
    try
    {
      // produce a string that can be logged
      var sb = new StringBuilder().Append($"{eventData.TimeStamp:HH:mm:ss.fffffff}[{eventData.EventName}] ");
      for (int i = 0; i < eventData.Payload?.Count; i++)
      {
        if (i > 0)
          sb.Append(", ");
        sb.Append(eventData.PayloadNames?[i]).Append(": ").Append(eventData.Payload[i]);
      }

      Console.WriteLine(sb.ToString().Trim());
    }
    catch
    {
      // on failure... well... we are the logger, so there's nobody to tell we failed
    }
  }
}

用法:

var listener = new SystemNetEventListener(); // start logging
... // do HTTP/Websocket stuff
listener.Dispose(); // stop logging

This answer does not include the request content. (But it still may help if you need to diagnose connection issues).

Trace logging of the System.Net code in .NET Core can be captured by making a class that inherits from System.Diagnostics.Tracing.EventListener

See https://github.com/dotnet/runtime/issues/64977 for details + original suggestion.

Example:

private class SystemNetEventListener : EventListener
{
  protected override void OnEventSourceCreated(EventSource eventSource)
  {
    // take anything from System.Net
    if (eventSource.Name?.StartsWith("Private.InternalDiagnostics.System.Net.") == true)
    {
      EnableEvents(eventSource, EventLevel.LogAlways);
    }
  }

  protected override void OnEventWritten(EventWrittenEventArgs eventData)
  {
    try
    {
      // produce a string that can be logged
      var sb = new StringBuilder().Append(
quot;{eventData.TimeStamp:HH:mm:ss.fffffff}[{eventData.EventName}] ");
      for (int i = 0; i < eventData.Payload?.Count; i++)
      {
        if (i > 0)
          sb.Append(", ");
        sb.Append(eventData.PayloadNames?[i]).Append(": ").Append(eventData.Payload[i]);
      }

      Console.WriteLine(sb.ToString().Trim());
    }
    catch
    {
      // on failure... well... we are the logger, so there's nobody to tell we failed
    }
  }
}

Usage:

var listener = new SystemNetEventListener(); // start logging
... // do HTTP/Websocket stuff
listener.Dispose(); // stop logging
遮云壑 2024-10-02 18:51:52

我意识到这是一个老问题。 @feroze 的回答说明了要做什么,但没有详细说明如何设置 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 服务客户端错误的原因时特别有用。原来我缺少一个标题。

I realise that this is an old question. @feroze's answer says what to do, but does not go into any detail on how to set up System.Net tracing to achieve it.

As this question was the first Google result for my query into the subject, and as we are all busy people, I thought I would save you all from having to hunt down this information.

System.Web is very powerful for debugging HttpWebRequests and can be easily set up using the 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>

Adding a simple HttpWebRequest in your code, and running in debugging mode in Visual Studio, the following information will be displayed in the debug console:

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

I found this especially useful when trying to find out the cause of a webservice client error. It turned out I was missing a header.

笔芯 2024-10-02 18:51:52

您可以使用 System.Net 跟踪机制来查看在线发送的原始 HTTP 请求。您还可以将自己的跟踪侦听器添加到进程中。

You can use System.Net tracing mechanism to see the raw HTTP requests sent on the wire. You can also add your own tracelistener to the process.

姜生凉生 2024-10-02 18:51:52

您可以使用网络流量嗅探器,例如 wireshark

这不是调试代理,但会嗅探所有流量并让您查看原始请求/响应。

You can use a network traffic sniffer like wireshark.

This is not a debugging proxy, but will sniff all traffic and let you see the raw requests/responses.

挥剑断情 2024-10-02 18:51:52

在这里回答我自己的问题,因为我想到了另一种方法。基本上这个想法是——将 HttpWebRequest 重新指向记录传入原始 HTTP 请求的页面。换句话说,按照此论坛帖子设置自定义 HTTP 处理程序:

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

然后仅更改 HttpWebRequest 中的 URL 以指向此新端点,但保持请求的所有其他元素相同。将结果写入文件或其他东西,你就成功了。

answering my own question here, because I thought of another way to do it. Basically the idea is -- you re-point the HttpWebRequest to a page that logs the incoming raw HTTP Request. In other words set up a custom HTTP handler as per this forum post:

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

And then change just the URL in the HttpWebRequest to point to this new endpoint, but keep all other elements of the request the same. Write the result to a file or something and you're golden.

隐诗 2024-10-02 18:51:52

我知道这是一个老问题,但我陷入了困境,我无法控制应用程序配置文件,因此我需要一种简单的方法来通过代码启用跟踪,然后轻松访问原始请求/响应数据事件。因此,我将这个自定义类 HttpRawTraceListener 放在一起,它可能对处于我位置的其他人有用:

https://github.com/jhilgeman/HttpRawTraceListener/blob/master/HttpRawTraceListener.cs

它的设计就像将文件添加到项目中一样简单,然后调用:

System.Diagnostics.HttpRawTraceListener.Initialize();

...开始跟踪。从那里,请求/响应将从跟踪消息中解析出来,然后通过 System.Diagnostics.HttpRawTraceListener.FinishedCommunication 事件提供。

它可能不是 100% 适合所有场景(例如,它不是代理,因此它不会捕获来自浏览器的 Web 请求),但它对于捕获对 Web 服务的 HttpWebRequests 请求/响应非常有效,并且它可能如果您需要这样的东西,这是一个很好的起点。

I know this is an old question, but I was in a tough spot where I didn't control the application config file, so I needed an easy way to enable the tracing via code and then easily access the raw request/response data in an event. So I put together this custom class, HttpRawTraceListener, which might be of use to others that are in my position:

https://github.com/jhilgeman/HttpRawTraceListener/blob/master/HttpRawTraceListener.cs

It was designed to be as simple as adding the file to your project, then calling:

System.Diagnostics.HttpRawTraceListener.Initialize();

...to start the trace. From there, requests/responses will be parsed out of the trace messages and then be made available via the System.Diagnostics.HttpRawTraceListener.FinishedCommunication event.

It's probably not 100% perfect for every scenario (e.g. it's not a proxy, so it won't capture web requests from a browser, for example), but it works pretty well for capturing HttpWebRequests requests/responses to web services, and it might be a good starting point if you need something like this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文