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

使用Ferry包时Flutter GraphQL Subscription无法生效如何解决?

核心问题

你遇到的卡在connection_init阶段的核心原因是 Ferry WebSocketLink使用的GraphQL订阅协议和Apollo Server端的协议不匹配:

  • Apollo Server v3及更高版本默认使用graphql-ws实现的新版订阅协议(对应Ferry中的GraphQLProtocol.graphqlTransportWs)
  • Ferry WebSocketLink如果不显式指定协议,部分版本会默认使用旧版subscriptions-transport-ws协议,导致服务端无法识别客户端发送的connection_init握手消息,不会返回connection_ack响应,整个订阅流程就会卡在握手阶段。

修复代码

你只需要在初始化WebSocketLink时显式指定和服务端匹配的协议即可:

var link = WebSocketLink(
      "ws://localhost:4000/graphql",
      initialPayload: {"subscriptionParam": arg},
      // 匹配Apollo Server默认的新版订阅协议
      protocol: GraphQLProtocol.graphqlTransportWs,
    );
var client = Client(link: link);
client.request(request).listen((data) {
      log(data.toString());
    }, onError: (error, stack) {
      log("Subscription error: " + error.toString());
    }); 

如果你使用的是Apollo Server v2或更早版本,服务端用的是旧版subscriptions-transport-ws协议,就把上面的协议参数换成GraphQLProtocol.subscriptionsTransportWs。

额外注意事项

  • 如果你需要在同一个Ferry Client中同时使用queries/mutations和subscriptions,不要直接把Client的链路设置为WebSocketLink,要使用SplitLink按操作类型分流:订阅请求走WebSocket链路,普通查询/变更走HTTP链路,示例如下:
final httpLink = HttpLink('http://localhost:4000/graphql');
final wsLink = WebSocketLink(
  "ws://localhost:4000/graphql",
  initialPayload: {"subscriptionParam": arg},
  protocol: GraphQLProtocol.graphqlTransportWs,
);

final splitLink = Link.split(
  (request) => request.isSubscription,
  wsLink,
  httpLink,
);

final client = Client(link: splitLink);
  • 如果你在Apollo Server端配置了订阅连接的onConnect校验钩子,需要确认你传递的initialPayload字段格式符合服务端的校验要求,否则也会导致握手被服务端拒绝。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 11:15:03