View Request & Response Headers For HTTP Requests In C# & .NET
[C#, NET]
It is very straightforward to send a HTTP request in C#. You do it like this:
// Setup our httpClient
var client = new HttpClient();
// Set the user agent because some servers reject requests without one
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0");
// Make a GET request
var response = await client.GetAsync("http://conradakunga.com");
// Retrieve the content
var result = await response.Content.ReadAsStringAsync();
// Print to console
Console.WriteLine(result);
Now, suppose you wanted to view the headers returned in your responses? This is very useful when troubleshooting and debugging.
You can achieve this using a DelegatingHandler. You can pass this class to your HttpClient, telling it to delegate its work. It is within this class that you do the heavy lifting.
The class looks like this:
public sealed class ViewHeadersDelegatingHandler : DelegatingHandler
{
public ViewHeadersDelegatingHandler() : base(new HttpClientHandler())
{
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Log request header summary
Log.Information("REQUEST HEADERS: {Count}", request.Headers.Count());
foreach (var header in request.Headers)
{
// Log each header
Log.Information("{Header} : {Value}", header.Key, string.Join(", ", header.Value));
}
// Check if the request contents have headers
if (request.Content?.Headers != null)
{
// Log request content header summary
Log.Information("REQUEST CONTENT HEADERS: {Count}", request.Content.Headers.Count());
foreach (var header in request.Content.Headers)
{
// Log each header
Log.Information("{Header} : {Value}", header.Key, string.Join(", ", header.Value));
}
}
Log.Information("Sending request to {URL}", request.RequestUri);
// Send the request and get the response
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
// Log response headers summary
Log.Information("RESPONSE HEADERS: {Count}", response.Headers.Count());
foreach (var header in response.Headers)
{
// Log each header
Log.Information("{Header} : {Value}", header.Key, string.Join(", ", header.Value));
}
// Check if response content has headers. It is unlikely
// for the content to be null, but check anyway
if (response.Content?.Headers != null)
{
Log.Information("RESPONSE CONTENT HEADERS: {Count}", response.Content.Headers.Count());
foreach (var header in response.Content.Headers)
{
// Log each header
Log.Information("{Header} : {Value}", header.Key, string.Join(", ", header.Value));
}
}
Log.Information("Request complete");
return response;
}
In this class I am using Serilog to output log messages.
You can then use this class in a calling program, like this:
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
var client = new HttpClient(new ViewHeadersDelegatingHandler());
// Set the user agent because some servers reject requests without one
client.DefaultRequestHeaders.Add("User-Agent",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14.5; rv:42.0) Gecko/20100101 Firefox/42.0");
// Make a GET request
var response = await client.GetAsync("http://conradakunga.com");
// Retrieve the content
var result = await response.Content.ReadAsStringAsync();
If I run this code, I get the following results:
[20:08:09 INF] REQUEST HEADERS: 1
[20:08:09 INF] User-Agent : Mozilla/5.0, (Macintosh; Intel Mac OS X 14.5; rv:42.0), Gecko/20100101, Firefox/42.0
[20:08:09 INF] Sending request to http://conradakunga.com/
[20:08:11 INF] RESPONSE HEADERS: 6
[20:08:11 INF] Date : Sun, 16 Feb 2025 17:08:11 GMT
[20:08:11 INF] Server : Apache
[20:08:11 INF] ETag : "1e232-62e35e3b99a40"
[20:08:11 INF] Accept-Ranges : bytes
[20:08:11 INF] Cache-Control : max-age=600
[20:08:11 INF] Vary : Accept-Encoding, User-Agent
[20:08:11 INF] RESPONSE CONTENT HEADERS: 4
[20:08:11 INF] Last-Modified : Sat, 15 Feb 2025 22:34:09 GMT
[20:08:11 INF] Content-Length : 123442
[20:08:11 INF] Expires : Sun, 16 Feb 2025 17:18:11 GMT
[20:08:11 INF] Content-Type : text/html
[20:08:11 INF] Request complete
Which looks like this:
We can update the program to fetch a bunch of headers from different sites, which have some interesting headers.
string[] urls =
[
"https://www.booking.com",
"https://www.conradakunga.com",
"https://www.gigaom.com",
"https://www.newsblur.com",
"https://www.wordpress.com",
];
// Make a GET request
foreach (var url in urls)
{
_ = await client.GetAsync(url);
}
Booking.com has this:
Gigaom has this:
NewsBlur has this:
WordPress has this:
TLDR
DelegatingHandlers
allow you to access data from any of the points of a HTTP request, such as the complete set of headers and content headers.
The code is in my GitHub.
Happy hacking!