升级到Apollo v3后GraphQL订阅返回Must provide document错误求助
问题原因
- Apollo Server v3默认启用内置订阅处理逻辑,你手动基于
subscriptions-transport-ws创建的独立订阅服务和内置逻辑冲突,请求被内置逻辑拦截后无法获取到正确的查询文档参数,因此返回Must provide document错误。 - 你当前使用的
subscriptions-transport-ws包已经被官方废弃,和Apollo v3的适配存在参数解析兼容问题。
可行解决方案
方案1:继续使用subscriptions-transport-ws(适配旧客户端)
只需在ApolloServer构造配置中新增subscriptions: false关闭内置订阅逻辑,避免冲突即可,修改后的配置如下:
const apolloServer = new ApolloServer({ schema, subscriptions: false, // 新增这一行,关闭内置订阅处理 playground: false, resolverValidationOptions: { requireResolversForResolveType: false }, // 剩余原有配置保持不变 });
如果修改后仍然报错,可以在onOperation钩子中手动解析查询生成document对象:
首先从graphql包导入parse方法:
import { parse } from 'graphql';
然后修改onOperation逻辑:
onOperation: async (_message, params, ws) => { console.log(_message) // 手动补充document参数 if (!params.document) { params.document = parse(_message.payload.query) } return params; }
方案2:切换为Apollo v3官方推荐的graphql-ws包(推荐)
- 先安装新依赖:
npm install graphql-ws ws - 替换原有订阅服务创建逻辑:
// 新增导入 import { WebSocketServer } from 'ws'; import { useServer } from 'graphql-ws/lib/use/ws'; // ... 原有代码保持到创建httpServer、schema之后 // 删除原有SubscriptionServer相关代码,替换为以下内容: const wsServer = new WebSocketServer({ server: httpServer, path: '/subscriptions', }); const serverCleanup = useServer({ schema, execute, subscribe, onConnect: async (ctx) => { console.log('on Connect') return {} }, onSubscribe: async (ctx, msg) => { console.log(msg) // 原有onOperation的逻辑可在此处实现 } }, wsServer); // 修改ApolloServer配置 const apolloServer = new ApolloServer({ schema, subscriptions: false, // 关闭内置订阅 playground: false, resolverValidationOptions: { requireResolversForResolveType: false }, formatError: err => { console.log(err); return err; }, plugins: [{ async serverWillStart() { return { async drainServer() { await serverCleanup.dispose(); } }; } }], uploads: false, path: '/graphql' });
修改完成后重启服务即可正常触发订阅的subscribe resolver。
内容的提问来源于stack exchange,提问作者Jan Schweiger
相关产品推荐
相关产品推荐

