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

Firebase可调用函数的中间件实现与通用逻辑提取方案咨询

Firebase Callable Functions 类中间件能力实现方案

核心实现逻辑

Firebase Callable Functions 没有内置类似 Express 的中间件机制,我们可以通过高阶函数封装实现同等的前置校验、逻辑复用能力:将通用的前置逻辑抽为独立的中间件函数,在业务代码执行前按顺序执行,遇到不符合要求的请求直接抛出错误拦截,无需在每个业务函数中重复编写校验逻辑。


具体实现步骤

1. 封装中间件执行高阶函数

首先定义通用的包装函数,负责接收中间件数组和实际的业务处理函数,按顺序执行中间件链条:

import * as functions from "firebase-functions";

// 中间件类型定义:参数为可调用函数的入参、上下文、共享透传状态,返回错误则直接拦截请求
type Middleware = (
  data: unknown,
  context: functions.https.CallableContext,
  state: Record<string, unknown>
) => functions.https.HttpsError | Promise<functions.https.HttpsError | void>;

/**
 * 可调用函数中间件包装器
 * @param middlewares 要执行的中间件数组,按顺序执行
 * @param handler 实际业务处理函数
 */
const withMiddleware = (
  middlewares: Middleware[],
  handler: (
    data: unknown,
    context: functions.https.CallableContext,
    state: Record<string, unknown>
  ) => Promise<unknown> | unknown
) => {
  return functions.https.onCall(async (data, context) => {
    const state = {};
    // 依次执行所有中间件
    for (const middleware of middlewares) {
      const error = await middleware(data, context, state);
      if (error) throw error;
    }
    // 中间件全部通过,执行业务逻辑
    return handler(data, context, state);
  });
};

2. 编写通用中间件

把身份校验、权限判断、参数校验、限流等通用逻辑抽为独立的中间件:

// 示例:登录状态校验中间件
const authMiddleware: Middleware = (data, context) => {
  if (!context.auth) {
    return new functions.https.HttpsError("unauthenticated", "请求需要登录身份");
  }
};

// 示例:管理员权限校验中间件
const adminPermissionMiddleware: Middleware = (data, context) => {
  if (context.auth?.token?.role !== "admin") {
    return new functions.https.HttpsError("permission-denied", "无管理员操作权限");
  }
};

// 示例:参数校验中间件
const createUserParamMiddleware: Middleware = (data) => {
  if (!data.phone || !data.username) {
    return new functions.https.HttpsError("invalid-argument", "缺少必填参数");
  }
};

3. 业务函数使用封装

直接用withMiddleware包装业务函数,按需传入需要的中间件即可:

// 创建用户接口:需要登录+管理员权限+参数校验
export const createUser = withMiddleware(
  [authMiddleware, adminPermissionMiddleware, createUserParamMiddleware],
  async (data, context, state) => {
    // 此处直接编写业务逻辑,无需再重复做前置校验
    return { success: true, userId: "xxx" };
  }
);

// 普通用户查询个人信息接口:只需要登录校验
export const getUserInfo = withMiddleware(
  [authMiddleware],
  async (data, context, state) => {
    return { user: context.auth };
  }
);

多可调用函数时的通用功能优化方案

当可调用函数数量较多时,可以通过以下方式进一步提升复用性、降低维护成本:

  • 中间件按用途分类归档:将所有通用中间件抽入独立目录(如/middlewares),按用途分为auth.ts、permission.ts、validator.ts、rateLimit.ts等,不同业务场景按需导入组合。
  • 封装常用中间件组合:如果大量函数需要相同的中间件链条,直接将组合封装为独立的包装器,避免每个函数重复编写中间件数组:
// 封装通用的管理员接口包装器,所有管理后台接口直接复用
const withAdminAuth = (handler: Parameters<typeof withMiddleware>[1]) => {
  return withMiddleware([authMiddleware, adminPermissionMiddleware, rateLimitMiddleware], handler);
};

// 管理端接口直接使用包装器即可,无需重复声明中间件
export const deleteUser = withAdminAuth(async (data) => {
  // 业务逻辑
});
export const updateSystemConfig = withAdminAuth(async (data) => {
  // 业务逻辑
});
  • 支持状态透传:中间件处理后的数据(如查询到的用户完整信息、权限配置等)可以存入state参数透传给后续中间件和业务函数,避免重复查询数据库。

内容的提问来源于stack exchange,提问作者Johnny Oshika

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 13:36:04