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 (_isClosed) {
    throw ClientException(
        'HTTP request failed. Client is already closed.', request.url);
  }

  final engine = _engine ?? CronetEngine.build();
  _engine = engine;

  if (engine._isClosed) {
    throw ClientException(
        'HTTP request failed. CronetEngine is already closed.', request.url);
  }

  final stream = request.finalize();
  final body = await stream.toBytes();
  final responseCompleter = Completer<StreamedResponse>();

  final builder = engine._engine.newUrlRequestBuilder(
    request.url.toString().toJString(),
    jb.UrlRequestCallbackProxy.new1(
        _urlRequestCallbacks(request, responseCompleter)),
    _executor,
  )..setHttpMethod(request.method.toJString());

  var headers = request.headers;
  if (body.isNotEmpty &&
      !headers.keys.any((h) => h.toLowerCase() == 'content-type')) {
    // Cronet requires that requests containing upload data set a
    // 'Content-Type' header.
    headers = {...headers, 'content-type': 'application/octet-stream'};
  }
  headers.forEach((k, v) => builder.addHeader(k.toJString(), v.toJString()));

  if (body.isNotEmpty) {
    builder.setUploadDataProvider(
        jb.UploadDataProviders.create2(body.toJByteBuffer()), _executor);
  }
  builder.build().start();
  return responseCompleter.future;
}