request method
Future
request(
- String requestUrl,
- String method, {
- String? body,
- Map<
String, List< ? queryParams,String> > - Media? uploadMedia,
- UploadOptions? uploadOptions,
- DownloadOptions? downloadOptions = client_requests.DownloadOptions.metadata,
Sends a HTTPRequest using method
(usually GET or POST) to requestUrl
using the specified queryParams
. Optionally include a
body
and/or uploadMedia
in the request.
If uploadMedia
was specified downloadOptions
must be
client_requests.DownloadOptions.Metadata
or null
.
If downloadOptions
is client_requests.DownloadOptions.Metadata
the
result will be decoded as JSON.
If downloadOptions
is null
the result will be a Future completing with
null
.
Otherwise the result will be downloaded as a client_requests.Media
Implementation
Future request(
String requestUrl,
String method, {
String? body,
Map<String, List<String>>? queryParams,
client_requests.Media? uploadMedia,
client_requests.UploadOptions? uploadOptions,
client_requests.DownloadOptions? downloadOptions =
client_requests.DownloadOptions.metadata,
}) async {
if (uploadMedia != null &&
downloadOptions != client_requests.DownloadOptions.metadata) {
throw ArgumentError(
'When uploading a [Media] you cannot download a '
'[Media] at the same time!',
);
}
client_requests.ByteRange? downloadRange;
if (downloadOptions is client_requests.PartialDownloadOptions &&
!downloadOptions.isFullDownload) {
downloadRange = downloadOptions.range;
}
queryParams = queryParams?.cast<String, List<String>>();
var response = await _request(requestUrl, method, body, queryParams,
uploadMedia, uploadOptions, downloadOptions, downloadRange);
response = await validateResponse(response);
if (downloadOptions == null) {
// If no download options are given, the response is of no interest
// and we will drain the stream.
return response.stream.drain();
} else if (downloadOptions == client_requests.DownloadOptions.metadata) {
// Downloading JSON Metadata
final stringStream = _decodeStreamAsText(response);
if (stringStream == null) {
throw client_requests.ApiRequestError(
'Unable to read response with content-type '
"${response.headers['content-type']}.",
);
}
final bodyString = await stringStream.join();
if (bodyString.isEmpty) return null;
return json.decode(bodyString);
}
// Downloading Media.
final contentType = response.headers['content-type'];
if (contentType == null) {
throw client_requests.ApiRequestError(
"No 'content-type' header in media response.");
}
int? contentLength;
if (response.headers['content-length'] != null) {
contentLength = int.tryParse(response.headers['content-length']!);
}
if (downloadRange != null) {
if (contentLength != downloadRange.length) {
throw client_requests.ApiRequestError(
'Content length of response does not match requested range length.',
);
}
if (!isWeb) {
// TODO(kevmoo) on the web, should check access-control-expose-headers
// but this is easy for now
final contentRange = response.headers[_contentRangeHeader];
final expected = 'bytes ${downloadRange.start}-${downloadRange.end}/';
if (contentRange == null || !contentRange.startsWith(expected)) {
throw client_requests.ApiRequestError(
'Attempting partial '
"download but got invalid '$_contentRangeHeader' header "
'(was: $contentRange, expected: $expected).',
);
}
}
}
return client_requests.Media(response.stream, contentLength,
contentType: contentType);
}