zino-hofmann / graphql-flutter

A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package.
https://zino-hofmann.github.io/graphql-flutter
MIT License
3.23k stars 613 forks source link

Exception: OperationException(linkException: ResponseFormatException(originalException: FormatException: Unexpected character (at character 1) #1350

Closed rrifafauzikomara closed 1 year ago

rrifafauzikomara commented 1 year ago

Postman.

Screenshot 2023-07-18 at 9 49 45 PM

example code of subs

Future<Map<String, dynamic>> subscription() async {
    try {
      final graphqlEndpoint = 'https://BASEURL/graphql';
      final subscriptionEndpoint =
          'wss://BASEURL/graphql/realtime?header=<EncodedHeader>&payload=e30=';
      var currentToken = _token();

      final HttpLink httpLink = HttpLink(
        graphqlEndpoint,
        defaultHeaders: {
          'Authorization': "Bearer $currentToken",
          'Sec-WebSocket-Protocol': GraphQLProtocol.graphqlWs,
        },
      );

      final WebSocketLink webSocketLink = WebSocketLink(
        subscriptionEndpoint,
        config: SocketClientConfig(
          autoReconnect: true,
          serializer: AppSyncRequest(uuid: 'uuid', token: currentToken),
          inactivityTimeout: const Duration(seconds: 60),
          headers: kIsWeb
              ? null
              : {
                  'Authorization': "Bearer $currentToken",
                  'Sec-WebSocket-Protocol': GraphQLProtocol.graphqlWs,
                },
          initialPayload: {
            'Authorization': currentToken,
          },
        ),
        subProtocol: GraphQLProtocol.graphqlWs,
      );

      final AuthLink authLink =
          AuthLink(getToken: () => 'Bearer $currentToken');

      final Link linkSplitted = authLink.split(
        (request) => request.isSubscription,
        webSocketLink,
        httpLink,
      );

      final graphQLCache = GraphQLCache();

      final client = GraphQLClient(
        link: linkSplitted,
        cache: graphQLCache,
        defaultPolicies: DefaultPolicies(
          watchQuery: Policies(fetch: FetchPolicy.noCache),
          query: Policies(fetch: FetchPolicy.noCache),
          mutate: Policies(fetch: FetchPolicy.noCache),
          subscribe: Policies(fetch: FetchPolicy.noCache),
        ),
        alwaysRebroadcast: true,
      );

      const checkOutSubscription = r'''
subscription MySubscription {
  onUpdateCheckout(userId: $userId) {
    createdAt
    checkoutId
    maxAllowedAmount
    maxAvailableAmount
    message
    state
    trancheId
  }
}
''';

      final options = SubscriptionOptions(
        document: gql(checkOutSubscription),
        variables: {
          "userId": "userId",
        },
      );

      final result = client.subscribe(options);
      Map<String, dynamic> data = {};
      result.listen(
        (event) {
          // not triggered
          data = event.data ?? {};
          if (data.isNotEmpty) {
            // not triggered
          }
        },
        cancelOnError: true,
      );

      return Future.value(data);
    } on Exception {
      rethrow;
    }
  }

logs

flutter: Request : {
  "userId": "244648"
}

flutter: Listen Subscription: Active

flutter: Listen Subscription Exception: OperationException(linkException: ResponseFormatException(originalException: FormatException: Unexpected character (at character 1)
Bad Request
^
, originalStackTrace: #0      _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
#1      _ChunkedJsonParser.parseNumber (dart:convert-patch/convert_patch.dart:1250:9)
#2      _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:915:22)
#3      _parseJson (dart:convert-patch/convert_patch.dart:35:10)
#4      JsonDecoder.convert (dart:convert/json.dart:610:36)
#5      JsonCodec.decode (dart:convert/json.dart:216:41)
#6      HttpLink._defaultHttpResponseDecoder (package:gql_http_link/src/link.dart:48:12)
#7      HttpLink._parseHttpResponse (package:gql_http_link/src/link.dart:117:53)
#8      HttpLink.request (package:gql_http_link/src/link.dart:78:28)
<asynchronous suspension>
), graphqlErrors: [])

flutter: Listen Subscription Data: {}

flutter: Listen Subscription Done
robertoestivill commented 1 year ago

You server is returning Bad Request and the library can not parse it. Not a library problem if you are not constructing a proper request.

vincenzopalazzo commented 1 year ago

Correct @robertoestivill

In any case, I am closing this due to the lack of minimal reproducible example

rrifafauzikomara commented 1 year ago

Hi @robertoestivill @vincenzopalazzo do u have any example of subs implementation? seems ur documentation not proper yet. Open an issue for that one as well here: https://github.com/zino-hofmann/graphql-flutter/issues/1349

Updated the example as well with postman screenshot

rrifafauzikomara commented 1 year ago

Updated.

Now I saw these on the log.

flutter: Initialising connection
flutter: Disconnected from websocket.
flutter: Initialising connection
flutter: Disconnected from websocket.
flutter: Initialising connection

Mean successfully connecting to subscription/websocket?

vincenzopalazzo commented 1 year ago

you may are setting the wrong ws protocol?

rrifafauzikomara commented 1 year ago

you may are setting the wrong ws protocol?

so this one (https://github.com/zino-hofmann/graphql-flutter/issues/1350#issuecomment-1640470400) still not connected to subscription/websocket?

vincenzopalazzo commented 1 year ago

the ws has different protocols

rrifafauzikomara commented 1 year ago

the ws has different protocols

hmm what u mean diff protocols? or do u have any idea what code should i check?

Coz basically, i just added this code.

final AuthLink authLink =
          AuthLink(getToken: () => 'Bearer $currentToken');

      final Link linkSplitted = authLink.split(
        (request) => request.isSubscription,
        webSocketLink,
        httpLink,
      );

and the result is this: https://github.com/zino-hofmann/graphql-flutter/issues/1350#issuecomment-1640470400

If I remove that like this one.

final Link linkSplitted = httpLink.split(
        (request) => request.isSubscription,
        webSocketLink,
        httpLink,
      );

I will got an error like this one: https://github.com/zino-hofmann/graphql-flutter/issues/1350#issue-1770000167

vincenzopalazzo commented 1 year ago

this https://github.com/zino-hofmann/graphql-flutter/pull/1206 should have a basic configuration of the ws, also please check the documentation and also research about grahql ws protocols

rrifafauzikomara commented 1 year ago

let me check ur example: https://github.com/zino-hofmann/graphql-flutter/tree/main/examples/starwars

idk why prev i dont see it.

rrifafauzikomara commented 1 year ago

Hi, @vincenzopalazzo @robertoestivill have a question.

In Postman, if I don't send a Message by clicked the Send button after successfully connected to the wss. I also can't get the data. The result is the same as this one (https://github.com/zino-hofmann/graphql-flutter/issues/1350#issuecomment-1640470400), only successfully connected or disconnected.

Screenshot Postman:

Screenshot 2023-07-19 at 1 05 14 AM

Message from Postman:

{
  "id": "{{$randomUUID}}",
  "payload": {
    "data": "{\"query\":\"subscription updateCheckout { onUpdateCheckout(userId: \\\"{{userId}}\\\") { userId createdAt amount checkoutId maxAllowedAmount maxAvailableAmount message state trancheId }}\"}",
    "extensions": {
      "authorization": {
        "Authorization": "{{cognitoIdToken}}",
        "host": "{{apiHost}}"
      }
    }
  },
  "type": "start"
}

Schema from AWS.

subscription MySubscription {
  onUpdateCheckout(userId: $userId) {
    createdAt
    checkoutId
    maxAllowedAmount
    maxAvailableAmount
    message
    state
    trancheId
  }
}

So my question is, how can I send a Message from the app side using this package?