diff --git a/cjpm.lock b/cjpm.lock index 972ba8c..6eef633 100644 --- a/cjpm.lock +++ b/cjpm.lock @@ -1,19 +1,19 @@ version = 0 [requires] - soulsoft_web_http = {version = "1.0.20260528"} soulsoft_extensions_options_configuration = {version = "1.0.20260528"} + soulsoft_web_http = {version = "1.0.20260528"} soulsoft_web_routing = {version = "1.0.20260528"} - soulsoft_extensions_logging_configuration = {version = "1.0.20260528"} - soulsoft_extensions_configuration = {version = "1.0.20260528"} - soulsoft_serialization = {version = "1.0.20260528"} - soulsoft_extensions_injection = {version = "1.0.20260528"} - soulsoft_identity_claims = {version = "1.0.20260528"} - soulsoft_extensions_options = {version = "1.0.20260528"} - redis = {version = "1.0.20260627"} - soulsoft_web_hosting = {version = "1.0.20260528"} - soulsoft_web_mvc = {version = "1.0.20260528"} - soulsoft_web_cors = {version = "1.0.20260528"} - soulsoft_extensions_logging_console = {version = "1.0.20260528"} soulsoft_extensions_logging = {version = "1.0.20260528"} + soulsoft_web_hosting = {version = "1.0.20260528"} + soulsoft_identity_claims = {version = "1.0.20260528"} + redis = {version = "1.0.20260627"} soulsoft_extensions_hosting = {version = "1.0.20260528"} + soulsoft_serialization = {version = "1.0.20260528"} + soulsoft_web_mvc = {version = "1.0.20260528"} + soulsoft_extensions_logging_configuration = {version = "1.0.20260528"} + soulsoft_extensions_logging_console = {version = "1.0.20260528"} + soulsoft_extensions_configuration = {version = "1.0.20260528"} + soulsoft_web_cors = {version = "1.0.20260528"} + soulsoft_extensions_options = {version = "1.0.20260528"} + soulsoft_extensions_injection = {version = "1.0.20260528"} diff --git a/src/middlewares/SimApiRequestLogMiddleware.cj b/src/middlewares/SimApiRequestLogMiddleware.cj index b4246ec..765f87f 100644 --- a/src/middlewares/SimApiRequestLogMiddleware.cj +++ b/src/middlewares/SimApiRequestLogMiddleware.cj @@ -24,7 +24,9 @@ import simapi.helpers.* * - 捕获下游异常并记录,随后重抛(对齐 C# ExceptionDispatchInfo + edi.Throw) * - 响应体:soulsoft HttpResponse.body 只读且不可读回(read 抛 UnsupportedException), * 无法像 C# 那样用 MemoryStream 替换捕获;改为在各统一写出入口 - * (SimApiResponseWriter)缓存响应文本,此处直接读取。ShowFullResponse=false 时截断到 200 字符(对齐 C#) + * (SimApiResponseWriter)缓存响应文本,此处直接读取。 + * 响应行格式:*( Response [status] ) => [ N bytes ],随后换行输出响应体结构; + * ShowFullResponse=false 时截断到 200 字符(对齐 C#,长度仍显示完整字节数) * - ShowFullUrl=false 时仅显示路径+查询串;ShowRunTime=true 时请求行显示 [POST] (xxxms) */ public class SimApiRequestLogMiddleware <: IMiddleware { @@ -82,10 +84,28 @@ public class SimApiRequestLogMiddleware <: IMiddleware { } sbHead.append(" ${url}\n") - // 响应信息:状态码 + 响应体(经 SimApiResponseWriter 缓存读取) - sb.append("*( Response [${context.response.statusCode}] ) =>") - sb.append(readResponseBody(context)) - sb.append("\n") + // 响应信息:状态码 + 响应体长度(bytes),响应体结构换行显示 + let responseBody = readResponseBody(context) + let bodyLen = if (responseBody.isEmpty()) { + context.response.contentLength ?? 0 + } else { + responseBody.size + } + sb.append("*( Response [${context.response.statusCode}] ) => [ ${bodyLen} bytes ]\n") + if (!responseBody.isEmpty()) { + let display = if (_options.simApiRequestLogOptions.showFullResponse) { + responseBody + } else if (responseBody.size > 200) { + // 对齐 C#:ShowFullResponse=false 时截断到 200 字符(长度仍显示完整字节数) + responseBody[0..200] + "...(${responseBody.size})" + } else { + responseBody + } + sb.append(display) + if (!display.endsWith("\n")) { + sb.append("\n") + } + } if (let Some(ex) <- exception) { sb.append("Exception: ${ex.toString()}\n") } @@ -165,27 +185,13 @@ public class SimApiRequestLogMiddleware <: IMiddleware { } } - /// 响应体读取:从 SimApiResponseWriter 缓存取;未捕获到时回退 Content-Length + /// 响应体读取:从 SimApiResponseWriter 缓存取完整响应体;未捕获到时返回空串 + /// (长度与截断由调用方处理) private func readResponseBody(context: HttpContext): String { - let body = match (context.items.get(SimApiResponseWriter.responseBodyCacheKey)) { + match (context.items.get(SimApiResponseWriter.responseBodyCacheKey)) { case Some(v) => if (let s: String <- v) { s } else { "" } case None => "" } - if (body.isEmpty()) { - // 未捕获到响应体(如 IActionResult 直写路径):记录 Content-Length 作为替代 - if (let Some(len) <- context.response.contentLength) { - return " (响应体长度: ${len})" - } - return "" - } - if (_options.simApiRequestLogOptions.showFullResponse) { - return body - } - // 对齐 C#:ShowFullResponse=false 时截断到 200 字符 - if (body.size > 200) { - return body[0..200] + "...(${body.size})" - } - return body } /// 请求体截断:JSON 字段级截断(对齐 C#:仅对超长字符串字段截断),非 JSON 则整串截断