Skip to content

Instantly share code, notes, and snippets.

@mocella
Last active February 16, 2023 13:24
Show Gist options
  • Save mocella/9d11e3bffdd63df2443e7baa8d490eb4 to your computer and use it in GitHub Desktop.
Save mocella/9d11e3bffdd63df2443e7baa8d490eb4 to your computer and use it in GitHub Desktop.
.NET6 Middleware to log HttpContext request/response details
{
......
"FeatureFlags": {
"HttpRequestLoggingEnabled": true
}
}
public class HttpContextLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
private const int BodyLogSizeLimit = 4096;
public HttpContextLoggingMiddleware(
RequestDelegate next,
ILogger logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
var requestBodyStream = new MemoryStream();
var responseBodyStream = new MemoryStream();
var requestLog = new StringBuilder();
try
{
requestLog.AppendLine($"REQUEST Host: {context.Request.Host} - Path: {context.Request.Path} - HttpMethod: {context.Request.Method}");
if (context.Request.QueryString.HasValue)
{
requestLog.AppendLine($"REQUEST QueryString: {context.Request.QueryString}");
}
try
{
using var bodyReader = new StreamReader(context.Request.Body);
var bodyAsText = await bodyReader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(bodyAsText))
{
if (bodyAsText.Length > BodyLogSizeLimit)
{
// retain only first "BodyLogSizeLimit" characters so as to not blow up our logs too much
bodyAsText = bodyAsText[..BodyLogSizeLimit];
}
requestLog.AppendLine($"REQUEST Body : {bodyAsText}");
}
var bytesToWrite = Encoding.UTF8.GetBytes(bodyAsText);
requestBodyStream.Write(bytesToWrite, 0, bytesToWrite.Length);
requestBodyStream.Seek(0, SeekOrigin.Begin);
context.Request.Body = requestBodyStream;
}
catch (Exception)
{
requestLog.AppendLine($"REQUEST Body : N/A");
}
var originalBody = context.Response.Body;
using var newBody = new MemoryStream();
context.Response.Body = newBody;
await _next.Invoke(context); // send the request so we can capture the Response details we care to log
requestLog.AppendLine($"RESPONSE Status: {context.Response.StatusCode}");
try
{
newBody.Seek(0, SeekOrigin.Begin);
using var bodyReader = new StreamReader(context.Response.Body);
var bodyAsText = await bodyReader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(bodyAsText))
{
if (bodyAsText.Length > BodyLogSizeLimit)
{
// retain only first "BodyLogSizeLimit" characters so as to not blow up our logs too much
bodyAsText = bodyAsText[..BodyLogSizeLimit];
}
requestLog.AppendLine($"RESPONSE Body : {bodyAsText}");
}
newBody.Seek(0, SeekOrigin.Begin);
await newBody.CopyToAsync(originalBody);
}
catch (Exception)
{
requestLog.AppendLine($"RESPONSE Body : N/A");
}
_logger.LogInfo(requestLog.ToString());
}
finally
{
await requestBodyStream.DisposeAsync();
await responseBodyStream.DisposeAsync();
}
}
}
....
var app = builder.Build();
//
var httpLoggingEnabled = builder.Configuration.GetValue<bool>("FeatureFlags:HttpRequestLoggingEnabled");
if(httpLoggingEnabled)
{
app.UseMiddleware<HttpContextLoggingMiddleware>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment