send method

  1. @override
Future<ResponseOptions> send(
  1. RequestOptions options
)
override

Implementation

@override
Future<ResponseOptions> send(RequestOptions options) async {
  if (options.cancelToken?.isCancelled == true) {
    throw RequestCancelledException(options.cancelToken!.reason!);
  }

  final xhr = html.HttpRequest();
  final url = options.uri.toString();

  final completer = Completer<ResponseOptions>();

  xhr
    ..open(options.method, url, async: true)
    ..responseType = 'text';

  // timeout (ms)
  if (options.timeout != null) {
    xhr.timeout = options.timeout!.inMilliseconds;
  }

  // headers
  options.headers.forEach((k, v) => xhr.setRequestHeader(k, v));

  // events
  xhr.onError.listen((_) {
    if (!completer.isCompleted) {
      completer.completeError(NetworkException("Network error"));
    }
  });
  xhr.onTimeout.listen((_) {
    if (!completer.isCompleted) {
      completer.completeError(QuickTimeoutException());
    }
  });
  xhr.onReadyStateChange.listen((_) {
    if (xhr.readyState == html.HttpRequest.DONE && !completer.isCompleted) {
      final status = xhr.status;
      final ct = xhr.getResponseHeader('content-type') ?? '';
      final txt = xhr.responseText ?? '';
      dynamic data;
      if (ct.contains('application/json')) {
        try {
          data = jsonDecode(txt);
        } catch (_) {
          data = txt;
        }
      } else {
        data = txt.isEmpty ? null : txt;
      }
      completer.complete(ResponseOptions(
        statusCode: status!,
        data: data,
        requestOptions: options,
      ));
    }
  });

  // cancel
  if (options.cancelToken != null) {
    // Basit iptal: token tetiklenirse abort
    unawaited(_watchCancel(options.cancelToken!, xhr, completer));
  }

  // body
  dynamic sendData;
  if (options.body != null) {
    if (options.body is String) {
      sendData = options.body as String;
    } else if (options.body is List<int>) {
      sendData = html.Blob([options.body as List<int>]);
    } else {
      // JSON
      final hasCT = options.headers.keys.any(
        (k) => k.toLowerCase() == 'content-type',
      );
      if (!hasCT) {
        xhr.setRequestHeader('Content-Type', 'application/json');
      }
      sendData = jsonEncode(options.body);
    }
  }

  try {
    xhr.send(sendData);
  } catch (e) {
    if (!completer.isCompleted) {
      completer.completeError(NetworkException(e.toString()));
    }
  }

  return completer.future;
}