diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index 276a68eeb..78e72a7aa 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -11,6 +11,7 @@ See the [Migration Guide][] for the complete breaking changes list.** On web, timeout handling is best-effort because synchronous JavaScript work cannot be preempted. - Fix `FormData.clone()` dropping `boundaryName` and `camelCaseContentDisposition`, so a retried multipart request now keeps the original options instead of silently falling back to the defaults. - Fix `QueuedInterceptor` stalling its queue forever when the active request is cancelled while its callback is still pending (never calls `next`/`resolve`/`reject`), which blocked every subsequent request routed through the interceptor. +- Fix `ErrorInterceptorHandler.reject(..., true)` not continuing to following error interceptors in queued interceptors. ## 5.9.2 diff --git a/dio/lib/src/interceptor.dart b/dio/lib/src/interceptor.dart index ad9feb278..4e12dc8b8 100644 --- a/dio/lib/src/interceptor.dart +++ b/dio/lib/src/interceptor.dart @@ -178,10 +178,24 @@ class ErrorInterceptorHandler extends _BaseHandler { } /// Completes the request by reject with the [error] as the result. - void reject(DioException error) { + /// + /// Invoking the method will make the rest of interceptors in the queue + /// skipped to handle the request, + /// unless [callFollowingErrorInterceptor] is true + /// which delivers [InterceptorResultType.rejectCallFollowing] + /// to the [InterceptorState]. + void reject( + DioException error, [ + bool callFollowingErrorInterceptor = false, + ]) { _throwIfCompleted(); _completer.completeError( - InterceptorState(error, InterceptorResultType.reject), + InterceptorState( + error, + callFollowingErrorInterceptor + ? InterceptorResultType.rejectCallFollowing + : InterceptorResultType.reject, + ), error.stackTrace, ); _processNextInQueue?.call(); diff --git a/dio/test/interceptor_test.dart b/dio/test/interceptor_test.dart index 6237975dd..8ffc88b38 100644 --- a/dio/test/interceptor_test.dart +++ b/dio/test/interceptor_test.dart @@ -844,6 +844,39 @@ void main() { expect(tokenRequestCounts, 1); expect(result, 3); }); + + test( + 'error interceptor reject with callFollowingErrorInterceptor continues', + () async { + final dio = Dio() + ..options.baseUrl = MockAdapter.mockBase + ..httpClientAdapter = MockAdapter(); + + dio.interceptors + ..add( + QueuedInterceptorsWrapper( + onError: (error, handler) { + handler.reject(error.copyWith(error: 1), true); + }, + ), + ) + ..add( + QueuedInterceptorsWrapper( + onError: (error, handler) { + final count = error.error as int; + handler.next(error.copyWith(error: count + 1)); + }, + ), + ); + + expect( + dio + .get('/test-not-found') + .catchError((e) => throw (e as DioException).error as int), + throwsA(2), + ); + }, + ); }); group('LogInterceptor', () {