简体   繁体   English

查看将在 HttpResponseMessage / HttpRequestMessage (System.Net.Http, WebAPI) 中发送/接收的原始标头

[英]View Raw Headers that will be sent/received in HttpResponseMessage / HttpRequestMessage (System.Net.Http, WebAPI)

It can be extremely beneficial to visually see the raw list of Http Headers that will actually be sent or received in WebAPI's HttpResponseMessage / HttpRequestMessage types.直观地查看将在 WebAPI 的 HttpResponseMessage / HttpRequestMessage 类型中实际发送或接收的 Http 标头的原始列表非常有益。 I mean just a plain old string, with each header on a new line, exactly what is generated or received.我的意思是只是一个普通的旧字符串,每个标题都在一个新行上,正是生成或接收的内容。

But unfortunately, it does not look like either of these types allows you to just see what actually gets generated.但不幸的是,这两种类型中的任何一种都不能让您只看到实际生成的内容。 Instead, there are properties scattered everywhere.相反,到处都是散落的财产。 Some in the raw HttpResponseMessage / HttpRequestMessage types themselves, some in the response/request.Content.Headers (the two do not repeat, the latter is for ones not already covered as properties, typically for custom headers), ... and maybe Cookies somewhere gets a stash of its own headers.一些在原始 HttpResponseMessage / HttpRequestMessage 类型本身中,一些在 response/request.Content.Headers 中(两者不重复,后者用于尚未作为属性涵盖的那些,通常用于自定义标头),......也许还有 Cookies某处藏匿了自己的标题。 And visually getting to see those lists of Header collections is a pain as well, ie you end up with a bunch of iterating code for each such collection ... more mess.并且在视觉上看到这些 Header 集合的列表也很痛苦,也就是说,您最终会为每个这样的集合生成一堆迭代代码……更加混乱。

But in the actual response / request sent / received, there is no such division, and it is simple to see all Http headers.但是在实际的响应/请求发送/接收中,并没有这样的划分,简单的看到所有的Http headers。 So am I missing it somewhere?那我是不是在某个地方错过了它? Is there actually a simple and intuitive property somewhere in these that simply returns the raw headers string?实际上是否有一个简单直观的属性可以简单地返回原始标题字符串? Certainly the response already received the headers and just parsed them ... is that raw string hidden somewhere?当然,响应已经收到标题并只是解析它们......原始字符串是否隐藏在某处?

(BTW, I know about Fiddler... and that is entirely unsatisfactory. If I am having to deal with low-level messing of Http headers, then it makes good sense to be able to view them with the programmatic type I am using to generate and receive them with. But worse off, I still can't get localhost to work with Fiddler (on Win8), which invalidates its use for many debugging scenarios where all I want to do is see the stinking headers that will be generated.) (顺便说一句,我知道 Fiddler ......这完全不令人满意。如果我不得不处理 Http 标头的低级混乱,那么能够使用我正在使用的编程类型查看它们是很有意义的生成并接收它们。但更糟糕的是,我仍然无法让 localhost 与 Fiddler 一起工作(在 Win8 上),这使其在许多调试场景中的使用无效,在这些场景中,我只想看到将生成的臭头。 )

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

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

It seems that HttpRequestMessage.ToString does returns raw values (well, techincally they are not original, but very close to one since it's been using parsers delimeters to join them back).似乎 HttpRequestMessage.ToString 确实返回原始值(好吧,从技术上讲,它们不是原始值,但非常接近于原始值,因为它一直在使用解析器分隔符将它们连接回来)。 Unfortunately methods that's been used to construct result of ToString are private.不幸的是,用于构造 ToString 结果的方法是私有的。 So to resolve the same task I had to parse the result of 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));
}

Here is the code I use in order to be able to catch the Request and Response headers:这是我为了能够捕获请求和响应标头而使用的代码:

*This is taken from a Windows Forms app so: txtReceived and txtSent are simple multiline TextBoxes on a WindowsForms form. *这是从 Windows 窗体应用程序中获取的,因此:txtReceived 和 txtSent 是 WindowsForms 窗体上的简单多行文本框。 and the cursor is the Form's cursor.并且光标是窗体的光标。 * *

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM