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

NestJS GraphQL订阅:如何获取上下文并向解析器/拦截器传参?

解决NestJS订阅拦截器获取上下文及用户信息的问题

针对graphql-ws方案

  1. 在onConnect中处理授权并传递用户信息
    在订阅配置的onConnect回调里,解析授权头获取用户后,需要返回用户对象,这个对象会自动注入到GraphQL的执行上下文中:

    subscriptions: {
      'graphql-ws': {
        path: '/apis/event-service/graphql',
        onConnect: async (ctx) => {
          // 从连接参数中获取授权头
          const authHeader = ctx.connectionParams?.Authorization || ctx.connectionParams?.authorization;
          if (!authHeader) {
            throw new Error('未授权');
          }
          // 示例:解析token获取用户
          const user = await verifyToken(authHeader.split(' ')[1]);
          // 返回用户,会被挂载到GraphQL上下文
          return { user };
        },
      },
    }
    
  2. 拦截器中获取上下文和用户
    在拦截器的intercept方法里,通过GqlExecutionContext直接获取上下文,此时上下文已包含onConnect返回的用户:

    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
      const gqlCtx = GqlExecutionContext.create(context);
      // 获取graphql-ws传递的上下文
      const { user } = gqlCtx.getContext();
      // 将用户挂载到解析器可访问的位置(比如上下文的req对象)
      gqlCtx.getContext().req.user = user;
      return next.handle();
    }
    

针对subscriptions-transport-ws方案

  1. 在onConnect中处理授权并挂载用户到连接上下文
    该库的连接上下文需要挂载到connection.context上,后续才能在拦截器中获取:

    subscriptions: {
      'subscriptions-transport-ws': {
        path: '/apis/event-service/graphql',
        onConnect: async (connectionParams, webSocket, context) => {
          const authHeader = connectionParams.Authorization || connectionParams.authorization;
          if (!authHeader) {
            throw new Error('未授权');
          }
          const user = await verifyToken(authHeader.split(' ')[1]);
          // 将用户挂载到连接上下文
          context.connection.context.user = user;
          return context.connection.context;
        },
      },
    }
    
  2. 拦截器中获取上下文和用户
    需要通过switchToWs().getClient()获取连接客户端,再从其context属性中拿到用户:

    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
      const gqlCtx = GqlExecutionContext.create(context);
      // 获取subscriptions-transport-ws的客户端连接上下文
      const wsClient = gqlCtx.switchToWs().getClient();
      const { user } = wsClient.context;
      // 将用户挂载到解析器可访问的位置
      gqlCtx.getContext().req.user = user;
      return next.handle();
    }
    

关键注意点

  • 两种库的上下文传递机制完全不同,必须对应正确的获取方式,否则会返回undefined。
  • 拦截器需确保是全局拦截器,或被正确应用到订阅解析器所在的模块/解析器上。
  • 在onConnect中必须完成用户信息的解析和挂载/返回,否则后续拦截器无法获取到用户数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 07:10:21