refactor(api): 请求体解析收成 readJson / parseBody
54 处 handler 都手写同一段: const parsed = X.safeParse(await c.req.json().catch(() => null)) if (!parsed.success) return failure(c, 400, "invalid-request", ...) 漏写 .catch 就是一个畸形请求打出 500。 - http.ts 加 readJson(读 + 校验)和 parseBody(再加上 400)。parseBody 不给 message 时回 zod 的第一条 issue —— 后台表单原来就是这么写的,fallback 文案 「Invalid payload」/「参数错误」只在 issues 为空时才用得上,实际走不到 - 51 处换成 parseBody;另 3 处失败时带别的错误码或和路径参数一起判,换成 readJson - 错误码、状态码、文案、判断顺序都不变 实跑核过:非 JSON 请求体回原来的固定文案,公告标题为空回 zod issue。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c43da01ff2
commit
f2ca34fd4b
21 files changed
+234
-432
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import type { Context } from "hono"
|
||||
import type { z } from "zod"
|
||||
|
||||
export function success<T>(c: Context, data: T, status = 200) {
|
||||
return c.json({ data }, status as 200)
|
||||
@@ -12,3 +13,42 @@ export function failure(
|
||||
) {
|
||||
return c.json({ error: { code, message } }, status)
|
||||
}
|
||||
|
||||
/**
|
||||
* 读 JSON 请求体并按契约校验。body 不是合法 JSON 时按 `null` 交给 schema,
|
||||
* 由 schema 统一判失败 —— 原来每个 handler 都手写一遍 `c.req.json().catch(() => null)`,
|
||||
* 漏写 `.catch` 就是一个畸形请求打出 500。
|
||||
*/
|
||||
export async function readJson<S extends z.ZodType>(c: Context, schema: S) {
|
||||
return schema.safeParse(await c.req.json().catch(() => null))
|
||||
}
|
||||
|
||||
/**
|
||||
* `readJson` + 校验失败时的 400。绝大多数入参端点就是这个形状:
|
||||
*
|
||||
* const parsed = await parseBody(c, schema, "标签名不能为空")
|
||||
* if (!parsed.success) return parsed.response
|
||||
*
|
||||
* 不给 `message` 就回 zod 的第一条 issue(后台表单要告诉老师具体哪一栏不对)。
|
||||
* 失败时要带别的错误码、或者和路径参数一起判的,用 `readJson` 自己写。
|
||||
*/
|
||||
export async function parseBody<S extends z.ZodType>(
|
||||
c: Context,
|
||||
schema: S,
|
||||
message?: string,
|
||||
): Promise<
|
||||
{ success: true; data: z.output<S> } | { success: false; response: Response }
|
||||
> {
|
||||
const parsed = await readJson(c, schema)
|
||||
if (parsed.success) return { success: true, data: parsed.data }
|
||||
return {
|
||||
success: false,
|
||||
response: failure(
|
||||
c,
|
||||
400,
|
||||
"invalid-request",
|
||||
// issues 不会是空的,?? 只是给类型一个交代
|
||||
message ?? parsed.error.issues[0]?.message ?? "参数错误",
|
||||
),
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user