send method
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 ClientException
s.
Implementation
@override
Future<StreamedResponse> send(BaseRequest request) async {
if (_isClosed) {
throw ClientException(
'HTTP request failed. Client is already closed.', request.url);
}
_engine ??= CronetEngine.build();
final stream = request.finalize();
final body = await stream.toBytes();
final responseCompleter = Completer<StreamedResponse>();
final engine = _engine!._engine;
final builder = 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;
}