send method

  1. @override
Future<StreamedResponse> send(
  1. BaseRequest request
)

Sends an HTTP request and asynchronously returns the response.

Implementers should call BaseRequest.finalize to get the body of the request as a ByteStream. They shouldn't make any assumptions about the state of the stream; it could have data written to it asynchronously at a later point, or it could already be closed when it's returned. Any internal HTTP errors should be wrapped as ClientExceptions.

Implementation

@override
Future<StreamedResponse> send(BaseRequest request) async {
  if (_closed) {
    throw ClientException(
      'HTTP request failed. Client is already closed.',
      request.url,
    );
  }
  if (request.url.scheme != 'https') {
    throw ClientException(
      'Http2Client only supports https (got "${request.url.scheme}").',
      request.url,
    );
  }

  List<int>? bodyBytes;

  Future<StreamedResponse> attempt() async {
    final lease = await _poolFor(request.url).acquire();
    try {
      bodyBytes ??= await request.finalize().toBytes();
    } catch (_) {
      lease.release();
      rethrow;
    }
    try {
      return await _sendOverHttp2(lease, request, bodyBytes!);
    } catch (_) {
      lease.markFailed();
      lease.release();
      rethrow;
    }
  }

  return attempt()
      .catchError(
        (Object _) => attempt(),
        test: (error) => error is _ConnectionClosedByPeer,
      )
      .catchError(
        (Object error, StackTrace stackTrace) => Error.throwWithStackTrace(
          ClientException('$error', request.url),
          stackTrace,
        ),
        test: (error) => error is! ClientException,
      );
}