77 lines
2.7 KiB
Plaintext
77 lines
2.7 KiB
Plaintext
/*
|
||
* Copyright (c) 2025 SimcuTeam. All rights reserved.
|
||
* 移植自 C# 项目 SimApi(E:\simcu\simapi-net),遵循 MIT 许可证。
|
||
*/
|
||
|
||
package simapi.middlewares
|
||
|
||
import soulsoft_web_http.*
|
||
import soulsoft_extensions_logging.*
|
||
import simapi_serialization.*
|
||
import simapi.communications.*
|
||
import simapi.exceptions.*
|
||
import simapi.configurations.*
|
||
import simapi.helpers.*
|
||
|
||
/**
|
||
* 异常处理中间件:全异常捕获,统一输出 HTTP 200 + JSON 响应。
|
||
* 对应 C# 的 SimApi.Middlewares.SimApiExceptionMiddleware。
|
||
*/
|
||
public class SimApiExceptionMiddleware <: IMiddleware {
|
||
private let _options: SimApiOptions
|
||
private let _logger: ILogger
|
||
|
||
public init(options: SimApiOptions, loggerFactory: ILoggerFactory) {
|
||
_options = options
|
||
_logger = loggerFactory.createLogger("SimApi.ExceptionMiddleware")
|
||
}
|
||
|
||
/**
|
||
* 中间件入口(IMiddleware 风格,对齐 C# UseMiddleware<T> 的 InvokeAsync)。
|
||
*/
|
||
public func invoke(context: HttpContext, next: RequestDelegate): Unit {
|
||
try {
|
||
// 透传 Query-Id 请求头
|
||
if (let Some(queryId) <- context.request.headers.get("Query-Id")) {
|
||
context.response.headers.add("Query-Id", queryId)
|
||
}
|
||
next(context)
|
||
// 若响应未开始且状态码不在跳过列表,则视为业务错误
|
||
if (!context.response.hasStarted) {
|
||
let code = Int64(context.response.statusCode)
|
||
if (!_options.simApiExceptionOptions.skipStatusCodes.contains(code)) {
|
||
throw SimApiException(code)
|
||
}
|
||
}
|
||
} catch (ex: Exception) {
|
||
let response = buildResponse(ex, context)
|
||
if (!context.response.hasStarted) {
|
||
context.response.statusCode = 200
|
||
context.response.contentType = "application/json; charset=utf-8"
|
||
SimApiResponseWriter.write(context, responseJson(response))
|
||
}
|
||
}
|
||
}
|
||
|
||
private func buildResponse(ex: Exception, context: HttpContext): SimApiBaseResponse {
|
||
if (let simEx: SimApiException <- ex) {
|
||
let message = if (simEx.message.isEmpty()) {
|
||
SimApiBaseResponse.getDefaultMessage(simEx.code)
|
||
} else {
|
||
simEx.message
|
||
}
|
||
var response = SimApiBaseResponse(simEx.code, message)
|
||
if (context.response.statusCode == 404) {
|
||
response.message = "接口不存在"
|
||
}
|
||
return response
|
||
}
|
||
_logger.error(EventId(0), ex, ex.message)
|
||
return SimApiBaseResponse(500)
|
||
}
|
||
|
||
private func responseJson(response: SimApiBaseResponse): String {
|
||
JsonSerializer.Serialize(response)
|
||
}
|
||
}
|