call<T> method

Future<HttpsCallableResult<T>> call<T>([
  1. dynamic data
])

Calls the function with the given data.

Implementation

Future<HttpsCallableResult<T>> call<T>([dynamic data]) async {
  assert(_debugIsValidParameterType(data), 'data must be json serialized');
  String encodedData;
  try {
    encodedData = json.encode({'data': data});
  } catch (e, st) {
    throw FirebaseFunctionsException(
      message: 'Data was not json encodeable',
      code: 'internal',
      details:
          '${options.timeout} millisecond timeout occurred on request to $_url with $data',
      stackTrace: st,
    );
  }
  final auth = FirebaseAuth.instanceFor(app: app);
  String? authToken;
  if (auth.currentUser != null) {
    authToken = await auth.currentUser!.getIdToken();
  }

  try {
    final response = await _client.post(
      _url,
      body: encodedData,
      headers: {
        'Content-Type': 'application/json',
        if (authToken != null) 'Authorization': 'Bearer $authToken',
        // TODO add back once installations is supported.
        // if (messagingToken != null)
        // 'Firebase-Instance-ID-Token': '$messagingToken',
        // if (appCheckToken != null)
        // 'X-Firebase-AppCheck': '$appCheckToken'
      },
    ).timeout(options.timeout);
    if (response.statusCode >= 200 && response.statusCode < 300) {
      Map<String, dynamic> body;
      try {
        body = json.decode(response.body.isEmpty ? '{}' : response.body)
            as Map<String, dynamic>;
      } catch (e, st) {
        throw FirebaseFunctionsException(
          message: 'Failed to parse json response',
          code: 'internal',
          details: 'Result body from http call was ${response.body}',
          stackTrace: st,
        );
      }
      if (!body.containsKey('data') && !body.containsKey('result')) {
        throw FirebaseFunctionsException(
          message: 'Response is missing data field',
          code: 'internal',
          details: 'Result body from http call was ${response.body}',
        );
      }
      // Result is for backwards compatibility
      final result = body['data'] ?? body['result'];

      return HttpsCallableResult(result);
    } else {
      Map<String, dynamic> details;
      try {
        details = json.decode(response.body);
      } catch (e) {
        // fine if we can't parse explicit error data
        details = {'details': response.body};
      }
      throw _errorForResponse(
        response.statusCode,
        details,
      );
    }
  } on TimeoutException catch (e, st) {
    throw FirebaseFunctionsException(
      message: 'Firebase functions timeout',
      code: 'deadline-exceeded',
      details:
          '${options.timeout} millisecond timeout occurred on request to $_url with $encodedData',
      stackTrace: st,
    );
  }
}