Last active
January 2, 2022 15:30
-
-
Save bent-rasmussen/7bd3be2606e09759c2f3d84bbefb5626 to your computer and use it in GitHub Desktop.
LINQPad HTTP request tracing tool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Query Kind="Statements"> | |
<Namespace>System.Net.Http</Namespace> | |
<Namespace>System.Threading.Tasks</Namespace> | |
<Namespace>System.Dynamic</Namespace> | |
</Query> | |
await TestAsync("Foo", http => http.GetStringAsync("http://www.google.com/"), HttpFormatOptions.Verbose); | |
static object Title(string message, bool isError = false) | |
{ | |
var color = isError ? "red" : "black"; | |
return Util.RawHtml($"<em style='font-weight:bold;font-style:normal;color:{color}'>{message}</em>"); | |
} | |
async Task TestAsync(string label, Func<HttpClient, Task> test, HttpFormatOptions format) | |
{ | |
var dc = new DumpContainer().Dump(label); | |
var handler = new TransformingHttpHandler(new HttpClientHandler()); | |
handler.Format = format; | |
using var http = new HttpClient(handler); | |
try | |
{ | |
await test(http); | |
dc.AppendContent(Title("Request")); | |
dc.AppendContent(handler.TransformedRequest); | |
dc.AppendContent(Title("Response")); | |
dc.AppendContent(handler.TransformedResponse); | |
} | |
catch (Exception ex) | |
{ | |
dc.AppendContent(Title("Exception")); | |
dc.AppendContent(ex); | |
} | |
} | |
public record HttpFormatOptions | |
{ | |
public bool IncludeRequestContent = true; | |
public bool IncludeResponseContent = true; | |
public static HttpFormatOptions Succint => new HttpFormatOptions() | |
{ | |
IncludeRequestContent = false, | |
IncludeResponseContent = false | |
}; | |
public static HttpFormatOptions Verbose => new HttpFormatOptions() | |
{ | |
IncludeRequestContent = true, | |
IncludeResponseContent = true | |
}; | |
} | |
public class TransformingHttpHandler : DelegatingHandler | |
{ | |
public TransformingHttpHandler(HttpMessageHandler innerHandler) | |
: base(innerHandler) | |
{ | |
} | |
public HttpFormatOptions Format { get; set; } = HttpFormatOptions.Succint; | |
public object TransformedRequest { get; private set; } | |
public object TransformedResponse { get; private set; } | |
static async Task<dynamic> AbbreviateRequestAsync(HttpRequestMessage message, HttpFormatOptions format) | |
{ | |
await Task.Yield(); | |
if (message is null) | |
return new { RequestIsNull = true }; | |
dynamic result = new ExpandoObject(); | |
result.RequestUri = message.RequestUri; | |
result.Method = message.Method.ToString(); | |
if (format.IncludeRequestContent && message.Content is not null) result.Content = await message.Content.ReadAsStringAsync(); | |
if (message.Headers.Any()) result.Headers = message.Headers; | |
return result; | |
} | |
static async Task<dynamic> AbbreviateResponseAsync(HttpResponseMessage message, HttpFormatOptions format) | |
{ | |
await Task.Yield(); | |
if (message is null) | |
return new { ResponseIsNull = true }; | |
dynamic result = new ExpandoObject(); | |
result.Status = message.StatusCode; | |
result.StatusCode = (int)message.StatusCode; | |
result.IsSuccessStatusCode = message.IsSuccessStatusCode; | |
if (format.IncludeResponseContent && message.Content is not null) result.Content = await message.Content.ReadAsStringAsync(); | |
if (message.Headers.Any()) result.Headers = message.Headers; | |
if (message.TrailingHeaders.Any()) result.TrailingHeaders = message.TrailingHeaders; | |
return result; | |
} | |
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | |
{ | |
TransformedRequest = await AbbreviateRequestAsync(request, Format); | |
var response = await base.SendAsync(request, cancellationToken); | |
TransformedResponse = await AbbreviateResponseAsync(response, Format); | |
return response; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment