using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using xCommons.Extensions; using xCommons.Models; namespace xCommons.Middlewares { public partial class XRequestLogger { private readonly ILogger logger; private readonly RequestDelegate next; public XRequestLogger ( RequestDelegate next, ILoggerFactory loggerFactory ) { // this.next = next; this.logger = loggerFactory .CreateLogger (); } public async Task InvokeAsync (HttpContext context) { // var logModel = new XLoggerModel (); // logModel.Path = context.Request.Path; logModel.Schema = context.Request.Scheme; logModel.Method = context.Request.Method; logModel.Headers = context.Request.Headers; logModel.Host = context.Request.Host.ToString (); logModel.QueryString = context.Request.QueryString.ToString (); logModel.UserID = context.User.Identity.IsAuthenticated ? context.User.Identity.Name : "Not Authenticated"; // logModel.Connection = new XLoggerHttpConnection { Id = context.Connection.Id, RemoteIpAddress = context.Connection.RemoteIpAddress.ToString (), RemotePort = context.Connection.RemotePort.ToString (), LocalIpAddress = context.Connection.LocalIpAddress.ToString (), LocalPort = context.Connection.LocalPort.ToString (), }; // // Check if a request is a Post Call so read data from Body ... if (context.Request.Method.ToNormalString () == "post") { // context.Request.EnableBuffering (); var request = await new StreamReader (context.Request.Body) .ReadToEndAsync (); // context.Request.Body.Position = 0; logModel.Request = request; } // logModel.RequestedOn = DateTime.UtcNow; // // Do Request ... await next.Invoke (context); // using (Stream originalRequest = context.Response.Body) { try { using (var memStream = new MemoryStream ()) { // context.Response.Body = memStream; // // All the Request processing as described above // happens from here. // Response handling starts from here // set the pointer to the beginning of the // memory stream to read memStream.Position = 0; // // read the memory stream till the end var response = await new StreamReader (memStream) .ReadToEndAsync (); // logModel.Response = response; logModel.RespondedOn = DateTime.UtcNow; logModel.StatusCode = context.Response.StatusCode; logModel.IsSucceed = context.Response.StatusCode >= 200 && context.Response.StatusCode <= 299; // // since we have read till the end of the stream, // reset it onto the first position memStream.Position = 0; // // now copy the content of the temporary memory // stream we have passed to the actual response body // which will carry the response out. await memStream.CopyToAsync (originalRequest); } } catch (Exception ex) { // // Log Exception ... logger.LogError ($"Error on Logging Request/Response ... {ex.ToJSON()}"); } finally { // // assign the response body to the actual context context.Response.Body = originalRequest; } } // // Log Response ... logger.LogCritical ($"Http Response/Response Information:{Environment.NewLine}" + $"Schema:{logModel.Schema} " + Environment.NewLine + $"Host: {logModel.Host} " + Environment.NewLine + $"Path: {logModel.Path} " + Environment.NewLine + $"Method: {logModel.Method} " + Environment.NewLine + $"UserID: {logModel.UserID} " + Environment.NewLine + $"QueryString: {context.Request.QueryString} " + Environment.NewLine + $"Headers: {logModel.Headers.ToJSON()}" + Environment.NewLine + $"" + Environment.NewLine + $"Http Connection: " + Environment.NewLine + $"Id: {logModel.Connection.Id}" + Environment.NewLine + $"RemoteIpAddress: {logModel.Connection.RemoteIpAddress}" + Environment.NewLine + $"RemotePort: {logModel.Connection.RemotePort}" + Environment.NewLine + $"LocalIpAddress: {logModel.Connection.LocalIpAddress}" + Environment.NewLine + $"LocalPort: {logModel.Connection.LocalPort}" + Environment.NewLine + $"" + Environment.NewLine + $"Request Body: {logModel.Request}" + Environment.NewLine + $"RequestedOn: {logModel.RequestedOn}" + Environment.NewLine + $"" + Environment.NewLine + $"IsSucceed: {logModel.IsSucceed}" + Environment.NewLine + $"StatucCode: {logModel.StatusCode}" + Environment.NewLine + $"Response Body: {logModel.Response}" + Environment.NewLine + $"RespondedOn: {logModel.RespondedOn}" + Environment.NewLine + $"" + Environment.NewLine ); } } }