Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Request and response logging middleware for HTTP logging
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.IO;
namespace WeatherApi.Middleware;
public class RequestResponseLoggingMiddleware
{
private readonly ILogger<RequestResponseLoggingMiddleware> _logger;
private readonly RecyclableMemoryStreamManager _recyclableMemoryStreamManager;
private readonly RequestDelegate _next;
public RequestResponseLoggingMiddleware(
RequestDelegate next,
ILogger<RequestResponseLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
_recyclableMemoryStreamManager = new RecyclableMemoryStreamManager();
}
public async Task Invoke(HttpContext context)
{
if (!_logger.IsEnabled(LogLevel.Debug))
{
await _next.Invoke(context);
return;
}
await LogRequest(context.Request);
var originalResponseBodyStream = context.Response.Body;
using var responseBody = _recyclableMemoryStreamManager.GetStream();
context.Response.Body = responseBody;
await _next(context);
await LogResponse(context.Response);
await responseBody.CopyToAsync(originalResponseBodyStream);
}
private async Task LogRequest(HttpRequest httpRequest)
{
var requestDictionary = await GetRequestContent(httpRequest);
_logger.LogDebug("Request content: {RequestContent}", requestDictionary);
}
private async Task LogResponse(HttpResponse httpResponse)
{
var responseDictionary = await GetResponseContent(httpResponse);
_logger.LogDebug("Response content: {ResponseContent}", responseDictionary);
}
public async Task<Dictionary<string, string>> GetRequestContent(HttpRequest request)
{
if (request is null)
{
return new Dictionary<string, string>();
}
var requestDictionary = new Dictionary<string, string>
{
{ nameof(request.Method), request.Method },
{ nameof(request.Path), request.Path },
{ nameof(request.Scheme), request.Scheme }
};
if (request.Headers != null && request.Headers.Any())
{
var headers = JsonSerializer.Serialize(request.Headers);
requestDictionary.Add(nameof(request.Headers), headers);
}
if (request.QueryString.HasValue && request.QueryString.Value != null)
{
requestDictionary.Add(nameof(request.QueryString), request.QueryString.Value);
}
if (request.Body is null ||
request.ContentType is null ||
!request.ContentType.Contains("application/json"))
{
return requestDictionary;
}
request.EnableBuffering();
await using var requestBodyStream = _recyclableMemoryStreamManager.GetStream();
await request.Body.CopyToAsync(requestBodyStream);
request.Body.Seek(0, SeekOrigin.Begin);
var requestBodyContent = GetContent(requestBodyStream);
requestDictionary.Add(nameof(request.Body), requestBodyContent);
return requestDictionary;
}
public async Task<Dictionary<string, string>> GetResponseContent(HttpResponse response)
{
if (response is null)
{
return new Dictionary<string, string>();
}
var responseDictionary = new Dictionary<string, string>
{
{ nameof(response.StatusCode), response.StatusCode.ToString() }
};
if (response.Headers != null && response.Headers.Any())
{
var headers = JsonSerializer.Serialize(response.Headers);
responseDictionary.Add(nameof(response.Headers), headers);
}
response.Body.Seek(0, SeekOrigin.Begin);
if (response.ContentType is null || !response.ContentType.Contains("application/json"))
{
return responseDictionary;
}
await using var responseBodyStream = _recyclableMemoryStreamManager.GetStream();
await response.Body.CopyToAsync(responseBodyStream);
var responseBodyContent = GetContent(responseBodyStream);
response.Body.Seek(0, SeekOrigin.Begin);
if (!string.IsNullOrEmpty(responseBodyContent))
{
responseDictionary.Add(nameof(response.Body), responseBodyContent);
}
return responseDictionary;
}
private static string GetContent(Stream stream)
{
const int readChunkBufferLength = 4096;
stream.Seek(0, SeekOrigin.Begin);
using var textWriter = new StringWriter();
using var reader = new StreamReader(stream);
var readChunk = new char[readChunkBufferLength];
int readChunkLength;
do
{
readChunkLength = reader.ReadBlock(readChunk, 0, readChunkBufferLength);
textWriter.Write(readChunk, 0, readChunkLength);
}
while (readChunkLength > 0);
return textWriter.ToString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment