using iTextSharp.text.log; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.IO; namespace DealerSelection.Common.Logging; public class LoggingMiddleware { public const string Key = "LoggingMiddlewareCfg"; private const int ReadChunkBufferLength = 4096; private const int MaxContentLength = 10 * 1024 * 1024; //10MB private RecyclableMemoryStreamManager MemoryStreamManager { get; set; } = null; private readonly RequestDelegate RequestDelegate; enum ErrorTypes { Validation, Error }; public LoggingMiddleware(RequestDelegate requestDelegate) { RequestDelegate = requestDelegate; MemoryStreamManager = new RecyclableMemoryStreamManager(); } public async Task Invoke(HttpContext context, ILogger logger) { try { ApiInfo loggingInfo = await ExtractInfoFromRequest(context.Request); Stream originalBodyStream = context.Request.Body; using MemoryStream responseBody = MemoryStreamManager.GetStream(); context.Response.Body = responseBody; await RequestDelegate(context); ExtractMessageHeaderIntoInfo(loggingInfo, context.Request); if(await ExtractResponseInfo(loggingInfo, context.Response, originalBodyStream, logger)) { //logger.Info(loggingInfo.ToString()); AzureLogHelper.LogMessage($"Api Incoming: {loggingInfo.ToString()}"); } } catch { } } private async Task ExtractInfoFromRequest(HttpRequest request) { ApiInfo info = new ApiInfo(request.Method, request.GetDisplayUrl(),Environment.MachineName,DateTime.Now); if(request.ContentLength.GetValueOrDefault() > 0) { request.EnableBuffering(); using MemoryStream requestStream = MemoryStreamManager.GetStream(); await request.Body.CopyToAsync(requestStream); info.RequestInfo.ContentBody = await ReadStreamInChunks(requestStream); request.Body.Position = 0; } return info; } private async Task ReadStreamInChunks(Stream stream) { stream.Seek(0, SeekOrigin.Begin); await using StringWriter textWriter = new StringWriter(); using StreamReader reader = new StreamReader(stream); char[] readChunk = new char[ReadChunkBufferLength]; int readChunkLength; do { readChunkLength = await reader.ReadBlockAsync(readChunk, 0, ReadChunkBufferLength); await textWriter.WriteAsync(readChunk, 0, readChunkLength); } while (readChunkLength > 0); return textWriter.ToString(); } private async Task ExtractResponseInfo(ApiInfo loggingInfo, HttpResponse response, Stream originalBodyStream, ILogger logger) { //loggingInfo.CustomInfo = new CustomInfo(response); if(loggingInfo.IsValid()) { try { loggingInfo.ResponseInfo = new ResponseInfo(response); response.Body.Seek(0, SeekOrigin.Begin); if(response.Body.Length < MaxContentLength) loggingInfo.ResponseInfo.ContentBody = await new StreamReader(response.Body).ReadToEndAsync(); else loggingInfo.ResponseInfo.ContentBody = $"Size {response.Body.Length} too large to retrieve"; } catch (Exception ex) { logger.Error($"Exception logging request {@loggingInfo}, error {@ex}"); return false; } loggingInfo.ResponseInfo.ContentType = response.Headers.ContentType.Any() ? string.Join(",", response.Headers.ContentType) : null; } response.Body.Seek(0, SeekOrigin.Begin); await response.Body.CopyToAsync(originalBodyStream); return loggingInfo.IsValid(); } private void ExtractMessageHeaderIntoInfo(ApiInfo apiInfo, HttpRequest request) { //List> headers = request.Headers.ToList(); //apiInfo.RequestInfo.BuId = HttpHeaderHelper.ExtractInt(CustomInfo.BuId, headers); //apiInfo.RequestInfo.RecordId = HttpHeaderHelper.ExtractInt(CustomInfo.RecordId, headers); //apiInfo.RequestInfo.SecurityContext = HttpHeaderHelper.ExtractInt(CustomInfo.SecurityContext, headers); //apiInfo.RequestInfo.InnerException = HttpHeaderHelper.ExtractInt(CustomInfo.InnerException, headers); //apiInfo.RequestInfo.ExceptionStack = HttpHeaderHelper.ExtractInt(CustomInfo.ExceptionStack, headers); //apiInfo.RequestInfo.RealException = HttpHeaderHelper.ExtractInt(CustomInfo.RealException, headers); //apiInfo.RequestInfo.BuId = HttpHeaderHelper.ExtractInt(CustomInfo.BuId, headers); //apiInfo.RequestInfo.BuId = HttpHeaderHelper.ExtractInt(CustomInfo.BuId, headers); } }