From aa5148c10a507046f66ce40fcfdd4ce04aacbcaa Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 30 Sep 2024 10:12:49 -0700 Subject: [PATCH 1/2] Handled errors --- .../dataconnect/connector/mutations.gql | 2 ++ .../lib/src/network/grpc_transport.dart | 3 ++ .../lib/src/network/rest_transport.dart | 7 +++++ .../test/src/network/rest_transport_test.dart | 28 +++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/connector/mutations.gql b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/connector/mutations.gql index 8f186103a4f6..1e4194f7999b 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/connector/mutations.gql +++ b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/connector/mutations.gql @@ -21,6 +21,7 @@ mutation addDateAndTimestamp($date: Date!, $timestamp: Timestamp!) @auth(level: mutation seedMovies @auth(level: PUBLIC) { the_matrix: movie_insert( data: { + id: "09d5f835656c467787347668bbb44522" title: "The Matrix" releaseYear: 1999 genre: "Sci-Fi" @@ -70,6 +71,7 @@ mutation thing($title: Any! = "ABC") @auth(level: PUBLIC) { mutation seedData @auth(level: PUBLIC) { the_matrix: movie_insert( data: { + id: "09d5f835656c467787347668bbb44522" title: "The Matrix" releaseYear: 1999 genre: "Action" diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart index 3f43ec6273b0..acbe34e91668 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart @@ -137,6 +137,9 @@ class GRPCTransport implements DataConnectTransport { try { response = await stub.executeMutation(request, options: CallOptions(metadata: await getMetadata())); + if (response.errors.isNotEmpty) { + throw Exception(response.errors); + } return deserializer(jsonEncode(response.data.toProto3Json())); } on Exception catch (e) { throw DataConnectError(DataConnectErrorCode.other, diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart index 8a7b1931f530..3843bdd3b19a 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart @@ -112,6 +112,13 @@ class RestTransport implements DataConnectTransport { ? DataConnectErrorCode.unauthorized : DataConnectErrorCode.other, "Received a status code of ${r.statusCode} with a message '${message}'"); + } else { + Map bodyJson = + jsonDecode(r.body) as Map; + if (bodyJson.containsKey("errors")) { + throw DataConnectError( + DataConnectErrorCode.other, bodyJson['errors'].toString()); + } } /// The response we get is in the data field of the response diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart index 9489d0247271..4720ac78ece7 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart @@ -223,5 +223,33 @@ void main() { body: anyNamed('body'), )).called(1); }); + test('invokeOperation should throw an error if the server throws one', + () async { + final mockResponse = http.Response(""" +{ + "data": {}, + "errors": [ + { + "message": "SQL query error: pq: duplicate key value violates unique constraint movie_pkey", + "locations": [], + "path": [ + "the_matrix" + ], + "extensions": null + } + ] +}""", 200); + when(mockHttpClient.post(any, + headers: anyNamed('headers'), body: anyNamed('body'))) + .thenAnswer((_) async => mockResponse); + + final deserializer = (String data) => 'Deserialized Data'; + + expect( + () => transport.invokeOperation( + 'testQuery', deserializer, null, null, 'executeQuery'), + throwsA(isA()), + ); + }); }); } From 829b54f06fb864d9eb6084fd476bdc0b5c817de9 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 30 Sep 2024 12:01:33 -0700 Subject: [PATCH 2/2] Only throw errors if errors is not empty --- .../firebase_data_connect/lib/src/network/rest_transport.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart index 3843bdd3b19a..727f5739c2d5 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart @@ -115,7 +115,8 @@ class RestTransport implements DataConnectTransport { } else { Map bodyJson = jsonDecode(r.body) as Map; - if (bodyJson.containsKey("errors")) { + if (bodyJson.containsKey("errors") && + (bodyJson['errors'] as List).isNotEmpty) { throw DataConnectError( DataConnectErrorCode.other, bodyJson['errors'].toString()); }