using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System; using System.Diagnostics; using System.IO; using System.Net; using System.Threading.Tasks; namespace FastGithub.ReverseProxy { /// /// 请求日志中间件 /// sealed class RequestLoggingMiddleware { private readonly ILogger logger; /// /// 请求日志中间件 /// /// public RequestLoggingMiddleware(ILogger logger) { this.logger = logger; } /// /// 执行请求 /// /// /// /// public async Task InvokeAsync(HttpContext context, RequestDelegate next) { var stopwatch = Stopwatch.StartNew(); try { await next(context); } finally { stopwatch.Stop(); } var request = context.Request; var response = context.Response; var message = $"{request.Method} {request.Scheme}://{request.Host}{request.Path} responded {response.StatusCode} in {stopwatch.Elapsed.TotalMilliseconds} ms"; var client = context.Connection.RemoteIpAddress; if (IPAddress.Loopback.Equals(client) == false) { message = $"{client} {message}"; } var exception = context.GetForwarderErrorFeature()?.Exception; if (IsError(exception) == false) { this.logger.LogInformation(message); } else { this.logger.LogError($"{message}{Environment.NewLine}{exception}"); } } private static bool IsError(Exception? exception) { if (exception == null || exception is OperationCanceledException) { return false; } if (exception is IOException ioException && ioException.InnerException is ConnectionAbortedException) { return false; } return true; } } }