Skip to content

fix: handleErrorResponse 只认自家信封,其它形状的错误响应体都被吞成 "400 Bad Request" #57

Description

@LittlePenhu

src/lib/api/client.ts:109 的兜底链只认两种形状的响应体,其它形状一律退化成状态码,把服务端给的信息全丢了(main @ 99029d7)。

const error = body?.status?.message ?? body?.message ?? `${httpStatus} ${statusText}`;

而 parseBody(:53-61)碰到非 JSON 时会把文本原样返回:

async function parseBody(resp: Response): Promise<any> {
  const text = await resp.text();
  if (!text) return null;
  try {
    return JSON.parse(text);
  } catch {
    return text;
  }
}

于是下面这些响应体在界面上都是同一句话。我用仓库里真实的 client.ts 各跑了一遍(桩掉 fetch 让它返回 400 + 对应响应体,看最终抛给提示栏的是什么):

服务端实际返回的响应体 界面上显示
{"status":{"code":95001,"message":"数据校验失败:xxx"},…} "数据校验失败:xxx"
{"status":{"code":95001,"message":""},…} ""(空提示)
{"timestamp":…,"status":400,"error":"Bad Request","path":"…"}(Spring 默认错误体) "400 Bad Request"
<!doctype html><html>…400 Bad Request…</html> "400 Bad Request"
Bad Request: failed to read request body(纯文本) "400 Bad Request"
空响应体 "400 Bad Request"

只有第一种(项目自己的信封)能把服务端的话带出来,后四种在界面上完全一样。

这不是假设出来的场景。今天有人在导入页上传音击的档案 JSON,只看到 400、拿不到任何原因,最后只能挂一个 window.fetch 钩子把原始响应体捞出来看。这条兜底链恰好把唯一能定位问题的信息丢掉了。

顺带一个对照,说明信封本身是好的:同一个后端对未鉴权请求会返回 {"status":{"code":94011,"message":"Unauthorized"},"time":"…","data":"Insufficient authentication"},那种情况界面上能正常显示。问题只出在"信封之外的形状"。

(那个导入 400 本身是什么引起的,我还没有结论——后端不开源,拿不到它的导入 DTO。这不影响本 issue:无论后端说了什么,前端现在都显示不出来。)

修法:

-  const error = body?.status?.message ?? body?.message ?? `${httpStatus} ${statusText}`;
+  // 非信封形状的响应体也得能透出点什么,否则界面上只剩一个状态码
+  const raw = typeof body === 'string'
+    ? body.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 200)
+    : '';
+  const error = body?.status?.message || body?.message || raw || `${httpStatus} ${statusText}`;

我把这几行又按上面那张表格逐个跑了一遍:

响应体形状 现在 改后
自家信封(带 message) 数据校验失败:xxx 不变
自家信封,message 为空 ""(空提示) 400 Bad Request
Spring 默认错误体 400 Bad Request 不变
HTML 错误页 400 Bad Request 不变(原文里就是这个词)
纯文本 400 Bad Request Bad Request: failed to read request body
空响应体 400 Bad Request 不变

关键点是:现在能正常显示的那条路一个字都不动(信封里的 message 照旧原样透出,不会影响 parity 断言),只把"什么都显示不出来"的那几种情形补上。?? 换 || 也顺带修掉了空字符串弹空提示的问题。

(我第一版草稿想把状态码固定拼在前面,实测发现 HTML 错误页会变成 400 400 Bad Request,所以没采用。另外 body 是纯文本时 .status / .message 取不到值,可选链会安全跳过,raw 那条能兜住。)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions