enableXhr method

JavascriptRuntime enableXhr()

Implementation

JavascriptRuntime enableXhr() {
  httpClient = httpClient ?? http.Client();
  dartContext[XHR_PENDING_CALLS_KEY] = [];

  Timer.periodic(Duration(milliseconds: 40), (timer) {
    // exits if there is no pending call to remote
    if (!hasPendingXhrCalls()) return;

    // collect the pending calls into a local variable making copies
    List<dynamic> pendingCalls = List<dynamic>.from(getPendingXhrCalls()!);
    // clear the global pending calls list
    clearXhrPendingCalls();

    // for each pending call, calls the remote http service
    pendingCalls.forEach((element) async {
      XhrPendingCall pendingCall = element as XhrPendingCall;
      HttpMethod eMethod = HttpMethod.values.firstWhere((e) =>
          e.toString().toLowerCase() ==
          ("HttpMethod.${pendingCall.method}".toLowerCase()));
      late http.Response response;
      switch (eMethod) {
        case HttpMethod.head:
          response = await httpClient!.head(
            Uri.parse(pendingCall.url!),
            headers: pendingCall.headers,
          );
          break;
        case HttpMethod.get:
          response = await httpClient!.get(
            Uri.parse(pendingCall.url!),
            headers: pendingCall.headers,
          );
          break;
        case HttpMethod.post:
          response = await httpClient!.post(
            Uri.parse(pendingCall.url!),
            body: (pendingCall.body is String)
                ? pendingCall.body
                : jsonEncode(pendingCall.body),
            headers: pendingCall.headers,
          );
          break;
        case HttpMethod.put:
          response = await httpClient!.put(
            Uri.parse(pendingCall.url!),
            body: (pendingCall.body is String)
                ? pendingCall.body
                : jsonEncode(pendingCall.body),
            headers: pendingCall.headers,
          );
          break;
        case HttpMethod.patch:
          response = await httpClient!.patch(
            Uri.parse(pendingCall.url!),
            body: (pendingCall.body is String)
                ? pendingCall.body
                : jsonEncode(pendingCall.body),
            headers: pendingCall.headers,
          );
          break;
        case HttpMethod.delete:
          response = await httpClient!.delete(
            Uri.parse(pendingCall.url!),
            headers: pendingCall.headers,
          );
          break;
      }
      // assuming request was successfully executed
      String responseText = utf8.decode(response.bodyBytes);
      try {
        responseText = jsonEncode(json.decode(responseText));
      } on Exception {}
      final xhrResult = XmlHttpRequestResponse(
        responseText: responseText,
        responseInfo:
            XhtmlHttpResponseInfo(statusCode: 200, statusText: "OK"),
      );

      final responseInfo = jsonEncode(xhrResult.responseInfo);
      //final responseText = xhrResult.responseText; //.replaceAll("\\n", "\\\n");
      final error = xhrResult.error;
      // send back to the javascript environment the
      // response for the http pending callback
      this.evaluate(
        "globalThis.xhrRequests[${pendingCall.idRequest}].callback($responseInfo, `$responseText`, $error);",
      );
    });
  });

  this.evaluate("""
  var xhrRequests = {};
  var idRequest = -1;
  function XMLHttpRequestExtension_send_native() {
    idRequest += 1;
    var cb = arguments[4];
    var context = arguments[5];
    xhrRequests[idRequest] = {
      callback: function(responseInfo, responseText, error) {
        cb(responseInfo, responseText, error);
      }
    };
    var args = [];
    args[0] = arguments[0];
    args[1] = arguments[1];
    args[2] = arguments[2];
    args[3] = arguments[3];
    args[4] = idRequest;
    sendMessage('SendNative', JSON.stringify(args));
  }
  """);

  final evalXhrResult = this.evaluate(xhrJsCode);

  if (_XHR_DEBUG) print('RESULT evalXhrResult: $evalXhrResult');

  this.onMessage('SendNative', (arguments) {
    try {
      String? method = arguments[0];
      String? url = arguments[1];
      dynamic headersList = arguments[2];
      String? body = arguments[3];
      int? idRequest = arguments[4];

      Map<String, String> headers = {};
      headersList.forEach((header) {
        // final headerMatch = regexpHeader.allMatches(value).first;
        // String? headerName = headerMatch.group(0);
        // String? headerValue = headerMatch.group(1);
        // if (headerName != null) {
        //   headers[headerName] = headerValue ?? '';
        // }
        String headerKey = header[0];
        headers[headerKey] = header[1];
      });
      (dartContext[XHR_PENDING_CALLS_KEY] as List<dynamic>).add(
        XhrPendingCall(
          idRequest: idRequest,
          method: method,
          url: url,
          headers: headers,
          body: body,
        ),
      );
    } on Error catch (e) {
      if (_XHR_DEBUG) print('ERROR calling sendNative on Dart: >>>> $e');
    } on Exception catch (e) {
      if (_XHR_DEBUG) print('Exception calling sendNative on Dart: >>>> $e');
    }
  });
  return this;
}