Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class RequestResponseLoggingMiddleware
- {
- private readonly RequestDelegate _next;
- private readonly ILogger<RequestResponseLoggingMiddleware> _logger;
- private readonly RecyclableMemoryStreamManager _recyclableMemoryStreamManager;
- private const int ReadChunkBufferLength = 4096;
- public RequestResponseLoggingMiddleware(RequestDelegate next, ILogger<RequestResponseLoggingMiddleware> logger)
- {
- _next = next;
- _logger = logger;
- _recyclableMemoryStreamManager = new RecyclableMemoryStreamManager();
- }
- public async Task Invoke(HttpContext context)
- {
- var requestProfilerModel = new RequestProfilerModel
- {
- RequestTime = new DateTimeOffset(),
- Context = context,
- Request = await FormatRequestAsync(context)
- };
- var originalBody = context.Response.Body;
- using (var newResponseBody = _recyclableMemoryStreamManager.GetStream())
- {
- context.Response.Body = newResponseBody;
- await _next(context);
- newResponseBody.Seek(0, SeekOrigin.Begin);
- await newResponseBody.CopyToAsync(originalBody);
- newResponseBody.Seek(0, SeekOrigin.Begin);
- requestProfilerModel.Response = await FormatResponseAsync(context, newResponseBody);
- requestProfilerModel.ResponseTime = new DateTimeOffset();
- _logger.LogInformation(requestProfilerModel.Request);
- _logger.LogInformation(requestProfilerModel.Response);
- }
- }
- private async Task<string> FormatResponseAsync(HttpContext context, Stream newResponseBody)
- {
- var request = context.Request;
- var response = context.Response;
- return $"Http Response Information: {Environment.NewLine}" +
- $"Schema: {request.Scheme} {Environment.NewLine}" +
- $"Host: {request.Host} {Environment.NewLine}" +
- $"Path: {request.Path} {Environment.NewLine}" +
- $"QueryString: {request.QueryString} {Environment.NewLine}" +
- $"Headers: {Environment.NewLine}" + FormatHeaders(response.Headers) +
- $"StatusCode: {response.StatusCode} {Environment.NewLine}" +
- $"Response Body: {await ReadStreamInChunksAsync(newResponseBody)}";
- }
- private async Task<string> FormatRequestAsync(HttpContext context)
- {
- var request = context.Request;
- return $"Http Request Information: {Environment.NewLine}" +
- $"Schema:{request.Scheme} {Environment.NewLine}" +
- $"Host: {request.Host} {Environment.NewLine}" +
- $"Path: {request.Path} {Environment.NewLine}" +
- $"QueryString: {request.QueryString} {Environment.NewLine}" +
- $"Headers: {Environment.NewLine}" + FormatHeaders(request.Headers) +
- $"Request Body: {await GetRequestBodyAsync(request)}";
- }
- private string FormatHeaders(IHeaderDictionary headers)
- {
- var stringBuilder = new StringBuilder();
- foreach (var (key, value) in headers)
- {
- stringBuilder.AppendLine($"- {key}: {value}");
- }
- return stringBuilder.ToString();
- }
- public async Task<string> GetRequestBodyAsync(HttpRequest request)
- {
- request.EnableBuffering();
- request.EnableRewind();
- using (var stream = _recyclableMemoryStreamManager.GetStream())
- {
- await request.Body.CopyToAsync(stream);
- request.Body.Seek(0, SeekOrigin.Begin);
- return await ReadStreamInChunksAsync(stream);
- }
- }
- private static async Task<string> ReadStreamInChunksAsync(Stream stream)
- {
- stream.Seek(0, SeekOrigin.Begin);
- string result;
- using (var stringWriter = new StringWriter())
- using (var streamReader = new StreamReader(stream))
- {
- var readChunk = new char[ReadChunkBufferLength];
- int readChunkLength;
- //do while: is useful for the last iteration in case readChunkLength < chunkLength
- do
- {
- readChunkLength = await streamReader.ReadBlockAsync(readChunk, 0, ReadChunkBufferLength);
- await stringWriter.WriteAsync(readChunk, 0, readChunkLength);
- } while (readChunkLength > 0);
- result = stringWriter.ToString();
- }
- return result;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement