75 lines
2.6 KiB
Plaintext
75 lines
2.6 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.communications.*
|
|||
|
|
import simapi.exceptions.*
|
|||
|
|
import simapi.configurations.*
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 异常处理中间件:全异常捕获,统一输出 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"
|
|||
|
|
context.response.write(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 {
|
|||
|
|
response.toJsonString()
|
|||
|
|
}
|
|||
|
|
}
|