send method
Sends an HTTP request and asynchronously returns the response.
Implementation
@override
Future<StreamedResponse> send(BaseRequest request) async {
  if (_isClosed) {
    throw ClientException(
        'HTTP request failed. Client is already closed.', request.url);
  }
  final bodyBytes = await request.finalize().toBytes();
  try {
    final response = await _fetch(
      '${request.url}'.toJS,
      RequestInit(
        method: request.method,
        body: bodyBytes.isNotEmpty ? bodyBytes.toJS : null,
        credentials: withCredentials ? 'include' : 'same-origin',
        headers: {
          if (request.contentLength case final contentLength?)
            'content-length': contentLength,
          for (var header in request.headers.entries)
            header.key: header.value,
        }.jsify()! as HeadersInit,
        signal: _abortController.signal,
        redirect: request.followRedirects ? 'follow' : 'error',
      ),
    ).toDart;
    final contentLengthHeader = response.headers.get('content-length');
    final contentLength = contentLengthHeader != null
        ? int.tryParse(contentLengthHeader)
        : null;
    if (contentLength == null && contentLengthHeader != null) {
      throw ClientException(
        'Invalid content-length header [$contentLengthHeader].',
        request.url,
      );
    }
    final headers = <String, String>{};
    (response.headers as _IterableHeaders)
        .forEach((String value, String header, [JSAny? _]) {
      headers[header.toLowerCase()] = value;
    }.toJS);
    return StreamedResponseV2(
      _readBody(request, response),
      response.status,
      headers: headers,
      request: request,
      contentLength: contentLength,
      url: Uri.parse(response.url),
      reasonPhrase: response.statusText,
    );
  } catch (e, st) {
    _rethrowAsClientException(e, st, request);
  }
}