File tree Expand file tree Collapse file tree 5 files changed +97
-6
lines changed
plugins/native_dio_adapter Expand file tree Collapse file tree 5 files changed +97
-6
lines changed Original file line number Diff line number Diff line change 22
33## Unreleased
44
5- * None. *
5+ - Support request cancellation for native HTTP clients via use of ` AbortableRequest ` (introduced in http package from version 1.5.0)
66
77## 1.5.0
88
Original file line number Diff line number Diff line change @@ -23,7 +23,11 @@ class ConversionLayerAdapter implements HttpClientAdapter {
2323 Stream <Uint8List >? requestStream,
2424 Future <dynamic >? cancelFuture,
2525 ) async {
26- final request = await _fromOptionsAndStream (options, requestStream);
26+ final request = await _fromOptionsAndStream (
27+ options,
28+ requestStream,
29+ cancelFuture,
30+ );
2731 final response = await client.send (request);
2832 return response.toDioResponseBody (options);
2933 }
@@ -34,10 +38,12 @@ class ConversionLayerAdapter implements HttpClientAdapter {
3438 Future <BaseRequest > _fromOptionsAndStream (
3539 RequestOptions options,
3640 Stream <Uint8List >? requestStream,
41+ Future <dynamic >? cancelFuture,
3742 ) async {
38- final request = Request (
43+ final request = AbortableRequest (
3944 options.method,
4045 options.uri,
46+ abortTrigger: cancelFuture,
4147 );
4248
4349 request.headers.addAll (
Original file line number Diff line number Diff line change @@ -21,14 +21,15 @@ dependencies:
2121 sdk : flutter
2222
2323 dio : ^5.4.0
24- cupertino_http : ' >=1.0.0 < 3.0.0 '
25- cronet_http : ' >=0.4.0 <2.0.0 '
26- http : ^1.0 .0
24+ cupertino_http : ^2. 3.0
25+ cronet_http : ^1.5.0
26+ http : ^1.5 .0
2727
2828dev_dependencies :
2929 lints : ^2.0.0
3030 flutter_test :
3131 sdk : flutter
32+ async : # transitive
3233
3334platforms :
3435 android :
Original file line number Diff line number Diff line change 1+ import 'package:async/async.dart' show CancelableOperation;
12import 'package:http/http.dart' ;
23
34class CloseClientMock implements Client {
@@ -30,3 +31,38 @@ class ClientMock implements Client {
3031 throw UnimplementedError ();
3132 }
3233}
34+
35+ class AbortClientMock implements Client {
36+ bool isRequestCanceled = false ;
37+
38+ @override
39+ Future <StreamedResponse > send (BaseRequest request) async {
40+ final cancellable = CancelableOperation .fromFuture (
41+ Future <void >.delayed (const Duration (seconds: 5 )),
42+ );
43+
44+ if (request is Abortable ) {
45+ request.abortTrigger? .whenComplete (
46+ () {
47+ cancellable.cancel ();
48+ isRequestCanceled = true ;
49+ },
50+ );
51+ }
52+
53+ await cancellable.valueOrCancellation ();
54+
55+ if (cancellable.isCanceled) {
56+ throw AbortedError ();
57+ }
58+
59+ return StreamedResponse (Stream .fromIterable ([]), 200 );
60+ }
61+
62+ @override
63+ void noSuchMethod (Invocation invocation) {
64+ throw UnimplementedError ();
65+ }
66+ }
67+
68+ class AbortedError extends Error {}
Original file line number Diff line number Diff line change @@ -62,4 +62,52 @@ void main() {
6262
6363 expect (await resp.stream.length, 5 );
6464 });
65+
66+ test ('request cancellation' , () {
67+ final mock = AbortClientMock ();
68+ final cla = ConversionLayerAdapter (mock);
69+ final cancelToken = CancelToken ();
70+
71+ Future <void >.delayed (const Duration (seconds: 1 )).then (
72+ (value) {
73+ cancelToken.cancel ();
74+ },
75+ );
76+
77+ expectLater (
78+ () => cla.fetch (
79+ RequestOptions (path: '' ),
80+ null ,
81+ cancelToken.whenCancel,
82+ ),
83+ throwsA (isA <AbortedError >()),
84+ );
85+ });
86+
87+ test ('request cancellation with Dio' , () async {
88+ final mock = AbortClientMock ();
89+ final cla = ConversionLayerAdapter (mock);
90+ final dio = Dio ();
91+ dio.httpClientAdapter = cla;
92+
93+ final cancelToken = CancelToken ();
94+
95+ Future <void >.delayed (const Duration (seconds: 1 )).then (
96+ (value) {
97+ cancelToken.cancel ();
98+ },
99+ );
100+
101+ await expectLater (
102+ () => dio.get <ResponseBody >('' , cancelToken: cancelToken),
103+ throwsA (
104+ isA <DioException >().having (
105+ (e) => e.type,
106+ 'type' ,
107+ DioExceptionType .cancel,
108+ ),
109+ ),
110+ );
111+ expect (mock.isRequestCanceled, true );
112+ });
65113}
You can’t perform that action at this time.
0 commit comments