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

Flutter连接AWS AppSync订阅时出现DuplicatedOperationError问题

Flutter连接AWS AppSync订阅触发DuplicatedOperationError且无法接收事件

我通过Flutter前端使用graphql_flutter库连接AWS AppSync GraphQL API,查询(Queries)和突变(Mutations)功能均正常,也能成功建立订阅所需的WebSocket连接。但当graphql_flutter发送如下start消息尝试订阅时:

{
  "type": "start",
  "id": "061bf284-c738-4a83-96e9-c8cf4b17369e",
  "payload": {
    "data": "{\"query\":\"subscription TransportChanged {\n  transportChange {\n    id\n    __typename\n  }\n  __typename\n}\"\,\"variables\":{}}",
    "extensions": {
      "authorization": {
        "Authorization": "base64encodedAuthorizationHeader",
        "host": "actual_api.appsync-api.eu-central-1.amazonaws.com"
      }
    }
  }
}

会收到错误响应:

{
  "id": "061bf284-c738-4a83-96e9-c8cf4b17369e",
  "type": "error",
  "payload": {
    "errors": [
      {
        "errorType": "DuplicatedOperationError",
        "message": "Duplicated operation with id 061bf284-c738-4a83-96e9-c8cf4b17369e"
      }
    ]
  }
}

随后会收到start_ack响应,但无法通过该连接接收任何订阅事件:

{
  "id": "061bf284-c738-4a83-96e9-c8cf4b17369e",
  "type": "start_ack"
}

我已经通过AWS AppSync QueryConsole测试过订阅功能,确认服务端正常,问题应该出在本地配置。


GraphQL客户端配置代码

var authSession = context.read<AppUser>().getAuthSessionFromState();
final String? authenticationToken =
    context.watch<AppUser>().authenticationToken;
Link link;
final HttpLink httpLink = HttpLink(
  graphqlUrl,
);

if (authenticationToken != null && authenticationToken.isNotEmpty) {
  final AuthLink authLink = AuthLink(
      getToken: () async => authenticationToken,
      headerKey: 'Authorization');
  graphQLClientIsAuthenticated = true;
  currentToken = authenticationToken;
  _tokenExpiry = authSession?.userPoolTokens?.idToken.claims.expiration;

  String toBase64(Map data) => base64.encode(utf8.encode(jsonEncode(data)));

  final authHeader = {
    "Authorization": authenticationToken,
    "host": graphqlHost,
  };

  final encodedHeader = toBase64(authHeader);

  final WebSocketLink wsLink = WebSocketLink(
    "$graphqlRealTimeUrl?header=$encodedHeader&payload=e30=",
    config: SocketClientConfig(
      serializer: AppSyncRequest(
          authHeader: authHeader),
      inactivityTimeout: const Duration(seconds: 60),
    ),
  );
  link = Link.split((request) => request.isSubscription,
      authLink.concat(wsLink), authLink.concat(httpLink));
} else {
  link = httpLink;
}

AppSyncRequest序列化器实现

import 'dart:convert';

import 'package:gql/language.dart' show printNode;
import 'package:graphql_flutter/graphql_flutter.dart';

class AppSyncRequest extends RequestSerializer {
  final Map<String, dynamic> authHeader;

  const AppSyncRequest({
    required this.authHeader,
  });

  @override
  Map<String, dynamic> serializeRequest(Request request) => {
        "data": jsonEncode({
          "query": printNode(request.operation.document),
          "variables": request.variables.isEmpty?null: request.variables,
        }),
        "extensions": {
          "authorization": this.authHeader,
        }
      };
}

我已经排查过网络问题,排除了这类原因,求帮忙定位问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 19:10:04