【问题标题】:View Raw Headers that will be sent/received in HttpResponseMessage / HttpRequestMessage (System.Net.Http, WebAPI)查看将在 HttpResponseMessage / HttpRequestMessage (System.Net.Http, WebAPI) 中发送/接收的原始标头
【发布时间】:2012-08-16 06:02:07
【问题描述】:

直观地查看将在 WebAPI 的 HttpResponseMessage / HttpRequestMessage 类型中实际发送或接收的 Http 标头的原始列表非常有益。我的意思是一个普通的旧字符串,每个标题都在一个新行上,正是生成或接收的内容。

但不幸的是,看起来这些类型中的任何一种都不允许您查看实际生成的内容。取而代之的是,到处都是属性。一些在原始 HttpResponseMessage / HttpRequestMessage 类型本身中,一些在 response/request.Content.Headers 中(两者不重复,后者用于尚未作为属性涵盖的那些,通常用于自定义标头),......也许还有 Cookie某处获得了自己的标题。并且在视觉上看到这些 Header 集合列表也是一种痛苦,即你最终会为每个这样的集合生成一堆迭代代码......更多的混乱。

但是在实际发送/接收的响应/请求中,并没有这样的划分,简单的看到所有的Http headers。 所以我在某个地方错过了它吗?在其中的某个地方实际上是否有一个简单直观的属性可以简单地返回原始标头字符串?当然响应已经收到标头并刚刚解析它们......该原始字符串是否隐藏在某个地方?

(顺便说一句,我知道 Fiddler ......这完全不能令人满意。如果我必须处理 Http 标头的低级混乱,那么能够使用我的编程类型查看它们是很有意义的用于生成和接收它们。但更糟糕的是,我仍然无法让 localhost 与 Fiddler 一起工作(在 Win8 上),这使得它在许多调试场景中的使用无效,在这些场景中,我只想看到臭名昭著的标题生成。)

【问题讨论】:

  • 我也有同样的问题。似乎没有 HttpRequestMessage.Raw 属性或类似的东西。我想我必须重新创建给定 HeadersContent 属性的原始响应。
  • 你有没有得到这个?我已经设法使用在GlobalConfiguration 中注册的自定义消息处理程序获得了原始请求和响应的相似之处,但是在响应中,标头仅包含由 Web API 设置的标头,任何由 IIS 添加的都不存在。我只是希望他们能在某处提供 RAW 请求和响应属性,而不是将其隐藏在抽象层中!
  • “我只是希望他们能在某个地方提供一个 RAW 请求和响应属性,而不是将其隐藏在抽象层中!” - 太真实了!

标签: c# asp.net-web-api http-headers dotnet-httpclient


【解决方案1】:

我没有找到获取请求标头的 raw 值的方法,但是这段代码似乎返回了所有标头值(不是按原始顺序):

request.Headers.ToString() + request.Content.Headers.ToString()

【讨论】:

    【解决方案2】:

    似乎 HttpRequestMessage.ToString 确实返回了原始值(好吧,从技术上讲,它们不是原始值,但非常接近一个,因为它一直在使用解析器分隔符将它们连接回来)。不幸的是,用于构造 ToString 结果的方法是私有的。因此,要解决相同的任务,我必须解析 ToString 的结果:

    var values = new JObject();
    
    foreach (var raw_header in request.Headers
                                       .ToString()
                                       .Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries))
    {
        var index = raw_header.IndexOf(':');
        if (index <= 0)
            continue;
    
        var key = raw_header.Substring(0, index);
        var value = index + 1 >= raw_header.Length ? string.Empty : raw_header.Substring(index + 1).TrimStart(' ');
    
        values.Add(new JProperty(key, value));
    }
    

    【讨论】:

      【解决方案3】:

      这是我用来捕获请求和响应标头的代码:

      *这是从 Windows 窗体应用程序中获取的:txtReceived 和 txtSent 是 WindowsForms 窗体上的简单多行文本框。光标是窗体的光标。 *

          private HttpClient PrepareHttpClient()
          {
              var client = new HttpClient();
      
              client.DefaultRequestHeaders.Accept.Add(
                  new MediaTypeWithQualityHeaderValue("application/xml"));
      
              return client;
          }
      
          private string SendGetRequest(string url)
          {
              //Please be patient ...
              this.Cursor = Cursors.WaitCursor;
      
              var client = PrepareHttpClient();
              txtSent.Text = url;
              var taskReult = client.GetAsync(new Uri(url));
              HttpResponseMessage httpResponse = taskReult.Result;
      
              Stream st = httpResponse.Content.ReadAsStreamAsync().Result;
              StreamReader reader = new StreamReader(st);
              string content = reader.ReadToEnd();
      
              //Reset the cursor shape
              this.Cursor = Cursors.Default;
      
              txtReceived.Text = FormatResponse(httpResponse, content);
      
              //For GET we expect a response of 200 OK
              if (httpResponse.StatusCode == HttpStatusCode.OK)
              {
                  return content;
              }
      
              throw new ApplicationException(content);
          }
          /// <summary>
          /// Post to the server using JSON
          /// </summary>
          /// <typeparam name="T"></typeparam>
          /// <param name="url">The server uri</param>
          /// <param name="e">The object to POST</param>
          /// <returns></returns>
          private string SendPostRequest<T>(string url, T e)
          {
              this.Cursor = Cursors.WaitCursor;
              HttpClient client = new HttpClient();
      
              // Create the JSON formatter.
              MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
      
              // Use the JSON formatter to create the content of the request body.
              HttpContent content = new ObjectContent<T>(e, jsonFormatter);
              Stream st = content.ReadAsStreamAsync().Result;
              StreamReader reader = new StreamReader(st);
              string s = reader.ReadToEnd();
      
      
              // Send the request.
              var taskResult = client.PostAsync(url, content);
      
              //Note: We could simply perform the following line and save some time
              //but then we will not have access to the post content:
              //var taskResult = client.PostAsJsonAsync<T>(url, e);
      
              HttpResponseMessage httpResponse = taskResult.Result;
              this.Cursor = Cursors.Default;
      
              txtSent.Text = FormatRequest(httpResponse.RequestMessage, s);
      
              st = httpResponse.Content.ReadAsStreamAsync().Result;
              reader = new StreamReader(st);
              string responseContent = reader.ReadToEnd();
              txtReceived.Text = FormatResponse(httpResponse, responseContent);
      
              //For POST we expect a response of 201 Created
              if (httpResponse.StatusCode == HttpStatusCode.Created)
              {
                  return responseContent;
              }
      
              throw new ApplicationException(responseContent);
          }
      
          /// <summary>
          /// PUT to the server using JSON
          /// </summary>
          /// <typeparam name="T"></typeparam>
          /// <param name="url"></param>
          /// <param name="e"></param>
          /// <returns></returns>
          private string SendPutRequest<T>(string url, T e)
          {
              this.Cursor = Cursors.WaitCursor;
              HttpClient client = new HttpClient();
      
              // Create the JSON formatter.
              MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
      
              // Use the JSON formatter to create the content of the request body.
              HttpContent content = new ObjectContent<T>(e, jsonFormatter);
              Stream st = content.ReadAsStreamAsync().Result;
              StreamReader reader = new StreamReader(st);
              string s = reader.ReadToEnd();
      
              // Send the request.
              var taskResult = client.PutAsync(url, content);
      
              //Note: We could simply perform the following line and save some time
              //but then we will not have access to the post content:
              //var taskResult = client.PutAsJsonAsync<T>(url, e);
      
              HttpResponseMessage httpResponse = taskResult.Result;
      
              txtSent.Text = FormatRequest(httpResponse.RequestMessage, s);
      
              st = httpResponse.Content.ReadAsStreamAsync().Result;
              reader = new StreamReader(st);
              string responseContent = reader.ReadToEnd();
              this.Cursor = Cursors.Default;
              txtReceived.Text = FormatResponse(httpResponse, responseContent);
      
              //For PUT we expect a response of 200 OK
              if (httpResponse.StatusCode == HttpStatusCode.OK)
              {
                  return responseContent;
              }
      
              throw new ApplicationException(responseContent);
          }
      
          private string FormatRequest(HttpRequestMessage request, string content)
          {
              return
                  string.Format("{0} {1} HTTP/{2}\r\n{3}\r\n{4}",
                      request.Method,
                      request.RequestUri,
                      request.Version,
                      request.Headers,
                      content);
          }
      
          private string FormatResponse(HttpResponseMessage result, string content)
          {
              return
                  string.Format("HTTP/{0} {1} {2}\r\n{3}\r\n{4}",
                      result.Version,
                      (int)result.StatusCode,
                      result.ReasonPhrase,
                      result.Headers,
                      content);
          }
      

      【讨论】:

      • 谢谢 Dror,但很抱歉,大部分代码不需要发布,与问题完全无关。我也无法找出一个与响应字符串相似的实际答案。
      • 我目前使用的是一种 REBUILDING 响应字符串的方式,试图让它看起来尽可能像你期望的那样找到原件。我最终可能会发布该解决方案,这是检查每个可能的标头变量的大量冗长方法。这完全是荒谬的。一个简单的基于文本的字符串进来了,我呼吁团队请给我们一种方法来获取那个纯字符串。在我们所有的开发人员工作中看到它就大有帮助。
      猜你喜欢
      • 2021-12-24
      • 1970-01-01
      • 2014-09-18
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 2018-04-24
      • 2023-03-17
      • 2016-11-24
      相关资源
      最近更新 更多