using Confluent.Kafka; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using System.Net; using System.Text; using TelpoKafkaConsole.Common; using TelpoKafkaConsole.WebApi.Controllers.Api; namespace TelpoKafkaConsole.WebApi.Middleware { public class LoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public LoggingMiddleware(RequestDelegate next, ILogger logger) { _next = next; _logger = logger; } //public async Task InvokeAsync(HttpContext context) //{ // //// 在请求处理之前记录日志 // //using (_logger.BeginScope(new Dictionary { ["RequestId"] = "" })) // using (new CustomizeStopWatch(nameof(LoggingMiddleware), _logger)) // { // var request = await FormatRequest(context.Request); // _logger.LogInformation(request); // var originalBodyStream = context.Response.Body; // using var responseBody = new MemoryStream(); // context.Response.Body = responseBody; // await _next(context); // var response = await FormatResponse(context.Response); // _logger.LogInformation(response); // await responseBody.CopyToAsync(originalBodyStream); // } //} public async Task InvokeAsync(HttpContext context) { //// 在请求处理之前记录日志 //using (_logger.BeginScope(new Dictionary { ["RequestId"] = "" })) using (new CustomizeStopWatch(nameof(LoggingMiddleware), _logger)) { using var responseBody = new MemoryStream(); var originalBodyStream = context.Response.Body; try { var request = await FormatRequest(context.Request); _logger.LogInformation(request); context.Response.Body = responseBody; await _next(context); var response = await FormatResponse(context.Response); _logger.LogInformation(response); // await responseBody.CopyToAsync(originalBodyStream); } catch (Exception ex) { await HandleExceptionAsync(context, ex); // 捕获异常了 在HandleExceptionAsync中处理 } //var response = await FormatResponse(context.Response); //_logger.LogInformation(response); await responseBody.CopyToAsync(originalBodyStream); } } private async Task FormatRequest(HttpRequest request) { request.EnableBuffering(); var body = await new StreamReader(request.Body).ReadToEndAsync(); var formattedBody = FormatJson(body); request.Body.Position = 0; return $"请求: {request.Scheme} {request.Host}{request.Path} {request.QueryString} {formattedBody}"; } private async Task FormatResponse(HttpResponse response) { response.Body.Seek(0, SeekOrigin.Begin); var body = await new StreamReader(response.Body).ReadToEndAsync(); var formattedBody = FormatJson(body); response.Body.Seek(0, SeekOrigin.Begin); return $"响应: {response.StatusCode}: {formattedBody}"; } private static string FormatJson(string json) { if (string.IsNullOrEmpty(json)) { return string.Empty; } try { var obj = JsonConvert.DeserializeObject(json); // return JsonConvert.SerializeObject(obj, Formatting.Indented); return JsonConvert.SerializeObject(obj); } catch { return json; } } private async Task HandleExceptionAsync(HttpContext context, Exception exception) { context.Response.ContentType = "application/json"; // 返回json 类型 var response = context.Response; var errorResponse = new ErrorResponse { Success = false }; // 自定义的异常错误信息类型 switch (exception) { case ApplicationException ex: if (ex.Message.Contains("Invalid token")) { response.StatusCode = (int)HttpStatusCode.Forbidden; errorResponse.Message = ex.Message; break; } response.StatusCode = (int)HttpStatusCode.BadRequest; errorResponse.Message = ex.Message; break; case KeyNotFoundException ex: response.StatusCode = (int)HttpStatusCode.NotFound; errorResponse.Message = ex.Message; break; default: response.StatusCode = (int)HttpStatusCode.InternalServerError; errorResponse.Message = "Internal Server errors. Check Logs!"; break; } //var apiResponse = ApiResponse.Fail(response.StatusCode, $"{exception.Message}\n{exception.InnerException}\n{exception.StackTrace}"); var apiResponse = ApiResponse.Fail(response.StatusCode, $"{exception.Message}"); var resultJson = JsonConvert.SerializeObject(apiResponse); var resultBytes = Encoding.UTF8.GetBytes(resultJson); await response.Body.WriteAsync(resultBytes, 0, resultBytes.Length); var responseStr = await FormatResponse(context.Response); _logger.LogError(responseStr); } internal class ErrorResponse { public bool Success { get; set; } public string Message { get; set; } = String.Empty; } } }