新版@apollo/server与graphql-tools中Schema拼接与自省问题解决
问题:升级GraphQL网关后远程Schema拼接成功但API返回null
版本升级清单
| 包名 | 旧版本 | 目标版本 |
|---|---|---|
| graphql-tools | V4.0.5 | V9.0.0 |
| apollo-server-express | V2.7.2 | @apollo/server V4.8.0 |
| express | V4.17.1 | V4.18.2 |
| graphql | V14.4.2 | V16.7.1 |
核心问题
旧版本通过introspectSchema+makeRemoteExecutableSchema+mergeSchemas实现远程Schema拼接,升级后这两个核心函数废弃,改用@graphql-tools/wrap和@graphql-tools/executor-http相关API后,Schema拼接成功且能接收introspection查询,但调用接口时返回null。根源在于:
mergeSchemas在v9中对subschema执行器的支持不足,需改用stitchSchemas- 请求上下文(如身份头)未正确传递给远程服务
- Apollo Server v4的上下文传递逻辑需适配新的执行器体系
修复步骤
1. 替换mergeSchemas为stitchSchemas
graphql-tools v9中,mergeSchemas已被stitchSchemas替代,后者更适配subschema的执行器配置:
// 导入替换 import { stitchSchemas } from '@graphql-tools/stitch'; // 修改createSchema函数 const createSchema = async () => { const remoteSchemas = []; for (let service of servicesList) { const retSchema = await utils.getRemoteSchema(service.url); remoteSchemas.push(retSchema); } // 用stitchSchemas替代mergeSchemas,注意参数名改为subschemas return stitchSchemas({ subschemas: remoteSchemas, }); };
2. 修复getRemoteSchema实现(含上下文传递)
旧代码中的setContext逻辑需要迁移到buildHTTPExecutor的配置中,确保请求头能传递给远程服务:
// 导入必要模块 import { buildHTTPExecutor } from '@graphql-tools/executor-http'; import { schemaFromExecutor } from '@graphql-tools/wrap'; import fetch from 'cross-fetch'; // 环境无fetch时需安装cross-fetch // 修改getRemoteSchema方法 getRemoteSchema: async (url) => { const remoteExecutor = buildHTTPExecutor({ endpoint: url, // 自定义fetch逻辑,用于传递请求头 fetch: async (uri, options) => { // 这里需要从当前请求上下文获取头信息,后续会和Apollo上下文关联 const context = options?.context; return fetch(uri, { ...options, headers: { ...options.headers, // 替换为你需要传递的头,比如身份令牌 Authorization: context?.req?.headers?.authorization, // 其他自定义请求头 }, }); }, }); const schema = await schemaFromExecutor(remoteExecutor); return { schema, executor: remoteExecutor, }; };
3. 适配Apollo Server v4的上下文传递
确保Apollo Server的上下文能传递到远程执行器:
const start = async () => { const app = express(); // 统一上下文生成逻辑 const createContext = async ({ req, connection }) => { let context = {}; if (req) { // 从request提取需要传递的信息,比如请求头 context = { req }; } else if (connection && connection.context) { context = connection.context; } return context; }; const schema = await createSchema(); const server = new ApolloServer({ schema, introspection: true, // 配置Apollo Server上下文 context: createContext, }); await server.start(); app.use( '/graphql', cors(), json(), expressMiddleware(server, { context: createContext, // 确保中间件使用相同上下文逻辑 }) ); // 启动服务 app.listen(4000, () => { console.log('Gateway running on http://localhost:4000/graphql'); }); };
4. 补全依赖安装
确认已安装所有必要依赖:
npm install @apollo/server express graphql @graphql-tools/stitch @graphql-tools/wrap @graphql-tools/executor-http cors cross-fetch
关键说明
stitchSchemas是graphql-tools v9官方推荐的Schema拼接方案,原生支持subschema的执行器和上下文传递- 远程执行器的
fetch配置是传递请求上下文的核心,必须确保当前请求的上下文能正确注入到远程调用中 - Apollo Server v4的
expressMiddleware需要显式配置上下文生成函数,确保和ApolloServer实例的上下文逻辑一致
内容的提问来源于stack exchange,提问作者Aman Kumar
相关产品推荐
相关产品推荐

