From 96e1ef032fe0e87ae87c4571ad39765c173e031c Mon Sep 17 00:00:00 2001 From: Morlay Date: Wed, 19 Jan 2022 11:57:28 +0800 Subject: [PATCH 01/33] Fix BrowserHttpClientAdapter canceled hangs --- .github/workflows/dio.yml | 3 ++- dio/lib/src/adapters/browser_adapter.dart | 9 ++++++++- dio/test/basic_test.dart | 3 +-- dio/test/readtimeout_test.dart | 2 ++ dio/test/upload_stream_test.dart | 4 ++-- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 1019cbe5e..80aedbf18 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -54,7 +54,8 @@ jobs: with: sdk: ${{ matrix.sdk }} - run: pub get - - run: dart test --chain-stack-traces + - run: dart test --chain-stack-traces --platform=vm + - run: dart test --chain-stack-traces --platform=chrome - name: Upload test report uses: actions/upload-artifact@v2 if: always() && matrix.sdk == 'stable' diff --git a/dio/lib/src/adapters/browser_adapter.dart b/dio/lib/src/adapters/browser_adapter.dart index 86e1a8c04..f097b3c46 100644 --- a/dio/lib/src/adapters/browser_adapter.dart +++ b/dio/lib/src/adapters/browser_adapter.dart @@ -148,13 +148,20 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { ); }); - cancelFuture?.then((_) { + cancelFuture?.then((err) { if (xhr.readyState < 4 && xhr.readyState > 0) { try { xhr.abort(); } catch (e) { // ignore } + + // xhr.onError will not triggered when xhr.abort() called. + // so need to manual throw the cancel error to avoid Future hang ups. + // or added xhr.onAbort like axios did https://github.com/axios/axios/blob/master/lib/adapters/xhr.js#L102-L111 + if (!completer.isCompleted) { + completer.completeError(err); + } } }); diff --git a/dio/test/basic_test.dart b/dio/test/basic_test.dart index f59759b7c..59fde7244 100644 --- a/dio/test/basic_test.dart +++ b/dio/test/basic_test.dart @@ -1,7 +1,6 @@ // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -@TestOn('vm') import 'dart:async'; import 'dart:io'; @@ -46,7 +45,7 @@ void main() { Dio().get('http://http.invalid'), throwsA((e) => e is DioError && e.error is SocketException), ); - }); + }, testOn: "vm"); test('#cancellation', () async { var dio = Dio(); diff --git a/dio/test/readtimeout_test.dart b/dio/test/readtimeout_test.dart index b57d86782..4878b6e9c 100644 --- a/dio/test/readtimeout_test.dart +++ b/dio/test/readtimeout_test.dart @@ -1,5 +1,7 @@ +@TestOn("vm") import 'dart:async'; import 'dart:io'; + import 'package:dio/dio.dart'; import 'package:test/test.dart'; diff --git a/dio/test/upload_stream_test.dart b/dio/test/upload_stream_test.dart index 142b32252..edbe1c8d8 100644 --- a/dio/test/upload_stream_test.dart +++ b/dio/test/upload_stream_test.dart @@ -39,7 +39,7 @@ void main() { ); var img = base64Encode(f.readAsBytesSync()); expect(r.data['data'], 'data:application/octet-stream;base64,' + img); - }); + }, testOn: "vm"); test('file stream', () async { var f = File('../dio/test/test.jpg'); @@ -55,5 +55,5 @@ void main() { ); var img = base64Encode(f.readAsBytesSync()); expect(r.data['data'], 'data:application/octet-stream;base64,' + img); - }); + }, testOn: "vm"); } From 95c004e546405d6c9adde58b8a79239ea439993b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Wed, 26 Jan 2022 15:47:36 +0100 Subject: [PATCH 02/33] Revert "It's safe for status code to be non-null" This reverts commit 0107079f31d31ea3b4c6dc0dc9170e23b01dbc2e. # Conflicts: # dio/CHANGELOG.md --- dio/CHANGELOG.md | 1 - dio/lib/src/adapter.dart | 4 ++-- dio/lib/src/adapters/browser_adapter.dart | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index f8869e531..2542468e5 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -1,6 +1,5 @@ # Unreleased - require Dart `2.12.1` which fixes exception handling for secure socket connections (https://github.com/dart-lang/sdk/issues/45214) -- `ResponseBody.statusCode` is now non-nullable - Only delete file if it exists when downloading. # 4.0.5-beta1 diff --git a/dio/lib/src/adapter.dart b/dio/lib/src/adapter.dart index a363b70c5..07346ad12 100644 --- a/dio/lib/src/adapter.dart +++ b/dio/lib/src/adapter.dart @@ -61,10 +61,10 @@ class ResponseBody { Stream stream; /// the response headers - Map> headers; + late Map> headers; /// Http status code - int statusCode; + int? statusCode; /// Returns the reason phrase associated with the status code. /// The reason phrase must be set before the body is written diff --git a/dio/lib/src/adapters/browser_adapter.dart b/dio/lib/src/adapters/browser_adapter.dart index 86e1a8c04..6badb24ea 100644 --- a/dio/lib/src/adapters/browser_adapter.dart +++ b/dio/lib/src/adapters/browser_adapter.dart @@ -53,7 +53,7 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { completer.complete( ResponseBody.fromBytes( body, - xhr.status!, + xhr.status, headers: xhr.responseHeaders.map((k, v) => MapEntry(k, v.split(','))), statusMessage: xhr.statusText, isRedirect: xhr.status == 302 || xhr.status == 301, From 283bb350b11d3e7dee87d9db27abb3e611df3670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Wed, 26 Jan 2022 16:06:53 +0100 Subject: [PATCH 03/33] improve inner stacktraces --- dio/lib/src/dio_error.dart | 2 +- dio/lib/src/dio_mixin.dart | 18 +++++++++++------- dio/lib/src/entry/dio_for_native.dart | 7 +++++-- dio/test/interceptor_test.dart | 10 +++++++--- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/dio/lib/src/dio_error.dart b/dio/lib/src/dio_error.dart index b76e1f88f..eabc12323 100644 --- a/dio/lib/src/dio_error.dart +++ b/dio/lib/src/dio_error.dart @@ -42,7 +42,7 @@ class DioError implements Exception { /// The original error/exception object; It's usually not null when `type` /// is DioErrorType.other - dynamic error; + Object? error; StackTrace? stackTrace; diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index e9ae16b9f..46a2aac96 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -475,8 +475,6 @@ abstract class DioMixin implements Dio { @override Future> fetch(RequestOptions requestOptions) async { - final stackTrace = StackTrace.current; - if (requestOptions.cancelToken != null) { requestOptions.cancelToken!.requestOptions = requestOptions; } @@ -550,6 +548,7 @@ abstract class DioMixin implements Dio { assureDioError( err, requestOptions, + stackTrace, ), ); } @@ -621,7 +620,7 @@ abstract class DioMixin implements Dio { data is InterceptorState ? data.data : data, requestOptions, ); - }).catchError((err, _) { + }).catchError((err, maybeStackTrace) { var isState = err is InterceptorState; if (isState) { @@ -630,6 +629,11 @@ abstract class DioMixin implements Dio { } } + StackTrace? stackTrace; + if (maybeStackTrace is StackTrace?) { + stackTrace = maybeStackTrace; + } + throw assureDioError( isState ? err.data : err, requestOptions, @@ -689,8 +693,8 @@ abstract class DioMixin implements Dio { type: DioErrorType.response, ); } - } catch (e) { - throw assureDioError(e, reqOpt); + } catch (e, stackTrace) { + throw assureDioError(e, reqOpt, stackTrace); } } @@ -782,9 +786,9 @@ abstract class DioMixin implements Dio { static DioError assureDioError( err, - RequestOptions requestOptions, [ + RequestOptions requestOptions, StackTrace? sourceStackTrace, - ]) { + ) { DioError dioError; if (err is DioError) { dioError = err; diff --git a/dio/lib/src/entry/dio_for_native.dart b/dio/lib/src/entry/dio_for_native.dart index ea267028a..1a0fbad09 100644 --- a/dio/lib/src/entry/dio_for_native.dart +++ b/dio/lib/src/entry/dio_for_native.dart @@ -183,6 +183,7 @@ class DioForNative with DioMixin implements Dio { completer.completeError(DioMixin.assureDioError( err, response.requestOptions, + stackTrace, )); } }); @@ -193,20 +194,22 @@ class DioForNative with DioMixin implements Dio { closed = true; await raf.close(); completer.complete(response); - } catch (e) { + } catch (e, stackTrace) { completer.completeError(DioMixin.assureDioError( e, response.requestOptions, + stackTrace, )); } }, - onError: (e) async { + onError: (e, stackTrace) async { try { await _closeAndDelete(); } finally { completer.completeError(DioMixin.assureDioError( e, response.requestOptions, + stackTrace as StackTrace?, )); } }, diff --git a/dio/test/interceptor_test.dart b/dio/test/interceptor_test.dart index ec7a48359..21adb2ae5 100644 --- a/dio/test/interceptor_test.dart +++ b/dio/test/interceptor_test.dart @@ -122,7 +122,8 @@ void main() { if (err.requestOptions.path == '/reject-next/reject') { handler.reject(err); } else { - err.error++; + var count = (err.error as int); + err.error = count++; handler.next(err); } } @@ -143,10 +144,13 @@ void main() { }, onError: (err, handler) { if (err.requestOptions.path == '/resolve-next/reject-next') { - err.error++; + var count = (err.error as int); + err.error = count++; + handler.next(err); } else { - err.error++; + var count = (err.error as int); + err.error = count++; handler.next(err); } }, From 271eebd017a850652bf86a676405f0d782ae9a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asc=C3=AAnio?= Date: Wed, 26 Jan 2022 23:53:09 -0300 Subject: [PATCH 04/33] docs: fix table of contents links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 94100c471..fcb3de72c 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,9 @@ Welcome to submit Dio's third-party plugins and related libraries [here](https:/ - [Sending FormData](#sending-formdata) -- [Transformer](#Transformer) +- [Transformer](#transformer) -- [Set proxy and HttpClient config](#set-proxy-and-httpclient-config) +- [Using proxy](#using-proxy) - [Https certificate verification](#https-certificate-verification) From 0e11a48a36af6ca9c56fc5ed81444d81b2dc825a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Thu, 27 Jan 2022 20:15:53 +0100 Subject: [PATCH 05/33] Improve DioError --- .DS_Store | Bin 0 -> 6148 bytes dio/lib/src/adapters/browser_adapter.dart | 21 +++--- dio/lib/src/adapters/io_adapter.dart | 20 ++--- dio/lib/src/cancel_token.dart | 9 +-- dio/lib/src/dio_error.dart | 70 +++++++++++++++--- dio/lib/src/dio_mixin.dart | 31 ++++---- dio/lib/src/entry/dio_for_native.dart | 7 +- dio/lib/src/options.dart | 2 +- dio/test/basic_test.dart | 2 +- dio/test/download_test.dart | 2 +- dio/test/interceptor_test.dart | 14 ++-- .../lib/src/connection_manager_imp.dart | 5 +- 12 files changed, 112 insertions(+), 71 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7ce88ff4fb0d41f9115b10023908dda9f1a6d30d GIT binary patch literal 6148 zcmeHKOKL(v5Ufsw2yR@uoGau8gP0TK0+L81ATc2B-^z34XsP}zBG2s1B2o=KHPh2I z!_?ySYXG)9ZXSU-fGOP(Cm+V<`|cyVtB4WlJmVc7IJ|8RuP^&i_T_+cAMlACj@bU> z?{~f>lLAse3P=GdAO)_hKo!{O?8@irI4K|n{=WkLeQ0#YUN|Jir-MVZ0K^HyVVp-V zL2Mo%_QD~N5t=2Hm{hA4!;;Q;tGr$~BqkkJ&4<;^Rvn7P?L5ClI;Up8x;= literal 0 HcmV?d00001 diff --git a/dio/lib/src/adapters/browser_adapter.dart b/dio/lib/src/adapters/browser_adapter.dart index 6a9027844..d319f579a 100644 --- a/dio/lib/src/adapters/browser_adapter.dart +++ b/dio/lib/src/adapters/browser_adapter.dart @@ -76,10 +76,9 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { (value) { if (!haveSent) { completer.completeError( - DioError( + DioError.connectionTimeout( requestOptions: options, - error: 'Connecting timed out [${options.connectTimeout}ms]', - type: DioErrorType.connectTimeout, + timeout: options.connectTimeout!, ), StackTrace.current, ); @@ -102,10 +101,9 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { if (duration > sendTimeout) { uploadStopwatch.stop(); completer.completeError( - DioError( + DioError.sendTimeout( + timeout: options.sendTimeout!, requestOptions: options, - error: 'Sending timed out [${options.sendTimeout}ms]', - type: DioErrorType.sendTimeout, ), StackTrace.current, ); @@ -131,10 +129,9 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { if (duration > reveiveTimeout) { downloadStopwatch.stop(); completer.completeError( - DioError( + DioError.receiveTimeout( + timeout: options.receiveTimeout!, requestOptions: options, - error: 'Receiving timed out [${options.receiveTimeout}ms]', - type: DioErrorType.receiveTimeout, ), StackTrace.current, ); @@ -151,11 +148,11 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { xhr.onError.first.then((_) { // Unfortunately, the underlying XMLHttpRequest API doesn't expose any // specific information about the error itself. + // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onerror completer.completeError( - DioError( - type: DioErrorType.response, - error: 'XMLHttpRequest error.', + DioError.connectionError( requestOptions: options, + reason: 'XMLHttpRequest error.', ), StackTrace.current, ); diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index e3a903403..b17aeb02c 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -36,10 +36,9 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { var reqFuture = _httpClient.openUrl(options.method, options.uri); void _throwConnectingTimeout() { - throw DioError( + throw DioError.connectionTimeout( requestOptions: options, - error: 'Connecting timed out [${options.connectTimeout}ms]', - type: DioErrorType.connectTimeout, + timeout: options.connectTimeout!, ); } @@ -78,10 +77,9 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { try { await future; } on TimeoutException { - throw DioError( + throw DioError.sendTimeout( + timeout: options.sendTimeout!, requestOptions: options, - error: 'Sending timeout[${options.sendTimeout}ms]', - type: DioErrorType.sendTimeout, ); } } @@ -96,10 +94,9 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { try { responseStream = await future; } on TimeoutException { - throw DioError( + throw DioError.receiveTimeout( + timeout: options.receiveTimeout!, requestOptions: options, - error: 'Receiving data timeout[${options.receiveTimeout}]', - type: DioErrorType.receiveTimeout, ); } @@ -111,10 +108,9 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { final receiveTimeout = options.receiveTimeout; if (receiveTimeout != null && duration > receiveTimeout) { sink.addError( - DioError( + DioError.receiveTimeout( + timeout: options.receiveTimeout!, requestOptions: options, - error: 'Receiving data timeout[${options.receiveTimeout}]', - type: DioErrorType.receiveTimeout, ), ); //todo: to verify diff --git a/dio/lib/src/cancel_token.dart b/dio/lib/src/cancel_token.dart index 59baed088..b4698b178 100644 --- a/dio/lib/src/cancel_token.dart +++ b/dio/lib/src/cancel_token.dart @@ -13,7 +13,7 @@ class CancelToken { /// Whether is throw by [cancel] static bool isCancel(DioError e) { - return e.type == DioErrorType.cancel; + return e.type == DioErrorType.requestCancelled; } /// If request have been canceled, save the cancel Error. @@ -33,11 +33,10 @@ class CancelToken { Future get whenCancel => _completer.future; /// Cancel the request - void cancel([dynamic reason]) { - _cancelError = DioError( - type: DioErrorType.cancel, - error: reason, + void cancel([Object? reason]) { + _cancelError = DioError.requestCancelled( requestOptions: requestOptions ?? RequestOptions(path: ''), + reason: reason, ); _cancelError!.stackTrace = StackTrace.current; diff --git a/dio/lib/src/dio_error.dart b/dio/lib/src/dio_error.dart index eabc12323..14c158d79 100644 --- a/dio/lib/src/dio_error.dart +++ b/dio/lib/src/dio_error.dart @@ -2,8 +2,8 @@ import 'options.dart'; import 'response.dart'; enum DioErrorType { - /// It occurs when url is opened timeout. - connectTimeout, + /// Caused by a connection timeout. + connectionTimeout, /// It occurs when url is sent timeout. sendTimeout, @@ -11,26 +11,76 @@ enum DioErrorType { ///It occurs when receiving timeout. receiveTimeout, - /// When the server response, but with a incorrect status, such as 404, 503... - response, + /// The [DioError] was caused by an incorrect status code as configured by + /// [ValidateStatus]. + badResponse, /// When the request is cancelled, dio will throw a error with this type. - cancel, + requestCancelled, + + /// Caused for example by a `xhr.onError` or SocketExceptions. + connectionError, /// Default error type, Some other Error. In this case, you can /// use the DioError.error if it is not null. - other, + unknown, } -/// DioError describes the error info when request failed. +/// DioError describes the exception info when a request failed. class DioError implements Exception { + /// Prefer using one of the other constructors. + /// They're most likely better fitting. DioError({ required this.requestOptions, this.response, - this.type = DioErrorType.other, + this.type = DioErrorType.unknown, this.error, + this.stackTrace, + this.message, }); + DioError.badResponse({ + required int statusCode, + required this.requestOptions, + required this.response, + }) : type = DioErrorType.badResponse, + message = 'The request returned an ' + 'invalid status code of $statusCode'; + + DioError.connectionTimeout({ + required Duration timeout, + required this.requestOptions, + }) : type = DioErrorType.connectionTimeout, + message = 'The request connection took ' + 'longer than $timeout. It was aborted.'; + + DioError.sendTimeout({ + required Duration timeout, + required this.requestOptions, + }) : type = DioErrorType.sendTimeout, + message = 'The request took ' + 'longer than $timeout to send data. It was aborted.'; + + DioError.receiveTimeout({ + required Duration timeout, + required this.requestOptions, + }) : type = DioErrorType.receiveTimeout, + message = 'The request took ' + 'longer than $timeout to receive data. It was aborted.'; + + DioError.requestCancelled({ + required this.requestOptions, + required Object? reason, + }) : type = DioErrorType.requestCancelled, + message = 'The request was cancelled.', + error = reason; + + DioError.connectionError({ + required this.requestOptions, + required String reason, + }) : type = DioErrorType.connectionError, + message = 'The connection errored: $reason'; + /// Request info. RequestOptions requestOptions; @@ -44,9 +94,11 @@ class DioError implements Exception { /// is DioErrorType.other Object? error; + /// The stacktrace of the original error/exception object; + /// It's usually not null when `type` is DioErrorType.other StackTrace? stackTrace; - String get message => (error?.toString() ?? ''); + String? message; @override String toString() { diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index 46a2aac96..a0de1abd3 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -464,9 +464,9 @@ abstract class DioMixin implements Dio { requestOptions.cancelToken = cancelToken; if (_closed) { - throw DioError( + throw DioError.connectionError( + reason: "Dio can't establish a new connection after it was closed.", requestOptions: requestOptions, - error: "Dio can't establish new connection after closed.", ); } @@ -475,9 +475,7 @@ abstract class DioMixin implements Dio { @override Future> fetch(RequestOptions requestOptions) async { - if (requestOptions.cancelToken != null) { - requestOptions.cancelToken!.requestOptions = requestOptions; - } + requestOptions.cancelToken?.requestOptions = requestOptions; if (T != dynamic && !(requestOptions.responseType == ResponseType.bytes || @@ -686,11 +684,10 @@ abstract class DioMixin implements Dio { if (statusOk) { return checkIfNeedEnqueue(interceptors.responseLock, () => ret); } else { - throw DioError( + throw DioError.badResponse( + statusCode: responseBody.statusCode, requestOptions: reqOpt, response: ret, - error: 'Http status error [${responseBody.statusCode}]', - type: DioErrorType.response, ); } } catch (e, stackTrace) { @@ -792,17 +789,21 @@ abstract class DioMixin implements Dio { DioError dioError; if (err is DioError) { dioError = err; + dioError.stackTrace ??= sourceStackTrace; + return dioError; } else { - dioError = DioError(requestOptions: requestOptions, error: err); + return DioError( + requestOptions: requestOptions, + error: err, + stackTrace: sourceStackTrace, + ); } - - dioError.stackTrace = sourceStackTrace ?? dioError.stackTrace; - - return dioError; } - static Response assureResponse(response, - [RequestOptions? requestOptions]) { + static Response assureResponse( + response, [ + RequestOptions? requestOptions, + ]) { if (response is! Response) { return Response( data: response as T, diff --git a/dio/lib/src/entry/dio_for_native.dart b/dio/lib/src/entry/dio_for_native.dart index 1a0fbad09..87000d346 100644 --- a/dio/lib/src/entry/dio_for_native.dart +++ b/dio/lib/src/entry/dio_for_native.dart @@ -90,7 +90,7 @@ class DioForNative with DioMixin implements Dio { cancelToken: cancelToken ?? CancelToken(), ); } on DioError catch (e) { - if (e.type == DioErrorType.response) { + if (e.type == DioErrorType.badResponse) { if (e.response!.requestOptions.receiveDataWhenStatusError == true) { var res = await transformer.transformResponse( e.response!.requestOptions..responseType = ResponseType.json, @@ -227,10 +227,9 @@ class DioForNative with DioMixin implements Dio { await subscription.cancel(); await _closeAndDelete(); if (err is TimeoutException) { - throw DioError( + throw DioError.receiveTimeout( + timeout: timeout, requestOptions: response.requestOptions, - error: 'Receiving data timeout[$timeout]', - type: DioErrorType.receiveTimeout, ); } else { throw err; diff --git a/dio/lib/src/options.dart b/dio/lib/src/options.dart index 8c5e33f6e..0a5657e11 100644 --- a/dio/lib/src/options.dart +++ b/dio/lib/src/options.dart @@ -194,7 +194,7 @@ mixin OptionsMixin { late Map queryParameters; /// Timeout in milliseconds for opening url. - /// [Dio] will throw the [DioError] with [DioErrorType.connectTimeout] type + /// [Dio] will throw the [DioError] with [DioErrorType.connectionTimeout] type /// when time out. Duration? get connectTimeout => _connectTimeout; diff --git a/dio/test/basic_test.dart b/dio/test/basic_test.dart index f59759b7c..5f950763c 100644 --- a/dio/test/basic_test.dart +++ b/dio/test/basic_test.dart @@ -70,7 +70,7 @@ void main() { dio.get('401'), throwsA((e) => e is DioError && - e.type == DioErrorType.response && + e.type == DioErrorType.badResponse && e.response!.statusCode == 401), ); diff --git a/dio/test/download_test.dart b/dio/test/download_test.dart index 0b6e8cd59..ba85c05b0 100644 --- a/dio/test/download_test.dart +++ b/dio/test/download_test.dart @@ -89,7 +89,7 @@ void main() { cancelToken: cancelToken, ) .catchError((e) => throw (e as DioError).type), - throwsA(DioErrorType.cancel), + throwsA(DioErrorType.requestCancelled), ); //print(r); }); diff --git a/dio/test/interceptor_test.dart b/dio/test/interceptor_test.dart index 21adb2ae5..46ca0f58b 100644 --- a/dio/test/interceptor_test.dart +++ b/dio/test/interceptor_test.dart @@ -285,12 +285,12 @@ void main() { expect(response.data['errCode'], 0); expect( - dio.get('/fakepath3').catchError((e) => throw (e as DioError).message), - throwsA('test error'), + dio.get('/fakepath3').catchError((e) => throw (e as DioError)), + throwsA(isA()), ); expect( - dio.get('/fakepath4').catchError((e) => throw (e as DioError).message), - throwsA('test error'), + dio.get('/fakepath4').catchError((e) => throw (e as DioError)), + throwsA(isA()), ); response = await dio.get('/test'); @@ -358,10 +358,8 @@ void main() { response = await dio.get(urlNotFound + '2'); expect(response.data, 'fake data'); expect( - dio - .get(urlNotFound + '3') - .catchError((e) => throw (e as DioError).message), - throwsA('custom error info [404]'), + dio.get(urlNotFound + '3').catchError((e) => throw (e as DioError)), + throwsA(isA()), ); }); test('multi response interceptor', () async { diff --git a/plugins/http2_adapter/lib/src/connection_manager_imp.dart b/plugins/http2_adapter/lib/src/connection_manager_imp.dart index 7175b06fe..82b2b56aa 100644 --- a/plugins/http2_adapter/lib/src/connection_manager_imp.dart +++ b/plugins/http2_adapter/lib/src/connection_manager_imp.dart @@ -79,10 +79,9 @@ class _ConnectionManager implements ConnectionManager { } on SocketException catch (e) { if (e.osError == null) { if (e.message.contains('timed out')) { - throw DioError( + throw DioError.connectionTimeout( + timeout: options.connectTimeout!, requestOptions: options, - error: 'Connecting timed out [${options.connectTimeout}]', - type: DioErrorType.connectTimeout, ); } } From c61c8ebc905e1bda473136c89c530f143bffd3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Thu, 27 Jan 2022 20:42:38 +0100 Subject: [PATCH 06/33] improve error --- dio/lib/src/adapters/browser_adapter.dart | 3 ++- dio/lib/src/dio_error.dart | 30 ++++++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/dio/lib/src/adapters/browser_adapter.dart b/dio/lib/src/adapters/browser_adapter.dart index d319f579a..a3d5b914f 100644 --- a/dio/lib/src/adapters/browser_adapter.dart +++ b/dio/lib/src/adapters/browser_adapter.dart @@ -152,7 +152,8 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { completer.completeError( DioError.connectionError( requestOptions: options, - reason: 'XMLHttpRequest error.', + reason: 'The XMLHttpRequest onError callback was called. ' + 'This typically indicates an error on the network layer.', ), StackTrace.current, ); diff --git a/dio/lib/src/dio_error.dart b/dio/lib/src/dio_error.dart index 14c158d79..4e813480b 100644 --- a/dio/lib/src/dio_error.dart +++ b/dio/lib/src/dio_error.dart @@ -26,6 +26,27 @@ enum DioErrorType { unknown, } +extension _DioErrorTypeExtension on DioErrorType { + String toPrettyDescription() { + switch (this) { + case DioErrorType.connectionTimeout: + return 'connection timeout'; + case DioErrorType.sendTimeout: + return 'send timeout'; + case DioErrorType.receiveTimeout: + return 'receive timeout'; + case DioErrorType.badResponse: + return 'bad response'; + case DioErrorType.requestCancelled: + return 'request cancelled'; + case DioErrorType.connectionError: + return 'connection error'; + case DioErrorType.unknown: + return 'unknown'; + } + } +} + /// DioError describes the exception info when a request failed. class DioError implements Exception { /// Prefer using one of the other constructors. @@ -102,12 +123,15 @@ class DioError implements Exception { @override String toString() { - var msg = 'DioError [$type]: $message'; + var msg = 'DioError [${type.toPrettyDescription()}]: $message'; + if (error != null) { + msg += '\nError: $error'; + } if (error is Error) { - msg += '\n${(error as Error).stackTrace}'; + msg += '\nInner error stacktrace:\n${(error as Error).stackTrace}'; } if (stackTrace != null) { - msg += '\nSource stack:\n$stackTrace'; + msg += '\nInner stacktrace:\n$stackTrace'; } return msg; } From 4beed0b67a818423f6d2112d89ba72561630c2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Fri, 28 Jan 2022 19:55:58 +0100 Subject: [PATCH 07/33] wip --- dio/lib/src/dio_mixin.dart | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index a0de1abd3..2c6b0e0fc 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -786,18 +786,15 @@ abstract class DioMixin implements Dio { RequestOptions requestOptions, StackTrace? sourceStackTrace, ) { - DioError dioError; if (err is DioError) { - dioError = err; - dioError.stackTrace ??= sourceStackTrace; - return dioError; - } else { - return DioError( - requestOptions: requestOptions, - error: err, - stackTrace: sourceStackTrace, - ); + // nothing to be done + return err; } + return DioError( + requestOptions: requestOptions, + error: err, + stackTrace: sourceStackTrace, + ); } static Response assureResponse( From c17462e6e70c6755b28336b77786ba3270227061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 30 Jan 2022 18:06:38 +0100 Subject: [PATCH 08/33] wip --- dio/lib/src/adapters/browser_adapter.dart | 19 ++++--- dio/lib/src/adapters/io_adapter.dart | 67 +++++++++++++---------- dio/lib/src/cancel_token.dart | 2 +- dio/lib/src/dio_error.dart | 3 + 4 files changed, 52 insertions(+), 39 deletions(-) diff --git a/dio/lib/src/adapters/browser_adapter.dart b/dio/lib/src/adapters/browser_adapter.dart index a3d5b914f..fb3e2bade 100644 --- a/dio/lib/src/adapters/browser_adapter.dart +++ b/dio/lib/src/adapters/browser_adapter.dart @@ -74,16 +74,17 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { if (connectionTimeout != null) { Future.delayed(connectionTimeout).then( (value) { - if (!haveSent) { - completer.completeError( - DioError.connectionTimeout( - requestOptions: options, - timeout: options.connectTimeout!, - ), - StackTrace.current, - ); - xhr.abort(); + if (haveSent) { + return; } + completer.completeError( + DioError.connectionTimeout( + requestOptions: options, + timeout: options.connectTimeout!, + ), + StackTrace.current, + ); + xhr.abort(); }, ); } diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index b17aeb02c..7f8a719d5 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -35,18 +35,19 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { var _httpClient = _configHttpClient(cancelFuture, options.connectTimeout); var reqFuture = _httpClient.openUrl(options.method, options.uri); - void _throwConnectingTimeout() { - throw DioError.connectionTimeout( - requestOptions: options, - timeout: options.connectTimeout!, - ); - } - late HttpClientRequest request; try { final connectionTimeout = options.connectTimeout; if (connectionTimeout != null) { - request = await reqFuture.timeout(connectionTimeout); + request = await reqFuture.timeout( + connectionTimeout, + onTimeout: () { + throw DioError.connectionTimeout( + requestOptions: options, + timeout: options.connectTimeout!, + ); + }, + ); } else { request = await reqFuture; } @@ -55,13 +56,18 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { options.headers.forEach((k, v) { if (v != null) request.headers.set(k, '$v'); }); - } on SocketException catch (e) { + } on SocketException catch (e, stackTrace) { if (e.message.contains('timed out')) { - _throwConnectingTimeout(); + throw DioError.connectionTimeout( + requestOptions: options, + timeout: options.connectTimeout ?? + _httpClient.connectionTimeout ?? + Duration(), + error: e, + stackTrace: stackTrace, + ); } rethrow; - } on TimeoutException { - _throwConnectingTimeout(); } request.followRedirects = options.followRedirects; @@ -72,34 +78,37 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { var future = request.addStream(requestStream); final sendTimeout = options.sendTimeout; if (sendTimeout != null) { - future = future.timeout(sendTimeout); - } - try { - await future; - } on TimeoutException { - throw DioError.sendTimeout( - timeout: options.sendTimeout!, - requestOptions: options, + future = future.timeout( + sendTimeout, + onTimeout: () { + throw DioError.sendTimeout( + timeout: options.sendTimeout!, + requestOptions: options, + ); + }, ); } + + await future; } final stopwatch = Stopwatch()..start(); var future = request.close(); final receiveTimeout = options.receiveTimeout; if (receiveTimeout != null) { - future = future.timeout(receiveTimeout); - } - late HttpClientResponse responseStream; - try { - responseStream = await future; - } on TimeoutException { - throw DioError.receiveTimeout( - timeout: options.receiveTimeout!, - requestOptions: options, + future = future.timeout( + receiveTimeout, + onTimeout: () { + throw DioError.receiveTimeout( + timeout: options.receiveTimeout!, + requestOptions: options, + ); + }, ); } + final responseStream = await future; + var stream = responseStream.transform(StreamTransformer.fromHandlers( handleData: (data, sink) { diff --git a/dio/lib/src/cancel_token.dart b/dio/lib/src/cancel_token.dart index b4698b178..7b87f4d5d 100644 --- a/dio/lib/src/cancel_token.dart +++ b/dio/lib/src/cancel_token.dart @@ -37,8 +37,8 @@ class CancelToken { _cancelError = DioError.requestCancelled( requestOptions: requestOptions ?? RequestOptions(path: ''), reason: reason, + stackTrace: StackTrace.current, ); - _cancelError!.stackTrace = StackTrace.current; if (!_completer.isCompleted) { _completer.complete(_cancelError); diff --git a/dio/lib/src/dio_error.dart b/dio/lib/src/dio_error.dart index 4e813480b..e739b35de 100644 --- a/dio/lib/src/dio_error.dart +++ b/dio/lib/src/dio_error.dart @@ -71,6 +71,8 @@ class DioError implements Exception { DioError.connectionTimeout({ required Duration timeout, required this.requestOptions, + this.error, + this.stackTrace, }) : type = DioErrorType.connectionTimeout, message = 'The request connection took ' 'longer than $timeout. It was aborted.'; @@ -92,6 +94,7 @@ class DioError implements Exception { DioError.requestCancelled({ required this.requestOptions, required Object? reason, + this.stackTrace, }) : type = DioErrorType.requestCancelled, message = 'The request was cancelled.', error = reason; From 1df2d463569cbc43ad222a9d75aea7be7c7d5c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 30 Jan 2022 20:13:55 +0100 Subject: [PATCH 09/33] code improvement --- dio/lib/src/dio_mixin.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index 2c6b0e0fc..f99a7250b 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -751,8 +751,9 @@ abstract class DioMixin implements Dio { // If the request has been cancelled, stop request and throw error. static void checkCancelled(CancelToken? cancelToken) { - if (cancelToken != null && cancelToken.cancelError != null) { - throw cancelToken.cancelError!; + final error = cancelToken?.cancelError; + if (error != null) { + throw error; } } From 263726957b805ffcb27d351f24e908b9e4eb1732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 30 Jan 2022 20:29:33 +0100 Subject: [PATCH 10/33] fix tests --- dio/lib/src/adapters/io_adapter.dart | 1 + dio/test/interceptor_test.dart | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index 7f8a719d5..d493c0cde 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -76,6 +76,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { if (requestStream != null) { // Transform the request data var future = request.addStream(requestStream); + final sendTimeout = options.sendTimeout; if (sendTimeout != null) { future = future.timeout( diff --git a/dio/test/interceptor_test.dart b/dio/test/interceptor_test.dart index 46ca0f58b..bd8721b5e 100644 --- a/dio/test/interceptor_test.dart +++ b/dio/test/interceptor_test.dart @@ -123,7 +123,8 @@ void main() { handler.reject(err); } else { var count = (err.error as int); - err.error = count++; + count++; + err.error = count; handler.next(err); } } @@ -145,12 +146,13 @@ void main() { onError: (err, handler) { if (err.requestOptions.path == '/resolve-next/reject-next') { var count = (err.error as int); - err.error = count++; - + count++; + err.error = count; handler.next(err); } else { var count = (err.error as int); - err.error = count++; + count++; + err.error = count; handler.next(err); } }, From 1853a3067cef5f52284461a645a1921e63bc558d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 30 Jan 2022 21:08:01 +0100 Subject: [PATCH 11/33] better code flow --- dio/lib/src/adapters/io_adapter.dart | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index d493c0cde..b9bf33109 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -57,17 +57,17 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { if (v != null) request.headers.set(k, '$v'); }); } on SocketException catch (e, stackTrace) { - if (e.message.contains('timed out')) { - throw DioError.connectionTimeout( - requestOptions: options, - timeout: options.connectTimeout ?? - _httpClient.connectionTimeout ?? - Duration(), - error: e, - stackTrace: stackTrace, - ); + if (!e.message.contains('timed out')) { + rethrow; } - rethrow; + throw DioError.connectionTimeout( + requestOptions: options, + timeout: options.connectTimeout ?? + _httpClient.connectionTimeout ?? + Duration(), + error: e, + stackTrace: stackTrace, + ); } request.followRedirects = options.followRedirects; From 6588021a8709dc560ce73357f96bdecac3281ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Sun, 30 Jan 2022 21:08:15 +0100 Subject: [PATCH 12/33] only print stacktrace if not duplicated --- dio/lib/src/dio_error.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dio/lib/src/dio_error.dart b/dio/lib/src/dio_error.dart index e739b35de..d8cfeec0e 100644 --- a/dio/lib/src/dio_error.dart +++ b/dio/lib/src/dio_error.dart @@ -127,11 +127,12 @@ class DioError implements Exception { @override String toString() { var msg = 'DioError [${type.toPrettyDescription()}]: $message'; + final error = this.error; if (error != null) { msg += '\nError: $error'; } - if (error is Error) { - msg += '\nInner error stacktrace:\n${(error as Error).stackTrace}'; + if (error is Error && error.stackTrace != stackTrace) { + msg += '\nInner error stacktrace:\n${error.stackTrace}'; } if (stackTrace != null) { msg += '\nInner stacktrace:\n$stackTrace'; From fbee370898568db4195396a95d8d21736324507b Mon Sep 17 00:00:00 2001 From: Peter Leibiger Date: Fri, 4 Feb 2022 23:54:50 +0100 Subject: [PATCH 13/33] ci: Remove dev channel, now always points to beta --- .github/workflows/dio.yml | 2 +- .github/workflows/plugin_cookie_manager.yml | 2 +- .github/workflows/plugin_http2_adapter.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 1019cbe5e..d8e82a028 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -44,7 +44,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [ stable, beta, dev, 2.12.1 ] + sdk: [ stable, beta, 2.12.1 ] defaults: run: working-directory: dio diff --git a/.github/workflows/plugin_cookie_manager.yml b/.github/workflows/plugin_cookie_manager.yml index 2951aa56c..569218f7a 100644 --- a/.github/workflows/plugin_cookie_manager.yml +++ b/.github/workflows/plugin_cookie_manager.yml @@ -44,7 +44,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [ stable, beta, dev, 2.12.1 ] + sdk: [ stable, beta, 2.12.1 ] defaults: run: working-directory: plugins/cookie_manager diff --git a/.github/workflows/plugin_http2_adapter.yml b/.github/workflows/plugin_http2_adapter.yml index 20d2ee515..b580a9cfb 100644 --- a/.github/workflows/plugin_http2_adapter.yml +++ b/.github/workflows/plugin_http2_adapter.yml @@ -44,7 +44,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [ stable, beta, dev, 2.12.1 ] + sdk: [ stable, beta, 2.12.1 ] defaults: run: working-directory: plugins/http2_adapter From 39d6f83ed2e554a36cca9c82b30364c6b8fbc2b8 Mon Sep 17 00:00:00 2001 From: Peter Leibiger Date: Sat, 5 Feb 2022 01:41:06 +0100 Subject: [PATCH 14/33] ci: Upload and collect test results for all sdks --- .github/workflows/dio.yml | 4 ++-- .github/workflows/plugin_cookie_manager.yml | 4 ++-- .github/workflows/plugin_http2_adapter.yml | 4 ++-- .github/workflows/test-report.yml | 17 +++++++++++++++-- dio/test/upload_stream_test.dart | 2 +- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index d8e82a028..712fb6014 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -57,9 +57,9 @@ jobs: - run: dart test --chain-stack-traces - name: Upload test report uses: actions/upload-artifact@v2 - if: always() && matrix.sdk == 'stable' + if: always() with: - name: test-results + name: test-results-${{ matrix.sdk }} path: dio/build/reports/test-results.json publish-dry-run: diff --git a/.github/workflows/plugin_cookie_manager.yml b/.github/workflows/plugin_cookie_manager.yml index 569218f7a..9cc43330c 100644 --- a/.github/workflows/plugin_cookie_manager.yml +++ b/.github/workflows/plugin_cookie_manager.yml @@ -57,7 +57,7 @@ jobs: - run: dart test --chain-stack-traces - name: Upload test report uses: actions/upload-artifact@v2 - if: always() && matrix.sdk == 'stable' + if: always() with: - name: test-results + name: test-results-${{ matrix.sdk }} path: plugins/cookie_manager/build/reports/test-results.json diff --git a/.github/workflows/plugin_http2_adapter.yml b/.github/workflows/plugin_http2_adapter.yml index b580a9cfb..5f69bd69b 100644 --- a/.github/workflows/plugin_http2_adapter.yml +++ b/.github/workflows/plugin_http2_adapter.yml @@ -57,7 +57,7 @@ jobs: - run: dart test --chain-stack-traces - name: Upload test report uses: actions/upload-artifact@v2 - if: always() && matrix.sdk == 'stable' + if: always() with: - name: test-results + name: test-results-${{ matrix.sdk }} path: plugins/http2_adapter/build/reports/test-results.json diff --git a/.github/workflows/test-report.yml b/.github/workflows/test-report.yml index 3401fbb75..bd6ace890 100644 --- a/.github/workflows/test-report.yml +++ b/.github/workflows/test-report.yml @@ -14,10 +14,23 @@ jobs: report: runs-on: ubuntu-latest steps: + - name: Download and Extract Artifacts + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + run: | + mkdir -p artifacts && cd artifacts + + artifacts_url=${{ github.event.workflow_run.artifacts_url }} + + gh api "$artifacts_url" -q '.artifacts[] | [.name, .archive_download_url] | @tsv' | while read artifact + do + IFS=$'\t' read name url <<< "$artifact" + gh api $url > "$name.zip" + unzip -d "$name" "$name.zip" + done - name: Publish test reports uses: dorny/test-reporter@v1 with: name: ${{ github.event.workflow_run.workflow.name }} Test results - artifact: test-results - path: '**/*.json' + path: 'artifacts/**/test-results.json' reporter: dart-json diff --git a/dio/test/upload_stream_test.dart b/dio/test/upload_stream_test.dart index 142b32252..4a0d83fc7 100644 --- a/dio/test/upload_stream_test.dart +++ b/dio/test/upload_stream_test.dart @@ -6,7 +6,7 @@ import 'package:test/test.dart'; void main() { var dio = Dio(); - dio.options.baseUrl = 'http://httpbin.org/'; + dio.options.baseUrl = 'https://httpbin.org/'; test('stream', () async { Response r; const str = 'hello 😌'; From 0a7b8919fe45843c0ad598e6bc4a7d0afbe89a47 Mon Sep 17 00:00:00 2001 From: Peter Leibiger Date: Sat, 5 Feb 2022 02:36:54 +0100 Subject: [PATCH 15/33] Add changelog and update workflow --- .github/workflows/dio.yml | 6 +++--- dio/CHANGELOG.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 46fb8b631..fe3f5a7b0 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -45,6 +45,7 @@ jobs: fail-fast: false matrix: sdk: [ stable, beta, 2.12.1 ] + platform: [ vm, chrome ] defaults: run: working-directory: dio @@ -54,13 +55,12 @@ jobs: with: sdk: ${{ matrix.sdk }} - run: pub get - - run: dart test --chain-stack-traces --platform=vm - - run: dart test --chain-stack-traces --platform=chrome + - run: dart test --chain-stack-traces --platform=${{ matrix.platform }} - name: Upload test report uses: actions/upload-artifact@v2 if: always() with: - name: test-results-${{ matrix.sdk }} + name: test-results-${{ matrix.sdk }}-${{ matrix.platform }} path: dio/build/reports/test-results.json publish-dry-run: diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index 2542468e5..773e601bd 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased - require Dart `2.12.1` which fixes exception handling for secure socket connections (https://github.com/dart-lang/sdk/issues/45214) - Only delete file if it exists when downloading. +- Fix `BrowserHttpClientAdapter` canceled hangs # 4.0.5-beta1 - [Web] support send/receive progress in web platform From 2872c10738d248620625b98ae61f3e8f538be640 Mon Sep 17 00:00:00 2001 From: Peter Leibiger Date: Sat, 5 Feb 2022 02:46:31 +0100 Subject: [PATCH 16/33] ci: Run checkout in test reporter workflow --- .github/workflows/test-report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test-report.yml b/.github/workflows/test-report.yml index bd6ace890..41c8cd267 100644 --- a/.github/workflows/test-report.yml +++ b/.github/workflows/test-report.yml @@ -14,6 +14,7 @@ jobs: report: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v2 - name: Download and Extract Artifacts env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} From 1975121133525e258442c8eefc250866e1f71676 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Feb 2022 14:31:27 +0000 Subject: [PATCH 17/33] Bump subosito/flutter-action from 2.2.1 to 2.3.0 Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.2.1 to 2.3.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/v2.2.1...v2.3.0) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/example-app.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/example-app.yml b/.github/workflows/example-app.yml index 4cda0b3e0..21afc0069 100644 --- a/.github/workflows/example-app.yml +++ b/.github/workflows/example-app.yml @@ -19,7 +19,7 @@ jobs: working-directory: example_flutter_app steps: - uses: actions/checkout@v2 - - uses: subosito/flutter-action@v2.2.1 + - uses: subosito/flutter-action@v2.3.0 with: cache: true channel: stable @@ -34,7 +34,7 @@ jobs: working-directory: example_flutter_app steps: - uses: actions/checkout@v2 - - uses: subosito/flutter-action@v2.2.1 + - uses: subosito/flutter-action@v2.3.0 with: cache: true channel: stable @@ -48,7 +48,7 @@ jobs: working-directory: example_flutter_app steps: - uses: actions/checkout@v2 - - uses: subosito/flutter-action@v2.2.1 + - uses: subosito/flutter-action@v2.3.0 with: cache: true channel: stable From 3b1d276d7255c11bab168cef4b1fa2fb98568510 Mon Sep 17 00:00:00 2001 From: YFdyh000 Date: Wed, 9 Feb 2022 22:15:45 +0800 Subject: [PATCH 18/33] Fix links in README docs --- README-ZH.md | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index 292b0568e..9118a71d7 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -39,8 +39,8 @@ void getHttp() async { | Plugins | Status | Description | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | -| [dio_cookie_manager](https://github.com/flutterchina/dio/tree/master/plugins/cookie_manager) | [![Pub](https://img.shields.io/pub/v/dio_http2_adapter.svg?style=flat-square)](https://pub.dartlang.org/packages/dio_http2_adapter) | A cookie manager for Dio | -| [dio_http2_adapter](https://github.com/flutterchina/dio/tree/master/plugins/http2_adapter) | [![Pub](https://img.shields.io/pub/v/dio_cookie_manager.svg?style=flat-square)](https://pub.dartlang.org/packages/dio_cookie_manager) | A Dio HttpClientAdapter which support Http/2.0 | +| [dio_cookie_manager](https://github.com/flutterchina/dio/tree/master/plugins/cookie_manager) | [![Pub](https://img.shields.io/pub/v/dio_cookie_manager.svg?style=flat-square)](https://pub.dartlang.org/packages/dio_cookie_manager) | A cookie manager for Dio | +| [dio_http2_adapter](https://github.com/flutterchina/dio/tree/master/plugins/http2_adapter) | [![Pub](https://img.shields.io/pub/v/dio_http2_adapter.svg?style=flat-square)](https://pub.dartlang.org/packages/dio_http2_adapter) | A Dio HttpClientAdapter which support Http/2.0 | | [dio_smart_retry](https://github.com/rodion-m/dio_smart_retry) | [![Pub](https://img.shields.io/pub/v/dio_smart_retry.svg?style=flat-square)](https://pub.dev/packages/dio_smart_retry) | Flexible retry library for Dio | | [http_certificate_pinning](https://github.com/diefferson/http_certificate_pinning) | [![Pub](https://img.shields.io/pub/v/http_certificate_pinning.svg?style=flat-square)](https://pub.dev/packages/http_certificate_pinning) | Https Certificate pinning for Flutter | | [curl_logger_dio_interceptor](https://github.com/OwnWeb/curl_logger_dio_interceptor) | [![Pub](https://img.shields.io/pub/v/curl_logger_dio_interceptor.svg?style=flat-square)](https://pub.dev/packages/curl_logger_dio_interceptor) | A Flutter curl-command generator for Dio. | diff --git a/README.md b/README.md index fcb3de72c..08657dce7 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ void getHttp() async { | Plugins | Status | Description | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | -| [dio_cookie_manager](https://github.com/flutterchina/dio/tree/master/plugins/cookie_manager) | [![Pub](https://img.shields.io/pub/v/dio_http2_adapter.svg?style=flat-square)](https://pub.dartlang.org/packages/dio_http2_adapter) | A cookie manager for Dio | -| [dio_http2_adapter](https://github.com/flutterchina/dio/tree/master/plugins/http2_adapter) | [![Pub](https://img.shields.io/pub/v/dio_cookie_manager.svg?style=flat-square)](https://pub.dartlang.org/packages/dio_cookie_manager) | A Dio HttpClientAdapter which support Http/2.0 | +| [dio_cookie_manager](https://github.com/flutterchina/dio/tree/master/plugins/cookie_manager) | [![Pub](https://img.shields.io/pub/v/dio_cookie_manager.svg?style=flat-square)](https://pub.dartlang.org/packages/dio_cookie_manager) | A cookie manager for Dio | +| [dio_http2_adapter](https://github.com/flutterchina/dio/tree/master/plugins/http2_adapter) | [![Pub](https://img.shields.io/pub/v/dio_http2_adapter.svg?style=flat-square)](https://pub.dartlang.org/packages/dio_http2_adapter) | A Dio HttpClientAdapter which support Http/2.0 | | [dio_smart_retry](https://github.com/rodion-m/dio_smart_retry) | [![Pub](https://img.shields.io/pub/v/dio_smart_retry.svg?style=flat-square)](https://pub.dev/packages/dio_smart_retry) | Flexible retry library for Dio | | [http_certificate_pinning](https://github.com/diefferson/http_certificate_pinning) | [![Pub](https://img.shields.io/pub/v/http_certificate_pinning.svg?style=flat-square)](https://pub.dev/packages/http_certificate_pinning) | Https Certificate pinning for Flutter | | [curl_logger_dio_interceptor](https://github.com/OwnWeb/curl_logger_dio_interceptor) | [![Pub](https://img.shields.io/pub/v/curl_logger_dio_interceptor.svg?style=flat-square)](https://pub.dev/packages/curl_logger_dio_interceptor) | A Flutter curl-command generator for Dio. | From f94a281ad5814bbed76a445bd5c79fe537769c51 Mon Sep 17 00:00:00 2001 From: Nikolai Simonov Date: Thu, 10 Feb 2022 16:30:47 +0300 Subject: [PATCH 19/33] Fix requestOption copyWith's argument type for data --- dio/lib/src/options.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dio/lib/src/options.dart b/dio/lib/src/options.dart index f84b92aba..5da0bbe41 100644 --- a/dio/lib/src/options.dart +++ b/dio/lib/src/options.dart @@ -467,7 +467,7 @@ class RequestOptions extends _RequestConfig with OptionsMixin { int? sendTimeout, int? receiveTimeout, int? connectTimeout, - String? data, + dynamic data, String? path, Map? queryParameters, String? baseUrl, From e0bb1c5e50b777d49b18684c929cc0ce15971d38 Mon Sep 17 00:00:00 2001 From: YFdyh000 Date: Sun, 13 Feb 2022 20:19:48 +0800 Subject: [PATCH 20/33] add badssl to exception_test.dart --- dio/test/exception_test.dart | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/dio/test/exception_test.dart b/dio/test/exception_test.dart index d5aeb034b..cbcb05190 100644 --- a/dio/test/exception_test.dart +++ b/dio/test/exception_test.dart @@ -1,5 +1,7 @@ +import 'dart:io'; import 'package:dio/dio.dart'; import 'package:test/test.dart'; +import 'package:dio/adapter.dart'; void main() { test('catch DioError', () async { @@ -29,4 +31,32 @@ void main() { expect(error, isNotNull); expect(error is Exception, isTrue); }); + + test('catch sslerror: hostname mismatch', () async { + dynamic error; + + try { + await Dio().get('https://wrong.host.badssl.com/'); + fail('did not throw'); + } on DioError catch (e) { + error = e; + } + expect(error, isNotNull); + expect(error is Exception, isTrue); + }); + + test('allow badssl', () async { + var dio = Dio(); + (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = + (HttpClient client) { + client.badCertificateCallback = + (X509Certificate cert, String host, int port) => true; + }; + var response = await dio.get('https://wrong.host.badssl.com/'); + expect(response.statusCode, 200); + response = await dio.get('https://expired.badssl.com/'); + expect(response.statusCode, 200); + response = await dio.get('https://self-signed.badssl.com/'); + expect(response.statusCode, 200); + }, testOn: "!browser"); } From 1d7e5947e45e0b94be1cd25e86d0beecf15c32b3 Mon Sep 17 00:00:00 2001 From: Lukas Kirner Date: Fri, 4 Mar 2022 14:57:35 +0100 Subject: [PATCH 21/33] Correct JSON MIME Type detection --- dio/lib/src/transformer.dart | 20 ++++++++++++-------- dio/test/mimetype_test.dart | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 dio/test/mimetype_test.dart diff --git a/dio/lib/src/transformer.dart b/dio/lib/src/transformer.dart index ebeb850cc..819007976 100644 --- a/dio/lib/src/transformer.dart +++ b/dio/lib/src/transformer.dart @@ -47,6 +47,15 @@ abstract class Transformer { listFormat: listFormat, ); } + + /// Following: https://mimesniff.spec.whatwg.org/#json-mime-type + static bool isJsonMimeType(String? contentType) { + if (contentType == null) return false; + final mediaType = MediaType.parse(contentType); + if (mediaType.mimeType == 'application/json') return true; + if (mediaType.mimeType == 'text/json') return true; + return mediaType.subtype.endsWith('+json'); + } } /// The default [Transformer] for [Dio]. If you want to custom the transformation of @@ -64,7 +73,7 @@ class DefaultTransformer extends Transformer { Future transformRequest(RequestOptions options) async { var data = options.data ?? ''; if (data is! String) { - if (_isJsonMime(options.contentType)) { + if (Transformer.isJsonMimeType(options.contentType)) { return json.encode(options.data); } else if (data is Map) { options.contentType = @@ -156,7 +165,8 @@ class DefaultTransformer extends Transformer { } if (responseBody.isNotEmpty && options.responseType == ResponseType.json && - _isJsonMime(response.headers[Headers.contentTypeHeader]?.first)) { + Transformer.isJsonMimeType( + response.headers[Headers.contentTypeHeader]?.first)) { final callback = jsonDecodeCallback; if (callback != null) { return callback(responseBody); @@ -166,10 +176,4 @@ class DefaultTransformer extends Transformer { } return responseBody; } - - bool _isJsonMime(String? contentType) { - if (contentType == null) return false; - return MediaType.parse(contentType).mimeType == - Headers.jsonMimeType.mimeType; - } } diff --git a/dio/test/mimetype_test.dart b/dio/test/mimetype_test.dart new file mode 100644 index 000000000..c72543b33 --- /dev/null +++ b/dio/test/mimetype_test.dart @@ -0,0 +1,16 @@ +import 'package:dio/dio.dart'; +import 'package:test/test.dart'; + +void main() { + test('JSON MimeType "application/json" ', () { + expect(Transformer.isJsonMimeType("application/json"), isTrue); + }); + + test('JSON MimeType "text/json" ', () { + expect(Transformer.isJsonMimeType("text/json"), isTrue); + }); + + test('JSON MimeType "application/vnd.example.com+json" ', () { + expect(Transformer.isJsonMimeType("text/json"), isTrue); + }); +} From 5ddb661ab0db2bf6570139e64ebe5463c08a1c41 Mon Sep 17 00:00:00 2001 From: Minsu Lee Date: Mon, 7 Mar 2022 12:22:23 +0900 Subject: [PATCH 22/33] fix: abort request when timeout occurs --- dio/lib/src/adapters/io_adapter.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index 862267f2e..1f53972a7 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -61,6 +61,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { } rethrow; } on TimeoutException { + request.abort(); _throwConnectingTimeout(); } @@ -76,6 +77,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { try { await future; } on TimeoutException { + request.abort(); throw DioError( requestOptions: options, error: 'Sending timeout[${options.sendTimeout}ms]', @@ -116,7 +118,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { ), ); //todo: to verify - responseStream.detachSocket().then((socket) => socket.close()); + responseStream.detachSocket().then((socket) => socket.destroy()); } else { sink.add(Uint8List.fromList(data)); } From cba129ccd2e524f7e65be18a99cdd09e6553aabc Mon Sep 17 00:00:00 2001 From: Lukas Kirner Date: Mon, 28 Mar 2022 11:33:46 +0200 Subject: [PATCH 23/33] Typo --- dio/test/mimetype_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dio/test/mimetype_test.dart b/dio/test/mimetype_test.dart index c72543b33..d01035dbf 100644 --- a/dio/test/mimetype_test.dart +++ b/dio/test/mimetype_test.dart @@ -11,6 +11,6 @@ void main() { }); test('JSON MimeType "application/vnd.example.com+json" ', () { - expect(Transformer.isJsonMimeType("text/json"), isTrue); + expect(Transformer.isJsonMimeType("application/vnd.example.com+json"), isTrue); }); } From 7308fd8d9f8368dc8a23ab0a339904b65b281015 Mon Sep 17 00:00:00 2001 From: Lukas Kirner Date: Tue, 29 Mar 2022 11:08:56 +0200 Subject: [PATCH 24/33] Format mimetype_test.dart --- dio/test/mimetype_test.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dio/test/mimetype_test.dart b/dio/test/mimetype_test.dart index d01035dbf..5b2fe5e3e 100644 --- a/dio/test/mimetype_test.dart +++ b/dio/test/mimetype_test.dart @@ -11,6 +11,7 @@ void main() { }); test('JSON MimeType "application/vnd.example.com+json" ', () { - expect(Transformer.isJsonMimeType("application/vnd.example.com+json"), isTrue); + expect( + Transformer.isJsonMimeType("application/vnd.example.com+json"), isTrue); }); } From a5d84a4c9557d400bd5774734122caa76fb14276 Mon Sep 17 00:00:00 2001 From: wendux <824783146@qq.com> Date: Tue, 29 Mar 2022 17:57:01 +0800 Subject: [PATCH 25/33] update doc --- README-ZH.md | 3 ++- README.md | 3 ++- dio/CHANGELOG.md | 4 ++-- dio/README-ZH.md | 3 ++- dio/README.md | 3 ++- dio/lib/src/dio.dart | 11 +++++++++-- dio/lib/src/dio_mixin.dart | 9 +++++++++ dio/pubspec.yaml | 2 +- dio/test/readtimeout_test.dart | 2 +- 9 files changed, 30 insertions(+), 10 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index 4bd97b50a..bad761406 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -13,7 +13,7 @@ dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截 ```yaml dependencies: - dio: ^4.0.5-beta1 + dio: ^4.0.5 ``` > 如果你是dio 3.x 用户,想了解4.0的变更,请参考 [4.x更新列表](./migration_to_4.x.md)! @@ -44,6 +44,7 @@ void getHttp() async { | [dio_smart_retry](https://github.com/rodion-m/dio_smart_retry) | [![Pub](https://img.shields.io/pub/v/dio_smart_retry.svg?style=flat-square)](https://pub.dev/packages/dio_smart_retry) | Flexible retry library for Dio | | [http_certificate_pinning](https://github.com/diefferson/http_certificate_pinning) | [![Pub](https://img.shields.io/pub/v/http_certificate_pinning.svg?style=flat-square)](https://pub.dev/packages/http_certificate_pinning) | Https Certificate pinning for Flutter | | [curl_logger_dio_interceptor](https://github.com/OwnWeb/curl_logger_dio_interceptor) | [![Pub](https://img.shields.io/pub/v/curl_logger_dio_interceptor.svg?style=flat-square)](https://pub.dev/packages/curl_logger_dio_interceptor) | A Flutter curl-command generator for Dio. | +| [dio_cache_interceptor](https://github.com/llfbandit/dio_cache_interceptor) | [![Pub](https://img.shields.io/pub/v/dio_cache_interceptor.svg?style=flat-square)](https://pub.dev/packages/dio_cache_interceptor) | Dio HTTP cache interceptor with multiple stores respecting HTTP directives (or not) | | [dio_http_cache](https://github.com/hurshi/dio-http-cache) | [![Pub](https://img.shields.io/pub/v/dio_http_cache.svg?style=flat-square)](https://pub.dev/packages/dio_http_cache) | A simple cache library for Dio like Rxcache in Android | | [pretty_dio_logger](https://github.com/Milad-Akarie/pretty_dio_logger) | [![Pub](https://img.shields.io/pub/v/pretty_dio_logger.svg?style=flat-square)](https://pub.dev/packages/pretty_dio_logger) | Pretty Dio logger is a Dio interceptor that logs network calls in a pretty, easy to read format. | diff --git a/README.md b/README.md index 124c94d2d..ae8395235 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ A powerful Http client for Dart, which supports Interceptors, Global configurati ```yaml dependencies: - dio: ^4.0.5-beta1 + dio: ^4.0.5 ``` > Already know Dio 3 and just want to learn about what's new in Dio 4? Check out the [Migration Guide](./migration_to_4.x.md)! @@ -43,6 +43,7 @@ void getHttp() async { | [dio_smart_retry](https://github.com/rodion-m/dio_smart_retry) | [![Pub](https://img.shields.io/pub/v/dio_smart_retry.svg?style=flat-square)](https://pub.dev/packages/dio_smart_retry) | Flexible retry library for Dio | | [http_certificate_pinning](https://github.com/diefferson/http_certificate_pinning) | [![Pub](https://img.shields.io/pub/v/http_certificate_pinning.svg?style=flat-square)](https://pub.dev/packages/http_certificate_pinning) | Https Certificate pinning for Flutter | | [curl_logger_dio_interceptor](https://github.com/OwnWeb/curl_logger_dio_interceptor) | [![Pub](https://img.shields.io/pub/v/curl_logger_dio_interceptor.svg?style=flat-square)](https://pub.dev/packages/curl_logger_dio_interceptor) | A Flutter curl-command generator for Dio. | +| [dio_cache_interceptor](https://github.com/llfbandit/dio_cache_interceptor) | [![Pub](https://img.shields.io/pub/v/dio_cache_interceptor.svg?style=flat-square)](https://pub.dev/packages/dio_cache_interceptor) | Dio HTTP cache interceptor with multiple stores respecting HTTP directives (or not) | | [dio_http_cache](https://github.com/hurshi/dio-http-cache) | [![Pub](https://img.shields.io/pub/v/dio_http_cache.svg?style=flat-square)](https://pub.dev/packages/dio_http_cache) | A simple cache library for Dio like Rxcache in Android | | [pretty_dio_logger](https://github.com/Milad-Akarie/pretty_dio_logger) | [![Pub](https://img.shields.io/pub/v/pretty_dio_logger.svg?style=flat-square)](https://pub.dev/packages/pretty_dio_logger) | Pretty Dio logger is a Dio interceptor that logs network calls in a pretty, easy to read format. | diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index d3db1a816..3b0b73c93 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -1,9 +1,9 @@ -# 4.0.5-beta1 +# 4.0.5 - [Web] support send/receive progress in web platform - refactor timeout logic - use 'arraybuffer' instead of 'blob' for xhr requests in web platform - +- # 4.0.4 - Fix fetching null data in a response diff --git a/dio/README-ZH.md b/dio/README-ZH.md index 4bd97b50a..bad761406 100644 --- a/dio/README-ZH.md +++ b/dio/README-ZH.md @@ -13,7 +13,7 @@ dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截 ```yaml dependencies: - dio: ^4.0.5-beta1 + dio: ^4.0.5 ``` > 如果你是dio 3.x 用户,想了解4.0的变更,请参考 [4.x更新列表](./migration_to_4.x.md)! @@ -44,6 +44,7 @@ void getHttp() async { | [dio_smart_retry](https://github.com/rodion-m/dio_smart_retry) | [![Pub](https://img.shields.io/pub/v/dio_smart_retry.svg?style=flat-square)](https://pub.dev/packages/dio_smart_retry) | Flexible retry library for Dio | | [http_certificate_pinning](https://github.com/diefferson/http_certificate_pinning) | [![Pub](https://img.shields.io/pub/v/http_certificate_pinning.svg?style=flat-square)](https://pub.dev/packages/http_certificate_pinning) | Https Certificate pinning for Flutter | | [curl_logger_dio_interceptor](https://github.com/OwnWeb/curl_logger_dio_interceptor) | [![Pub](https://img.shields.io/pub/v/curl_logger_dio_interceptor.svg?style=flat-square)](https://pub.dev/packages/curl_logger_dio_interceptor) | A Flutter curl-command generator for Dio. | +| [dio_cache_interceptor](https://github.com/llfbandit/dio_cache_interceptor) | [![Pub](https://img.shields.io/pub/v/dio_cache_interceptor.svg?style=flat-square)](https://pub.dev/packages/dio_cache_interceptor) | Dio HTTP cache interceptor with multiple stores respecting HTTP directives (or not) | | [dio_http_cache](https://github.com/hurshi/dio-http-cache) | [![Pub](https://img.shields.io/pub/v/dio_http_cache.svg?style=flat-square)](https://pub.dev/packages/dio_http_cache) | A simple cache library for Dio like Rxcache in Android | | [pretty_dio_logger](https://github.com/Milad-Akarie/pretty_dio_logger) | [![Pub](https://img.shields.io/pub/v/pretty_dio_logger.svg?style=flat-square)](https://pub.dev/packages/pretty_dio_logger) | Pretty Dio logger is a Dio interceptor that logs network calls in a pretty, easy to read format. | diff --git a/dio/README.md b/dio/README.md index 124c94d2d..ae8395235 100644 --- a/dio/README.md +++ b/dio/README.md @@ -12,7 +12,7 @@ A powerful Http client for Dart, which supports Interceptors, Global configurati ```yaml dependencies: - dio: ^4.0.5-beta1 + dio: ^4.0.5 ``` > Already know Dio 3 and just want to learn about what's new in Dio 4? Check out the [Migration Guide](./migration_to_4.x.md)! @@ -43,6 +43,7 @@ void getHttp() async { | [dio_smart_retry](https://github.com/rodion-m/dio_smart_retry) | [![Pub](https://img.shields.io/pub/v/dio_smart_retry.svg?style=flat-square)](https://pub.dev/packages/dio_smart_retry) | Flexible retry library for Dio | | [http_certificate_pinning](https://github.com/diefferson/http_certificate_pinning) | [![Pub](https://img.shields.io/pub/v/http_certificate_pinning.svg?style=flat-square)](https://pub.dev/packages/http_certificate_pinning) | Https Certificate pinning for Flutter | | [curl_logger_dio_interceptor](https://github.com/OwnWeb/curl_logger_dio_interceptor) | [![Pub](https://img.shields.io/pub/v/curl_logger_dio_interceptor.svg?style=flat-square)](https://pub.dev/packages/curl_logger_dio_interceptor) | A Flutter curl-command generator for Dio. | +| [dio_cache_interceptor](https://github.com/llfbandit/dio_cache_interceptor) | [![Pub](https://img.shields.io/pub/v/dio_cache_interceptor.svg?style=flat-square)](https://pub.dev/packages/dio_cache_interceptor) | Dio HTTP cache interceptor with multiple stores respecting HTTP directives (or not) | | [dio_http_cache](https://github.com/hurshi/dio-http-cache) | [![Pub](https://img.shields.io/pub/v/dio_http_cache.svg?style=flat-square)](https://pub.dev/packages/dio_http_cache) | A simple cache library for Dio like Rxcache in Android | | [pretty_dio_logger](https://github.com/Milad-Akarie/pretty_dio_logger) | [![Pub](https://img.shields.io/pub/v/pretty_dio_logger.svg?style=flat-square)](https://pub.dev/packages/pretty_dio_logger) | Pretty Dio logger is a Dio interceptor that logs network calls in a pretty, easy to read format. | diff --git a/dio/lib/src/dio.dart b/dio/lib/src/dio.dart index 6e22c2fe2..fe1268632 100644 --- a/dio/lib/src/dio.dart +++ b/dio/lib/src/dio.dart @@ -179,16 +179,23 @@ abstract class Dio { /// /// Dio will enqueue the incoming request tasks instead /// send them directly when [interceptor.requestOptions] is locked. - + @Deprecated( + 'Will delete in v5.0. Use `QueuedInterceptor` instead, more detail see' + ' https://github.com/flutterchina/dio/issues/1308') void lock(); /// Unlock the current Dio instance. /// /// Dio instance dequeue the request task。 + @Deprecated( + 'Will delete in v5.0. Use `QueuedInterceptor` instead, more detail see' + ' https://github.com/flutterchina/dio/issues/1308') void unlock(); ///Clear the current Dio instance waiting queue. - + @Deprecated( + 'Will delete in v5.0. Use `QueuedInterceptor` instead, more detail see' + ' https://github.com/flutterchina/dio/issues/1308') void clear(); /// Download the file and save it in local. The default http method is "GET", diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index f6f912d95..fd7a78e65 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -281,6 +281,9 @@ abstract class DioMixin implements Dio { /// /// Dio will enqueue the incoming request tasks instead /// send them directly when [interceptor.requestOptions] is locked. + @Deprecated( + 'Will delete in v5.0. Use `QueuedInterceptor` instead, more detail see' + ' https://github.com/flutterchina/dio/issues/1308') @override void lock() { interceptors.requestLock.lock(); @@ -289,12 +292,18 @@ abstract class DioMixin implements Dio { /// Unlock the current Dio instance. /// /// Dio instance dequeue the request task。 + @Deprecated( + 'Will delete in v5.0. Use `QueuedInterceptor` instead, more detail see' + ' https://github.com/flutterchina/dio/issues/1308') @override void unlock() { interceptors.requestLock.unlock(); } ///Clear the current Dio instance waiting queue. + @Deprecated( + 'Will delete in v5.0. Use `QueuedInterceptor` instead, more detail see' + ' https://github.com/flutterchina/dio/issues/1308') @override void clear() { interceptors.requestLock.clear(); diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 66d9cb6ba..2293a08a1 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: dio description: A powerful Http client for Dart, which supports Interceptors, FormData, Request Cancellation, File Downloading, Timeout etc. -version: 4.0.5-beta1 +version: 4.0.5 homepage: https://github.com/flutterchina/dio environment: diff --git a/dio/test/readtimeout_test.dart b/dio/test/readtimeout_test.dart index d5b68e9a7..b57d86782 100644 --- a/dio/test/readtimeout_test.dart +++ b/dio/test/readtimeout_test.dart @@ -59,7 +59,7 @@ void main() { dio.options ..baseUrl = serverUrl.toString() - ..receiveTimeout= SLEEP_DURATION_AFTER_CONNECTION_ESTABLISHED - 1000; + ..receiveTimeout = SLEEP_DURATION_AFTER_CONNECTION_ESTABLISHED - 1000; DioError error; From ab0c93e80d5e929c82d878306d9d69ad2352c1a8 Mon Sep 17 00:00:00 2001 From: wendux <824783146@qq.com> Date: Tue, 29 Mar 2022 18:02:55 +0800 Subject: [PATCH 26/33] update changelog --- dio/CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index 7d1c9407d..d30e380c3 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -1,13 +1,11 @@ -# Unreleased +# 4.0.5 - require Dart `2.12.1` which fixes exception handling for secure socket connections (https://github.com/dart-lang/sdk/issues/45214) - Only delete file if it exists when downloading. - Fix `BrowserHttpClientAdapter` canceled hangs - -# 4.0.5 +- Correct JSON MIME Type detection - [Web] support send/receive progress in web platform - refactor timeout logic - use 'arraybuffer' instead of 'blob' for xhr requests in web platform -- # 4.0.4 From f56ce111ae166acb46606c88b3bdd7911dc6c863 Mon Sep 17 00:00:00 2001 From: wendux <824783146@qq.com> Date: Tue, 29 Mar 2022 18:33:34 +0800 Subject: [PATCH 27/33] release 4.0.5 --- dio/lib/src/adapters/io_adapter.dart | 15 +++++++++------ dio/lib/src/transformer.dart | 6 +++--- dio/test/readtimeout_test.dart | 1 + 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index 1f53972a7..accb11760 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -97,11 +97,15 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { try { responseStream = await future; } on TimeoutException { - throw DioError( - requestOptions: options, - error: 'Receiving data timeout[${options.receiveTimeout}ms]', - type: DioErrorType.receiveTimeout, - ); + try { + await responseStream.detachSocket(); + } finally { + throw DioError( + requestOptions: options, + error: 'Receiving data timeout[${options.receiveTimeout}ms]', + type: DioErrorType.receiveTimeout, + ); + } } var stream = @@ -117,7 +121,6 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { type: DioErrorType.receiveTimeout, ), ); - //todo: to verify responseStream.detachSocket().then((socket) => socket.destroy()); } else { sink.add(Uint8List.fromList(data)); diff --git a/dio/lib/src/transformer.dart b/dio/lib/src/transformer.dart index 819007976..79062a4dd 100644 --- a/dio/lib/src/transformer.dart +++ b/dio/lib/src/transformer.dart @@ -52,9 +52,9 @@ abstract class Transformer { static bool isJsonMimeType(String? contentType) { if (contentType == null) return false; final mediaType = MediaType.parse(contentType); - if (mediaType.mimeType == 'application/json') return true; - if (mediaType.mimeType == 'text/json') return true; - return mediaType.subtype.endsWith('+json'); + return mediaType.mimeType == 'application/json' || + mediaType.mimeType == 'text/json' || + mediaType.subtype.endsWith('+json'); } } diff --git a/dio/test/readtimeout_test.dart b/dio/test/readtimeout_test.dart index 4878b6e9c..f19a44c29 100644 --- a/dio/test/readtimeout_test.dart +++ b/dio/test/readtimeout_test.dart @@ -73,6 +73,7 @@ void main() { } expect(error, isNotNull); + //print(error); expect(error.type == DioErrorType.receiveTimeout, isTrue); }); From ac78e6151e1736f945cb9b215bbcfac230e19cf1 Mon Sep 17 00:00:00 2001 From: wendux <824783146@qq.com> Date: Thu, 31 Mar 2022 13:04:59 +0800 Subject: [PATCH 28/33] fix #1452 --- README-ZH.md | 2 +- README.md | 2 +- dio/CHANGELOG.md | 3 +++ dio/README-ZH.md | 2 +- dio/README.md | 2 +- dio/lib/src/adapters/io_adapter.dart | 16 ++++++---------- dio/pubspec.yaml | 2 +- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index 6d2f60efc..0e1fdfd4c 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -13,7 +13,7 @@ dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截 ```yaml dependencies: - dio: ^4.0.5 + dio: ^4.0.6 ``` > 如果你是dio 3.x 用户,想了解4.0的变更,请参考 [4.x更新列表](./migration_to_4.x.md)! diff --git a/README.md b/README.md index ec70dc230..c825a3e21 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ A powerful Http client for Dart, which supports Interceptors, Global configurati ```yaml dependencies: - dio: ^4.0.5 + dio: ^4.0.6 ``` > Already know Dio 3 and just want to learn about what's new in Dio 4? Check out the [Migration Guide](./migration_to_4.x.md)! diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index d30e380c3..f83fd12d6 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -1,3 +1,6 @@ +# 4.0.6 +- fix #1452 + # 4.0.5 - require Dart `2.12.1` which fixes exception handling for secure socket connections (https://github.com/dart-lang/sdk/issues/45214) - Only delete file if it exists when downloading. diff --git a/dio/README-ZH.md b/dio/README-ZH.md index 229a32bf8..6760c18c3 100644 --- a/dio/README-ZH.md +++ b/dio/README-ZH.md @@ -13,7 +13,7 @@ dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截 ```yaml dependencies: - dio: ^4.0.5 + dio: ^4.0.6 ``` > 如果你是dio 3.x 用户,想了解4.0的变更,请参考 [4.x更新列表](./migration_to_4.x.md)! diff --git a/dio/README.md b/dio/README.md index c2c875f88..74962f53e 100644 --- a/dio/README.md +++ b/dio/README.md @@ -12,7 +12,7 @@ A powerful Http client for Dart, which supports Interceptors, Global configurati ```yaml dependencies: - dio: ^4.0.5 + dio: ^4.0.6 ``` > Already know Dio 3 and just want to learn about what's new in Dio 4? Check out the [Migration Guide](./migration_to_4.x.md)! diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index accb11760..430391075 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -44,6 +44,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { late HttpClientRequest request; try { + request = await reqFuture; if (options.connectTimeout > 0) { request = await reqFuture .timeout(Duration(milliseconds: options.connectTimeout)); @@ -61,7 +62,6 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { } rethrow; } on TimeoutException { - request.abort(); _throwConnectingTimeout(); } @@ -97,15 +97,11 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { try { responseStream = await future; } on TimeoutException { - try { - await responseStream.detachSocket(); - } finally { - throw DioError( - requestOptions: options, - error: 'Receiving data timeout[${options.receiveTimeout}ms]', - type: DioErrorType.receiveTimeout, - ); - } + throw DioError( + requestOptions: options, + error: 'Receiving data timeout[${options.receiveTimeout}ms]', + type: DioErrorType.receiveTimeout, + ); } var stream = diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index c23520f5a..86847c13f 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: dio description: A powerful Http client for Dart, which supports Interceptors, FormData, Request Cancellation, File Downloading, Timeout etc. -version: 4.0.5 +version: 4.0.6 homepage: https://github.com/flutterchina/dio environment: From 0e3e3f2d14ed7c67c0c75a14e994f6916e25142d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Wed, 19 Oct 2022 08:16:02 +0200 Subject: [PATCH 29/33] Update dio/lib/src/adapters/browser_adapter.dart Co-authored-by: Alex Li --- dio/lib/src/adapters/browser_adapter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dio/lib/src/adapters/browser_adapter.dart b/dio/lib/src/adapters/browser_adapter.dart index fb3e2bade..84313f16b 100644 --- a/dio/lib/src/adapters/browser_adapter.dart +++ b/dio/lib/src/adapters/browser_adapter.dart @@ -149,7 +149,7 @@ class BrowserHttpClientAdapter implements HttpClientAdapter { xhr.onError.first.then((_) { // Unfortunately, the underlying XMLHttpRequest API doesn't expose any // specific information about the error itself. - // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onerror + // See also: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onerror completer.completeError( DioError.connectionError( requestOptions: options, From 23c0c3f0a40a60ac4d1d4f37b772aa1dc517e060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Wed, 19 Oct 2022 08:16:44 +0200 Subject: [PATCH 30/33] Update dio/lib/src/adapters/io_adapter.dart --- dio/lib/src/adapters/io_adapter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index b9bf33109..80bd643ab 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -64,7 +64,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { requestOptions: options, timeout: options.connectTimeout ?? _httpClient.connectionTimeout ?? - Duration(), + Duration.zero, error: e, stackTrace: stackTrace, ); From 0bb6422bb23be698554883e74842ebb8802269dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Fri, 21 Oct 2022 19:38:10 +0200 Subject: [PATCH 31/33] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 7ce88ff4fb0d41f9115b10023908dda9f1a6d30d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKOKL(v5Ufsw2yR@uoGau8gP0TK0+L81ATc2B-^z34XsP}zBG2s1B2o=KHPh2I z!_?ySYXG)9ZXSU-fGOP(Cm+V<`|cyVtB4WlJmVc7IJ|8RuP^&i_T_+cAMlACj@bU> z?{~f>lLAse3P=GdAO)_hKo!{O?8@irI4K|n{=WkLeQ0#YUN|Jir-MVZ0K^HyVVp-V zL2Mo%_QD~N5t=2Hm{hA4!;;Q;tGr$~BqkkJ&4<;^Rvn7P?L5ClI;Up8x;= From 92b561724474e7e9e9252bb45483618b146619eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Fri, 21 Oct 2022 19:44:57 +0200 Subject: [PATCH 32/33] don't force unwrap --- dio/lib/src/adapters/io_adapter.dart | 6 +++--- dio/lib/src/dio_mixin.dart | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dio/lib/src/adapters/io_adapter.dart b/dio/lib/src/adapters/io_adapter.dart index b4edaabcf..1f30435b9 100644 --- a/dio/lib/src/adapters/io_adapter.dart +++ b/dio/lib/src/adapters/io_adapter.dart @@ -84,7 +84,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { onTimeout: () { request.abort(); throw DioError.sendTimeout( - timeout: options.sendTimeout!, + timeout: sendTimeout, requestOptions: options, ); }, @@ -102,7 +102,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { receiveTimeout, onTimeout: () { throw DioError.receiveTimeout( - timeout: options.receiveTimeout!, + timeout: receiveTimeout, requestOptions: options, ); }, @@ -120,7 +120,7 @@ class DefaultHttpClientAdapter implements HttpClientAdapter { if (receiveTimeout != null && duration > receiveTimeout) { sink.addError( DioError.receiveTimeout( - timeout: options.receiveTimeout!, + timeout: receiveTimeout, requestOptions: options, ), ); diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index 407a974b9..057a22a73 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -694,7 +694,7 @@ abstract class DioMixin implements Dio { return checkIfNeedEnqueue(interceptors.responseLock, () => ret); } else { throw DioError.badResponse( - statusCode: responseBody.statusCode, + statusCode: responseBody.statusCode!, requestOptions: reqOpt, response: ret, ); From 38c0b7287d20a188e1c5fa359f5a5dfb30dd48e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Ueko=CC=88tter?= Date: Fri, 21 Oct 2022 19:49:41 +0200 Subject: [PATCH 33/33] fix changelog --- dio/CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index 76bbd81d8..a05064e62 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -1,7 +1,13 @@ +# Unreleased 5.0 + +- Add option to instantiate a `HttpClientAdapter`, which is platform independent + # 4.0.6 + - fix #1452 # 4.0.5 + - require Dart `2.12.1` which fixes exception handling for secure socket connections (https://github.com/dart-lang/sdk/issues/45214) - Only delete file if it exists when downloading. - Fix `BrowserHttpClientAdapter` canceled hangs @@ -10,8 +16,8 @@ - refactor timeout logic - use 'arraybuffer' instead of 'blob' for xhr requests in web platform - # 4.0.4 + - Fix fetching null data in a response # 4.0.3