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
- Status-Line
- General Header Fields (
Cache-Control
,Connection
,Date
, ...), - Response Header Fields (
Accept-Ranges
,Age
,Location
, ...) and also - Entity Header Fields
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 .net 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 vscode-restcode 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