send method
Future<StreamedResponse>
send(
- BaseRequest request, {
- CancellationToken? cancellationToken,
override
Sends an HTTP request and asynchronously returns the response.
Implementation
@override
Future<StreamedResponse> send(
BaseRequest request, {
CancellationToken? cancellationToken,
}) async {
if (cancellationToken?.isCancelled ?? false) {
throw cancellationToken!.exception!;
} else if (_isClosed) {
throw ClientException(
'HTTP request failed. Client is already closed.', request.url);
}
XMLHttpRequest? xhr = XMLHttpRequest();
final completer = CancellableCompleter<StreamedResponse>.sync(
cancellationToken,
onCancel: () {
_xhrs.remove(xhr);
xhr.abort();
},
);
unawaited(request.finalize().toBytes().then((bytes) async {
// Don't continue if the request has been cancelled at this point
if (cancellationToken?.isCancelled ?? false) return;
// Prepare the request
_xhrs.add(xhr);
xhr
..open(request.method, '${request.url}', true)
..responseType = 'arraybuffer'
..withCredentials = withCredentials;
for (var header in request.headers.entries) {
xhr.setRequestHeader(header.key, header.value);
}
// Prepare the response handler
unawaited(xhr.onLoad.first.then((_) {
if (xhr.responseHeaders['content-length'] case final contentLengthHeader
when contentLengthHeader != null &&
!_digitRegex.hasMatch(contentLengthHeader)) {
completer.completeError(ClientException(
'Invalid content-length header [$contentLengthHeader].',
request.url,
));
return;
}
var body = (xhr.response as JSArrayBuffer).toDart.asUint8List();
var responseUrl = xhr.responseURL;
var url = responseUrl.isNotEmpty ? Uri.parse(responseUrl) : request.url;
completer.complete(StreamedResponseV2(
ByteStream.fromBytes(body),
xhr.status,
contentLength: body.length,
request: request,
url: url,
headers: xhr.responseHeaders,
reasonPhrase: xhr.statusText,
));
_xhrs.remove(xhr);
}));
// Prepare the error handler
unawaited(xhr.onError.first.then((_) {
// Unfortunately, the underlying XMLHttpRequest API doesn't expose any
// specific information about the error itself.
completer.completeError(
ClientException('XMLHttpRequest error.', request.url),
StackTrace.current,
);
_xhrs.remove(xhr);
}));
// Send the request
xhr.send(bytes.toJS);
}));
return completer.future;
}