fetch method
Future<ResponseBody>
fetch(
- RequestOptions options,
- Stream<
List< ? requestStream,int> > - Future? cancelFuture
override
We should implement this method to make real http requests.
options
: The request options
requestStream
The request stream, It will not be null
only when http method is one of "POST","PUT","PATCH"
and the request body is not empty.
We should give priority to using requestStream(not options.data) as request data.
because supporting stream ensures the onSendProgress
works.
cancelFuture
: When cancelled the request, cancelFuture
will be resolved!
you can listen cancel event by it, for example:
cancelFuture?.then((_)=>print("request cancelled!"))
cancelFuture
: will be null when the request is not set CancelToken.
Implementation
@override
Future<ResponseBody> fetch(
RequestOptions options,
Stream<List<int>>? requestStream,
Future? cancelFuture,
) async {
if (_closed) {
throw Exception(
"Can't establish connection after [HttpClientAdapter] closed!");
}
var _httpClient = _configHttpClient(cancelFuture, options.connectTimeout);
Future requestFuture = _httpClient.openUrl(options.method, options.uri);
void _throwConnectingTimeout() {
throw DioError(
request: options,
error: 'Connecting timed out [${options.connectTimeout}ms]',
type: DioErrorType.CONNECT_TIMEOUT,
);
}
late HttpClientRequest request;
try {
if (options.connectTimeout > 0) {
request = await requestFuture
.timeout(Duration(milliseconds: options.connectTimeout));
} else {
request = await requestFuture;
}
//Set Headers
options.headers.forEach((k, v) => request.headers.set(k, v));
} on SocketException catch (e) {
if (e.message.contains('timed out')) _throwConnectingTimeout();
rethrow;
} on TimeoutException {
_throwConnectingTimeout();
}
if (options.method != 'GET' && requestStream != null) {
// Transform the request data
await request.addStream(requestStream);
}
Future future = request.close();
if (options.connectTimeout > 0) {
future = future.timeout(Duration(milliseconds: options.connectTimeout));
}
late HttpClientResponse responseStream;
try {
responseStream = await future;
} on TimeoutException {
_throwConnectingTimeout();
}
// https://github.com/dart-lang/co19/issues/383
var stream =
responseStream.transform<Uint8List>(StreamTransformer.fromHandlers(
handleData: (data, sink) {
sink.add(Uint8List.fromList(data));
},
));
var headers = <String, List<String>>{};
responseStream.headers.forEach((key, values) {
headers[key] = values;
});
return ResponseBody(
stream,
responseStream.statusCode,
headers: headers,
isRedirect:
responseStream.isRedirect || responseStream.redirects.isNotEmpty,
redirects: responseStream.redirects
.map((e) => RedirectRecord(e.statusCode, e.method, e.location))
.toList(),
statusMessage: responseStream.reasonPhrase,
);
}