import { randomUUID } from 'node:crypto'; import { sendOpenApiProblem, type OpenApiProblemResponse } from './open-api.protocol'; /** Mounted after parsers, before routes; never expose parser errors containing raw input. */ export function openApiBodyErrorMiddleware( error: unknown, request: { openApiRequestId?: string }, response: OpenApiProblemResponse, next: (error: unknown) => void, ) { const type = error && typeof error === 'object' && 'type' in error ? error.type : undefined; const failures: Record = { 'entity.parse.failed': { status: 400, code: 'PARAMETER_INVALID', message: '请求体必须为有效的JSON对象' }, 'entity.too.large': { status: 413, code: 'PAYLOAD_TOO_LARGE', message: '请求体超过大小限制' }, 'charset.unsupported': { status: 415, code: 'UNSUPPORTED_MEDIA_TYPE', message: '请求体字符集不受支持' }, 'encoding.unsupported': { status: 415, code: 'UNSUPPORTED_MEDIA_TYPE', message: '请求体编码不受支持' }, }; const failure = typeof type === 'string' && Object.hasOwn(failures, type) ? failures[type] : undefined; if (!failure) return next(error); sendOpenApiProblem(response, (request.openApiRequestId ??= `req_${randomUUID()}`), failure); }