You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在tRPC中间件中捕获tRPC过程抛出的Google API相关错误?

如何在tRPC中间件层统一捕获并处理Google API错误

我正在开发一个集成Google Drive和Spreadsheet APIs的tRPC应用,为此实现了自定义googleProcedure中间件,向查询或变更操作注入必要上下文,以便基于已认证用户访问Drive文件或表格。我的目标是简化错误处理,拦截来自Google API相关查询或过程的错误,避免在每个单独过程中重复编写错误捕获代码。但当前实现无法有效捕获过程中的错误,代码片段如下:

const googleProcedure = protectedProcedure.use(async ({ ctx, next }) => {
  // Initialization of googleClient, sheets, and drive

  try {
    return await next({
      ctx: {
        ...ctx,
        sheets,
        drive,
      },
    });
  } catch (err) {
    if (err && err instanceof GaxiosError && err.code == '401') {
      throw new TRPCError({
        code: 'UNAUTHORIZED',
        message: 'Not authenticated with Google',
      });
    }
    throw err;
  }
});

// Definitions for googleSpreadsheet router...
export const spreadsheet = router({
  create: googleProcedure.mutation(async ({ ctx, input }) => {}),
  appendRow: googleProcedure.mutation(async ({ ctx, input }) => {}),
  getAll: googleProcedure.query(async ({ ctx, input }) => {}),
  trash: googleProcedure.mutation(async ({ ctx, input }) => {}),
});

我尝试捕获Google相关的401错误并重新抛出为带有UNAUTHORIZED代码的TRPCError,但该方法未能按预期捕获错误。


问题分析

当前实现失效的常见原因有两个:

  1. GaxiosError类型判断失效:未正确导入GaxiosError,导致instanceof判断不成立,错误无法被识别。
  2. 错误码类型不匹配:Google API返回的GaxiosError中,err.code可能是数字形式的HTTP状态码(如401),而非字符串'401',导致判断条件不触发。

修正后的实现

以下是调整后的中间件代码,确保能正确捕获并处理Google API错误:

import { GaxiosError } from 'gaxios';
import { TRPCError } from '@trpc/server';

const googleProcedure = protectedProcedure.use(async ({ ctx, next }) => {
  let sheets, drive;

  try {
    // 初始化Google客户端及API实例(将初始化逻辑也纳入错误捕获)
    const googleClient = await getAuthenticatedGoogleClient(ctx.user.id);
    sheets = googleClient.sheets({ version: 'v4' });
    drive = googleClient.drive({ version: 'v3' });

    // 执行后续过程并注入上下文
    return await next({
      ctx: {
        ...ctx,
        sheets,
        drive,
      },
    });
  } catch (err) {
    // 优先判断是否为Google API的GaxiosError
    if (err instanceof GaxiosError) {
      const statusCode = err.response?.status || err.code;
      // 兼容数字和字符串形式的状态码
      if (statusCode === 401 || statusCode === '401') {
        throw new TRPCError({
          code: 'UNAUTHORIZED',
          message: '未通过Google身份验证',
        });
      }
      // 可扩展处理其他常见Google API错误
      if (statusCode === 403 || statusCode === '403') {
        throw new TRPCError({
          code: 'FORBIDDEN',
          message: '没有访问该Google资源的权限',
        });
      }
    }
    // 非Google API错误,原样抛出
    throw err;
  }
});

// 路由定义无需修改,过程内无需额外try-catch
export const spreadsheet = router({
  create: googleProcedure.mutation(async ({ ctx, input }) => {
    await ctx.sheets.spreadsheets.create({ /* 参数 */ });
  }),
  appendRow: googleProcedure.mutation(async ({ ctx, input }) => {
    await ctx.sheets.spreadsheets.values.append({ /* 参数 */ });
  }),
  getAll: googleProcedure.query(async ({ ctx, input }) => {
    return await ctx.sheets.spreadsheets.values.get({ /* 参数 */ });
  }),
  trash: googleProcedure.mutation(async ({ ctx, input }) => {
    await ctx.drive.files.update({ /* 参数 */ });
  }),
});

关键优化点

  1. 正确导入GaxiosError:确保从gaxios或googleapis包中导入GaxiosError,保证类型判断有效。
  2. 兼容状态码类型:同时判断数字和字符串形式的状态码,覆盖Google API返回的不同格式。
  3. 包含初始化逻辑的错误捕获:将Google客户端的初始化过程也纳入try-catch,捕获认证阶段的错误。
  4. 扩展错误处理能力:可根据需求添加更多Google API常见错误的处理逻辑(如404资源不存在、429请求限流等)。

内容的提问来源于stack exchange,提问作者Anatol Zakrividoroga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 23:00:07