Line data Source code
1 : import 'dart:async'; 2 : import 'dart:collection'; 3 : 4 : import 'options.dart'; 5 : import 'dio_error.dart'; 6 : import 'response.dart'; 7 : 8 : typedef InterceptorSendCallback = dynamic Function(RequestOptions options); 9 : typedef InterceptorErrorCallback = dynamic Function(DioError e); 10 : typedef InterceptorSuccessCallback = dynamic Function(Response e); 11 : typedef EnqueueCallback = FutureOr Function(); 12 : 13 : /// Add lock/unlock API for interceptors. 14 : class Lock { 15 : Future _lock; 16 : Completer _completer; 17 : 18 : /// Whether this interceptor has been locked. 19 10 : bool get locked => _lock != null; 20 : 21 : /// Lock the interceptor. 22 : /// 23 : /// Once the request/response interceptor is locked, the incoming request/response 24 : /// will be added to a queue before they enter the interceptor, they will not be 25 : /// continued until the interceptor is unlocked. 26 1 : void lock() { 27 1 : if (!locked) { 28 2 : _completer = Completer(); 29 3 : _lock = _completer.future; 30 : } 31 : } 32 : 33 : /// Unlock the interceptor. please refer to [lock()] 34 1 : void unlock() { 35 1 : if (locked) { 36 2 : _completer.complete(); 37 1 : _lock = null; 38 : } 39 : } 40 : 41 : /// Clean the interceptor queue. 42 0 : void clear([String msg = 'cancelled']) { 43 0 : if (locked) { 44 0 : _completer.completeError(msg); 45 0 : _lock = null; 46 : } 47 : } 48 : 49 : /// If the interceptor is locked, the incoming request/response task 50 : /// will enter a queue. 51 : /// 52 : /// [callback] the function will return a `Future` 53 : /// @nodoc 54 1 : Future enqueue(EnqueueCallback callback) { 55 1 : if (locked) { 56 : // we use a future as a queue 57 4 : return _lock.then((d) => callback()); 58 : } 59 : return null; 60 : } 61 : } 62 : 63 : /// Dio instance may have interceptor(s) by which you can intercept 64 : /// requests or responses before they are handled by `then` or `catchError`. 65 : class Interceptor { 66 : /// The callback will be executed before the request is initiated. 67 : /// 68 : /// If you want to resolve the request with some custom data, 69 : /// you can return a [Response] object or return [dio.resolve]. 70 : /// If you want to reject the request with a error message, 71 : /// you can return a [DioError] object or return [dio.reject] . 72 : /// If you want to continue the request, return the [Options] object. 73 : /// ```dart 74 : /// Future onRequest(RequestOptions options) => dio.resolve('fake data'); 75 : /// ... 76 : /// print(response.data) // 'fake data'; 77 : /// ``` 78 1 : Future onRequest(RequestOptions options) async => options; 79 : 80 : /// The callback will be executed on success. 81 : /// 82 : /// If you want to reject the request with a error message, 83 : /// you can return a [DioError] object or return [dio.reject] . 84 : /// If you want to continue the request, return the [Response] object. 85 1 : Future onResponse(Response response) async => response; 86 : 87 : /// The callback will be executed on error. 88 : /// 89 : /// If you want to resolve the request with some custom data, 90 : /// you can return a [Response] object or return [dio.resolve]. 91 : /// If you want to continue the request, return the [DioError] object. 92 0 : Future onError(DioError err) async => err; 93 : } 94 : 95 : class InterceptorsWrapper extends Interceptor { 96 : final InterceptorSendCallback _onRequest; 97 : final InterceptorSuccessCallback _onResponse; 98 : final InterceptorErrorCallback _onError; 99 : 100 1 : InterceptorsWrapper({ 101 : InterceptorSendCallback onRequest, 102 : InterceptorSuccessCallback onResponse, 103 : InterceptorErrorCallback onError, 104 : }) : _onRequest = onRequest, 105 : _onResponse = onResponse, 106 : _onError = onError; 107 : 108 : @override 109 1 : Future onRequest(RequestOptions options) async { 110 1 : if (_onRequest != null) { 111 1 : return _onRequest(options); 112 : } 113 : } 114 : 115 : @override 116 1 : Future onResponse(Response response) async { 117 1 : if (_onResponse != null) { 118 1 : return _onResponse(response); 119 : } 120 : } 121 : 122 : @override 123 1 : Future onError(DioError err) async { 124 1 : if (_onError != null) { 125 1 : return _onError(err); 126 : } 127 : } 128 : } 129 : 130 : class Interceptors extends ListMixin<Interceptor> { 131 : final _list = <Interceptor>[]; 132 : final Lock _requestLock = Lock(); 133 : final Lock _responseLock = Lock(); 134 : final Lock _errorLock = Lock(); 135 : 136 10 : Lock get requestLock => _requestLock; 137 : 138 6 : Lock get responseLock => _responseLock; 139 : 140 0 : Lock get errorLock => _errorLock; 141 : 142 : @override 143 : int length = 0; 144 : 145 2 : @override 146 : Interceptor operator [](int index) { 147 4 : return _list[index]; 148 : } 149 : 150 2 : @override 151 : void operator []=(int index, value) { 152 6 : if (_list.length == index) { 153 4 : _list.add(value); 154 : } else { 155 2 : _list[index] = value; 156 : } 157 : } 158 : }