import log4js from "logger"; import { getRequestURL, send, setResponseHeader, setResponseHeaders, setResponseStatus, } from "h3"; import { defineNitroErrorHandler } from "nitropack/runtime"; import { isJsonRequest, normalizeError } from "#server/utils/nitro-error-json"; const logger = log4js.getLogger("ERROR"); const isDev = process.env.NODE_ENV === "development"; /** 优先于 Nitro 内置 JSON 错误体:不向客户端返回 stack(开发/生产一致) */ export default defineNitroErrorHandler(function safeJsonErrorHandler(error, event) { if (!isJsonRequest(event)) { return; } const { statusCode, statusMessage, message } = normalizeError(error, isDev); if (error.unhandled || error.fatal || statusCode >= 500) { logger.error( "[request]", event.method, event.path, error.message, error instanceof Error ? (error.stack ?? "") : "", ); } const url = getRequestURL(event, { xForwardedHost: true, xForwardedProto: true }); setResponseHeaders(event, { "Content-Security-Policy": "script-src 'none'; frame-ancestors 'none';", "X-Content-Type-Options": "nosniff", "X-Frame-Options": "DENY", "Referrer-Policy": "no-referrer", }); if (statusCode === 404) { setResponseHeader(event, "Cache-Control", "no-cache"); } setResponseStatus(event, statusCode, statusMessage); setResponseHeader(event, "Content-Type", "application/json"); const body: Record = { error: true, url: url.href, statusCode, statusMessage, message, }; if (error.data !== undefined) { body.data = error.data; } return send(event, JSON.stringify(body)); });