using System.Text; using Common; using CommonDomain; using CommonService; using Newtonsoft.Json; namespace UserHost.Middleware { public class ApiLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; private readonly IApiLogService _apiLogService; public ApiLoggingMiddleware(RequestDelegate next, ILogger logger, IApiLogService apiLogService) { _next = next; _logger = logger; _apiLogService = apiLogService; } public async Task Invoke(HttpContext httpContext) { var request = httpContext.Request; if (request.Path.StartsWithSegments(new PathString("/api")) && request.Method.ToLower() != "options") { var requestTime = DateTime.Now; var requestBodyContent = string.Empty; var originalRequest = httpContext.Response.Body; if (request.Method == "POST") { request.EnableBuffering(); requestBodyContent = await new StreamReader(request.Body).ReadToEndAsync(); request.Body.Position = 0; } try { using (var responseBody = new MemoryStream()) { var response = httpContext.Response; response.Body = responseBody; await _next(httpContext); string responseBodyContent = null; responseBodyContent = await FormatResponse(response); await responseBody.CopyToAsync(originalRequest); string token = string.Empty, version = string.Empty, userAgent = string.Empty, source = string.Empty, deviceId = string.Empty, device = string.Empty, ip = string.Empty,sign=string.Empty; if (httpContext.Request != null && httpContext.Request.Headers != null) { if (!string.IsNullOrEmpty(httpContext.Request.Headers["Token"])) { token = httpContext.Request.Headers["Token"] + ""; } if (!string.IsNullOrEmpty(httpContext.Request.Headers["Version"])) { version = httpContext.Request.Headers["Version"] + ""; } if (!string.IsNullOrEmpty(httpContext.Request.Headers["User-Agent"])) { userAgent = httpContext.Request.Headers["User-Agent"] + ""; } if (!string.IsNullOrEmpty(httpContext.Request.Headers["Source"])) { source = httpContext.Request.Headers["Source"] + ""; } if (!string.IsNullOrEmpty(httpContext.Request.Headers["DeviceId"])) { deviceId = httpContext.Request.Headers["DeviceId"] + ""; } if (!string.IsNullOrEmpty(httpContext.Request.Headers["Device"])) { device = httpContext.Request.Headers["Device"] + ""; } if (!string.IsNullOrEmpty(httpContext.Request.Headers["Ip"])) { ip = httpContext.Request.Headers["Ip"] + ""; } if (!string.IsNullOrEmpty(httpContext.Request.Headers["Sign"])) { sign = httpContext.Request.Headers["Sign"] + ""; } } string allResponseContent = responseBodyContent; try { if (!string.IsNullOrEmpty(responseBodyContent)) { BaseResponse baseResponse = JsonConvert.DeserializeObject>(responseBodyContent); if (baseResponse != null && baseResponse.Data != null) { baseResponse.Data = null; } responseBodyContent = JsonConvert.SerializeObject(baseResponse); } } catch (Exception ex) { _logger.LogError(ex, "API响应日志脱敏序列化失败 path={Path}", request.Path); } var now = DateTime.Now; var apilog = new ApiLog() { requestTime = now, accessToken = token, clientIP = httpContext.Connection.RemoteIpAddress.ToString(), consumeTime = (DateTime.Now - requestTime).Milliseconds, requestHead= JsonConvert.SerializeObject(httpContext.Request.Headers), requestUrl = request.Path, requestMethod = request.Method.ToLower(), requestQuery = request.QueryString.ToString(), requestBody = requestBodyContent, httpStatus = httpContext.Response.StatusCode, responseBody = responseBodyContent, userAgent = userAgent, device= device, deviceId= deviceId, ip=ip, source=source, version=version, sign=sign }; await _apiLogService.InsertOneAsync(apilog); } } catch (Exception ex) { _logger.LogError(ex, "API日志记录失败 path={Path}", request.Path); } finally { httpContext.Response.Body = originalRequest; } } else { await _next(httpContext); } } private async Task FormatRequest(Microsoft.AspNetCore.Http.HttpRequest request) { var body = request.Body; request.EnableBuffering(); var buffer = new byte[Convert.ToInt32(request.ContentLength)]; await request.Body.ReadAsync(buffer, 0, buffer.Length); var bodyAsText = Encoding.UTF8.GetString(buffer); request.Body = body; return bodyAsText; } private async Task FormatResponse(HttpResponse response) { response.Body.Seek(0, SeekOrigin.Begin); string text = await new StreamReader(response.Body).ReadToEndAsync(); response.Body.Seek(0, SeekOrigin.Begin); return text; } } public static class ApiLoggingMiddlewareExtensions { public static IApplicationBuilder UseApiLogging(this IApplicationBuilder app) { return app.UseMiddleware(); } } }