Home > other >  Output all headers from HttpClient HttpResponseMessage to console
Output all headers from HttpClient HttpResponseMessage to console

Time:09-08

I would like to write all Request and Response Headers to the console.

Inside a console application (created via dotnet new console --framework net5.0) i have basically this code

using System;
using System.Collections.Specialized;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

....

var client = new HttpClient();
var request = new HttpRequestMessage();
request.Method = HttpMethod.Get;
// add uri and header and so on ... 

HttpResponseMessage response = await client.SendAsync(request);
PrintHeaders(response);

My first PrintHeaders() looks like this

public static void PrintHeaders(HttpResponseMessage response)
{
    // cast from HttpRequestHeaders
    // and  from HttpResponseHeaders
    PrintHeaders((HttpHeaders)response.RequestMessage.Headers);  
    PrintHeaders((HttpHeaders)response.Headers); 
}

And the other PrintHeaders() like this

public static void PrintHeaders(HttpHeaders headers)
{
    Console.WriteLine( "   Printing Headers " );
    Console.WriteLine( "   KEY        VALUE" );
    var headersEnumerator = headers.GetEnumerator();        
    while (headersEnumerator.MoveNext())
    {
        Console.WriteLine( " {0,-25} {1}"
            , headersEnumerator.Current.Key
            , String.Join(" ",headersEnumerator.Current.Value.GetEnumerator()) );
    }
    Console.WriteLine();
}

What is working

The code works in so far that it receives a response from the server. And writes headers to the console.

Output

 Printing Headers 
 KEY                       VALUE
 Authorization             System.String[]

 Printing Headers
 KEY                       VALUE
 Date                      System.String[]
 Date                      System.SZGenericArrayEnumerator`1[System.String]
 Connection                System.String[]

As you can see above System.String[] or System.SZGenericArrayEnumerator 1[System.String] is written instead of the acutal value.

// System.String[] for
headersEnumerator.Current.Value.ToString() 

// System.SZGenericArrayEnumerator`1[System.String] for
String.Join(" ",headersEnumerator.Current.Value.GetEnumerator())

What is missing / not working?

Not working is to get the header.value as plain string for example for the header-field date something like Wed, 07 Sep 2022 10:45:04 GMT

Instead i only get System.String[] or something similar.

Question

What can i do to output all header-keys and its values as plain text to the console?

CodePudding user response:

Quick fix is to change:

 Console.WriteLine( " {0,-25} {1}"
            , headersEnumerator.Current.Key
            , String.Join(" ",headersEnumerator.Current.Value.GetEnumerator()) );

To

 Console.WriteLine( " {0,-25} {1}"
            , headersEnumerator.Current.Key
            , String.Join(" ",headersEnumerator.Current.Value) ); //removing GetEnumerator()

CodePudding user response:

As a header key value is an enumerable of string, you could do something like this:

foreach (var header in response.Headers){
   foreach (var value in header.Value)
   {
       Console.WriteLine($"{header.Key} : {value}");
   }
}

CodePudding user response:

Headers are different beasts

The rfc2616 section Response mentions

After receiving and interpreting a request message, a server responds with an HTTP response message.

   Response      = Status-Line              ; Section 6.1
                  *(( general-header        ; Section 4.5
                   | response-header        ; Section 6.2
                   | entity-header ) CRLF)  ; Section 7.1
                  CRLF
                  [ message-body ]          ; Section 7.2

This makes it clear that the first lines of a response are not all of the same kind.

It seems to me that the pairing of classes in System.Net.Http is not a perfect match to rfc2616. So afaik there is no easy way to write code like this

printStatusLine();
printGeneralHeader()
printResponseHeader()
printEntityHeader()

Header Types and Status-Line

To my knowledge only differantiates between

  • httpResponseMessage.Headers
  • httpResponseMessage.Content.Headers and
  • fields related to Status-Line

Status Line

So far i got this

public static string GetStatusLine(HttpResponseMessage message)
{
    // HTTP-Version SP Status-Code SP Reason-Phrase CRLF
    // string statusLine = ${"{0} {1} {2}", respMsg.Version)            
    string version = message.Version.ToString();
    string code = ((int)message.StatusCode).ToString();
    string phrase = message.ReasonPhrase;
    string statusLine = $"{version} {code} {phrase} {Environment.NewLine}";
    return statusLine;
}

The code above returns this 1.1 200 OK. I assume that this is according to the status-line specs (HTTP-Version SP Status-Code SP Reason-Phrase CRLF). Nonetheless returns a status-line that looks like this

HTTP/1.1 200 OK

Compromise to get Headers - .net vs rfc2616

Since "dotnet-headers" and "rfc2616-headers" do not seem to match the easiest way is to use these members. But be aware that these methods likely do not return the same fields as you would expect according to rfc2616

public static string GetOtherHeaders(HttpResponseMessage message)
{
    string headerLines = "";
    foreach (var header in message.Headers)
    {
        foreach (var value in header.Value)
        {
            headerLines  = ($"{header.Key} : {value} {Environment.NewLine}");
        }
    }
    return headerLines;
}

and

public static string GetContentHeaders(HttpResponseMessage message)
{
    string contentHeaderLines = "";
    foreach (var header in message.Content.Headers)
    {
        foreach (var value in header.Value)
        {
            contentHeaderLines  = $"{header.Key} : {value} {Environment.NewLine}";
        }
    }
    return contentHeaderLines;
}

Hope that helps

  • Related