Last active
October 6, 2024 18:15
-
-
Save ahmedalejo/13db39cee504127c75456185518e00eb to your computer and use it in GitHub Desktop.
C#: Enable unobtrusive HttpClient request-response logging
This file contains hidden or 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
//Original share here https://github.com/reactiveui/refit/issues/258#issuecomment-243394076 on Aug 30, 2016 | |
//var httpClient = new HttpClient(new HttpLoggingHandler()){ BaseAddress = /**/}; | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Net.Http; | |
using System.Net.Http.Headers; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace Service.Shared.Clients; | |
public class HttpLoggingHandler : DelegatingHandler | |
{ | |
public HttpLoggingHandler(HttpMessageHandler innerHandler) | |
: base(innerHandler) | |
{ } | |
async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | |
{ | |
await Task.Delay(1, cancellationToken).ConfigureAwait(false); | |
var req = request; | |
var id = Guid.NewGuid().ToString(); | |
var msg = $"[{id} - Request]"; | |
var uri = req.RequestUri ?? throw new ArgumentNullException(nameof(request), "RequestUri can´t be null"); | |
var scheme = req.RequestUri.Scheme.ToUpperInvariant(); | |
WriteLine($"{msg}========Start=========="); | |
WriteLine($"{msg} {req.Method} {uri.PathAndQuery} {scheme}/{req.Version}"); | |
WriteLine($"{msg} Host: {uri.Scheme}://{uri.Host}"); | |
foreach (var header in req.Headers) | |
WriteLine($"{msg} {header.Key}: {string.Join(", ", header.Value)}"); | |
if (req.Content != null) | |
{ | |
foreach (var header in req.Content.Headers) | |
WriteLine($"{msg} {header.Key}: {string.Join(", ", header.Value)}"); | |
if (req.Content is StringContent || IsTextBasedContentType(req.Headers) || IsTextBasedContentType(req.Content.Headers)) | |
{ | |
var result = await req.Content.ReadAsStringAsync(cancellationToken); | |
WriteLine($"{msg} Content:"); | |
WriteLine($"{msg} {string.Join("", result.Cast<char>().Take(255))}..."); | |
} | |
} | |
var start = DateTime.Now; | |
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false); | |
var end = DateTime.Now; | |
WriteLine($"{msg} Duration: {end - start}"); | |
WriteLine($"{msg}==========End=========="); | |
msg = $"[{id} - Response]"; | |
WriteLine($"{msg}=========Start========="); | |
var resp = response; | |
WriteLine($"{msg} {scheme}/{resp.Version} {(int)resp.StatusCode} {resp.ReasonPhrase}"); | |
foreach (var header in resp.Headers) | |
WriteLine($"{msg} {header.Key}: {string.Join(", ", header.Value)}"); | |
if (resp.Content != null) | |
{ | |
foreach (var header in resp.Content.Headers) | |
WriteLine($"{msg} {header.Key}: {string.Join(", ", header.Value)}"); | |
if (resp.Content is StringContent || IsTextBasedContentType(resp.Headers) || IsTextBasedContentType(resp.Content.Headers)) | |
{ | |
start = DateTime.Now; | |
var result = await resp.Content.ReadAsStringAsync(cancellationToken); | |
end = DateTime.Now; | |
WriteLine($"{msg} Content:"); | |
WriteLine($"{msg} {string.Join("", result.Cast<char>().Take(255))}..."); | |
WriteLine($"{msg} Duration: {end - start}"); | |
} | |
} | |
WriteLine($"{msg}==========End=========="); | |
return response; | |
} | |
private static readonly string[] types = new[] { "html", "text", "xml", "json", "txt" }; | |
private static void WriteLine(FormattableString message) => | |
Debug.WriteLine(message); | |
private static bool IsTextBasedContentType(HttpHeaders headers) | |
{ | |
if (!headers.TryGetValues("Content-Type", out var values)) | |
return false; | |
var header = string.Join(" ", values).ToLowerInvariant(); | |
return types.Any(t => header.Contains(t)); | |
} | |
} |
This file contains hidden or 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
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Request]=========Start========= | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Request]========Start========== | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Request] GET / HTTPS/1.1 | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Request] Host: https://www.google.com | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Request] Duration: 00:00:00.2298277 | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Request]==========End========== | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response]=========Start========= | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] HTTPS/1.1 200 OK | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] X-XSS-Protection: 1; mode=block | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] X-Frame-Options: SAMEORIGIN | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Alternate-Protocol: 443:quic | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Alt-Svc: quic=":443"; ma=2592000; v="35,34,33,32,31,30" | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Vary: Accept-Encoding | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Transfer-Encoding: chunked | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Accept-Ranges: none | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Cache-Control: max-age=0, private | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Date: Tue, 30 Aug 2016 10:02:32 GMT | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] P3P: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info." | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Set-Cookie: NID=85=SAxtO23sG2Xuap7whetoj9Hn353S-wRFCEifyNFeFBIRWkd5fL4h2ws3rgyvk_dfIPbX_5SYqELFHWj4nXO62FxWpC3eeurykZEZQtI-EO9KsQDWpju9SaQ3XY9xwUa7; expires=Wed, 01-Mar-2017 10:02:32 GMT; path=/; domain=.google.com.br; HttpOnly | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Server: gws | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Content-Type: text/html; charset=ISO-8859-1 | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Expires: -1 | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Content: | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="pt"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>... | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response] Duration: 00:00:00.0503445 | |
[83544d2e-6f8b-4e6c-9827-a5e58557f99c - Response]==========End========== |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment