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

NestJS Resolver中mergeInfo不可用,如何实现GraphQL请求代理?

Answer

问题分析

你遇到的核心问题是mergeInfo仅在**Schema Stitching(Schema拼接)**场景下才会被注入到info对象中,而当前你的NestJS GraphQL模块配置没有启用Schema Stitching,所以无法访问info.mergeInfo。下面提供两种可行的解决思路:


方案一:启用Schema Stitching,让mergeInfo可用

要让mergeInfo出现在resolver的info参数里,你需要手动将本地Schema和远程Schema通过Schema Stitching合并,这样GraphQL工具链会自动注入mergeInfo对象。

步骤1:安装依赖

首先安装Schema Stitching所需的工具包:

npm install @graphql-tools/stitch @graphql-tools/schema

步骤2:修改GraphQLModule配置

调整forRootAsync的工厂函数,手动构建并合并本地与远程Schema:

import { stitchSchemas } from '@graphql-tools/stitch';
import { buildSchema } from 'type-graphql';
// 导入你的本地Resolver
import { CarResolver } from './car.resolver';

GraphQLModule.forRootAsync({
 imports: [CarModule],
 inject: [CarService],
 useFactory: async (mainAppService: MainAppService) => {
   // 构建本地Schema(如果是Code First模式)
   const localSchema = await buildSchema({
     resolvers: [CarResolver],
     typePaths: ['./**/*.graphql'],
   });

   // 获取你已经定义好的远程Schema
   const remoteCarSchema = await fetchRemoteSchema();

   // 拼接本地与远程Schema
   const mergedSchema = stitchSchemas({
     subschemas: [
       { schema: localSchema },
       { schema: remoteCarSchema },
     ],
   });

   return {
     context: async ({ req }) => ({ userId: 1 }),
     definitions: { outputAs: 'interface', path: '../../myschema.gql' },
     schema: mergedSchema, // 使用拼接后的Schema
   };
 },
}),

步骤3:正常使用delegateToSchema

现在你的getCar resolver里就能正常访问info.mergeInfo了,原来的代码无需修改即可运行。


方案二:更简便的代理方式——使用wrapSchema

如果不想手动写delegateToSchema逻辑,你可以用wrapSchema直接创建一个可自动代理请求的远程Schema,再和本地Schema合并,无需自定义Resolver。

步骤1:修改远程Schema获取逻辑

更新fetchRemoteSchema函数,返回一个包裹后的Schema:

import { wrapSchema } from '@graphql-tools/wrap';

const fetchRemoteSchema = async (): Promise<GraphQLSchema> => {
 const http = new HttpLink({ fetch: nodeFetch, uri: process.env.CAR_GRAPHQL_URL });
 const link = setContext((_, prevContext) => ({
   headers: { Authorization: `Basic ${process.env.CAR_BASIC_AUTH_TOKEN}` },
 })).concat(http);
 
 const remoteSchema = await introspectSchema(link);

 // 包裹Schema,自动处理请求代理
 return wrapSchema({
   schema: remoteSchema,
   link,
   // 可选:添加transforms来修改请求(比如参数映射)
   transforms: [
     {
       transformRequest(request) {
         // 将context中的userId映射为远程请求的id参数
         if (request.operationName === 'car') {
           return {
             ...request,
             variables: { id: request.context.userId },
           };
         }
         return request;
       },
     },
   ],
 });
};

步骤2:合并Schema到NestJS配置

在GraphQLModule中合并本地和包裹后的远程Schema:

import { mergeSchemas } from '@graphql-tools/schema';

GraphQLModule.forRootAsync({
 imports: [CarModule],
 inject: [CarService],
 useFactory: async (mainAppService: MainAppService) => {
   const localSchema = await buildSchema({
     resolvers: [CarResolver],
     typePaths: ['./**/*.graphql'],
   });
   const remoteCarSchema = await fetchRemoteSchema();

   // 合并两个Schema
   const mergedSchema = mergeSchemas({
     schemas: [localSchema, remoteCarSchema],
   });

   return {
     context: async ({ req }) => ({ userId: 1 }),
     definitions: { outputAs: 'interface', path: '../../myschema.gql' },
     schema: mergedSchema,
   };
 },
}),

优势

这种方式下,如果本地Schema的字段定义和远程一致,你甚至不需要写getCar resolver——合并后的Schema会自动把请求转发到远程服务器,大大简化了代码。


额外建议

  • 如果你使用的是NestJS的Code First模式,确保buildSchema正确导入了你的Resolver和类型。
  • 对于多服务的复杂场景,Apollo Federation也是一个可选方案,但需要远程GraphQL服务器支持Federation规范,配置成本相对更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 12:39:08