3. HTTP 状态码在 BFF 中的正确使用:2xx/3xx/4xx/5xx 状态码语义、自定义业务状态码设计、状态码映射规范

BFF 作为前端与后端微服务之间的“翻译层”,HTTP 状态码的使用不能简单透传后端原始状态码,也不能全部返回 200 然后在响应体中塞错误码。正确的做法是:BFF 根据前端消费习惯重新映射状态码,同时保留业务语义。本章从标准语义、自定义设计、映射规范三个维度展开。

3.1 HTTP 标准状态码在 BFF 中的语义

BFF 应严格区分“通信状态”与“业务状态”。通信状态由 HTTP 状态码表达,业务状态由响应体中的自定义码表达。下表列出 BFF 中最常用的标准状态码及其语义边界:

分类 状态码 标准含义 BFF 使用场景
2xx 成功 200 请求成功 正常返回业务数据;即使业务逻辑失败(如余额不足),也返回 200 + 业务错误码
2xx 成功 201 已创建 BFF 代理创建类接口(如创建订单、注册用户)成功后返回
2xx 成功 204 无内容 删除操作成功、或批量操作无需返回 body 时使用
3xx 重定向 301/302 永久/临时重定向 BFF 一般不直接返回 3xx,由网关或 CDN 处理;特殊场景如短链服务可透传
3xx 重定向 304 未修改 BFF 缓存层使用 ETag/Last-Modified 时返回,减少带宽
4xx 客户端错误 400 请求参数错误 参数校验失败、JSON 格式错误、必填字段缺失
4xx 客户端错误 401 未认证 Token 缺失、过期、无效;BFF 应统一拦截并返回 401,不转发到后端
4xx 客户端错误 403 无权限 用户已认证但无权访问资源;BFF 从后端响应中提取并映射
4xx 客户端错误 404 资源不存在 请求路径错误、资源已被删除;BFF 应避免暴露后端路径细节
4xx 客户端错误 409 资源冲突 并发修改、唯一约束冲突、重复提交
4xx 客户端错误 429 请求过多 BFF 限流触发时返回,配合 Retry-After 头部
5xx 服务端错误 500 内部错误 BFF 自身未捕获异常、后端服务不可用且无降级数据
5xx 服务端错误 502 网关错误 BFF 连接后端超时、DNS 解析失败、连接被拒绝
5xx 服务端错误 503 服务不可用 BFF 熔断打开、后端过载、主动拒绝请求
5xx 服务端错误 504 网关超时 后端响应超时,BFF 在超时阈值内未收到响应
关键原则:BFF 永远不要将后端 500 直接透传给前端。后端 500 应被 BFF 转换为 502/503/504,或降级为 200 + 业务错误码(如“服务繁忙,请稍后重试”)。

3.2 自定义业务状态码设计

HTTP 状态码只有几十个,无法表达千差万别的业务语义。因此 BFF 必须在响应体中携带自定义业务状态码。设计时遵循“三段式”结构:

// 响应体统一格式
{
  "code": 100200,       // 业务状态码
  "message": "success", // 人类可读描述
  "data": { ... },      // 业务数据
  "traceId": "abc123"   // 链路追踪 ID
}

三段式编码规则:

  • 第一位(1位):错误来源。1=系统级,2=业务级,3=安全级,4=第三方依赖。
  • 第二位(2位):模块编号。01=用户,02=订单,03=支付,04=商品,99=通用。
  • 第三位(3位):具体错误编号。从 001 开始递增,预留 100 个空位。
业务码 含义 HTTP 状态码 说明
100200 成功 200 请求处理正常
100400 参数校验失败 200 业务错误,不返回 400
100401 Token 过期 401 需重新登录
100403 无操作权限 403 权限不足
200001 用户不存在 200 业务查询正常,但数据为空
200201 订单状态不允许取消 200 业务逻辑冲突
200301 支付金额不一致 200 需前端提示用户确认
300001 请求被限流 429 触发 BFF 限流
300002 请求被熔断 503 触发 BFF 熔断
400001 第三方服务超时 504 后端响应超时
400002 第三方服务异常 502 后端返回非预期响应
设计建议:业务状态码的“成功”码固定为 100200,不要使用 0 或 20000 等容易与 HTTP 状态码混淆的值。前端 SDK 统一判断 code === 100200 为成功,其余均为失败。

3.3 状态码映射规范

BFF 从后端微服务获取响应后,需要执行“三层映射”才能返回给前端。映射流程如下图所示:

BFF 状态码三层映射流程 后端微服务 原始 HTTP + 业务码 BFF 映射引擎 状态码转换 + 降级 前端应用 统一响应格式 映射规则 规则一:通信错误透传 后端返回 401/403/429 等客户端错误 BFF 直接透传对应 HTTP 状态码 规则二:服务端错误降级 后端 500 → BFF 502/503/504 或降级为 200 + 业务码 400001 规则三:业务错误统一为 200 后端业务异常(如余额不足) BFF 统一返回 200 + 业务码 规则四:BFF 自身异常 BFF 限流 → 429 + 业务码 300001 BFF 熔断 → 503 + 业务码 300002

映射规范总结为四条硬规则:

  1. 通信错误透传:后端返回 4xx 客户端错误(401/403/404/429),BFF 直接透传对应 HTTP 状态码,不修改状态码分类。
  2. 服务端错误降级:后端返回 5xx,BFF 必须转换为 502/503/504,或降级为 200 + 业务码 400xxx,绝不允许透传 500。
  3. 业务错误统一为 200:后端业务逻辑异常(如“订单已取消”“库存不足”),BFF 统一返回 HTTP 200,业务语义由自定义码表达。
  4. BFF 自身异常独立编码:BFF 限流、熔断、超时等自身故障,使用 429/503/504 + 3xxxx 业务码,与后端错误隔离。

3.4 映射实现示例(Node.js)

// BFF 状态码映射中间件(Node.js + Express 示例)
function statusCodeMapper(req, res, next) {
  // 保存原始 res.json 方法
  const originalJson = res.json.bind(res);

  res.json = function (body) {
    // 如果响应体已有自定义格式,不重复包装
    if (body && typeof body.code === 'number') {
      return originalJson(body);
    }

    // 根据 HTTP 状态码决定映射策略
    const status = res.statusCode;

    if (status >= 200 && status < 300) {
      // 成功:包装为 100200
      return originalJson({
        code: 100200,
        message: 'success',
        data: body,
        traceId: req.traceId
      });
    }

    if (status >= 400 && status < 500) {
      // 客户端错误:透传状态码,业务码映射
      const codeMap = {
        400: 100400,
        401: 100401,
        403: 100403,
        404: 100404,
        429: 300001
      };
      return originalJson({
        code: codeMap[status] || 100400,
        message: body?.message || '客户端请求错误',
        data: null,
        traceId: req.traceId
      });
    }

    if (status >= 500) {
      // 服务端错误:降级为 502/503/504,业务码 4xxxx
      const downgradeStatus = status === 504 ? 504 : 502;
      res.status(downgradeStatus);
      return originalJson({
        code: 400001,
        message: '服务暂时不可用,请稍后重试',
        data: null,
        traceId: req.traceId
      });
    }

    return originalJson(body);
  };

  next();
}
避坑提醒:不要在前端 SDK 中同时判断 HTTP 状态码和业务码。统一约定:前端只判断 code === 100200 为成功,HTTP 状态码仅用于浏览器网络面板调试和 CDN/网关缓存策略。如果前端同时判断 HTTP 200 和 code 100200,会导致后端降级场景(HTTP 502 + code 400001)被错误处理。

3.5 状态码映射规范检查清单

检查项 通过标准 常见违规
后端 500 透传 BFF 转换为 502/503/504 或降级为 200 直接返回 500 给前端
业务错误状态码 统一返回 HTTP 200 + 业务码 返回 400/409 等 HTTP 错误码
限流/熔断状态码 429/503 + 3xxxx 业务码 返回 500 或 200 + 通用错误
成功响应格式 code=100200, data 不为 null 直接透传后端原始 JSON
错误响应格式 code != 100200, data=null, message 有值 data 字段返回错误堆栈
traceId 传递 所有响应均携带 traceId 错误响应缺少 traceId

通过以上规范,BFF 能够为前端提供可预测、可枚举、可自动化处理的错误响应体系。前端团队只需维护一张业务码映射表,即可覆盖所有异常场景,无需关心后端微服务的具体实现细节。