Skip to content

Instantly share code, notes, and snippets.

@arafaysaleem
Created July 4, 2022 08:00
Show Gist options
  • Save arafaysaleem/d6302b9b8f9684e084b4200f7c4bb363 to your computer and use it in GitHub Desktop.
Save arafaysaleem/d6302b9b8f9684e084b4200f7c4bb363 to your computer and use it in GitHub Desktop.
Api Interceptor For Network Layer
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// Providers
import '../../../features/all_providers.dart';
/// A class that holds intercepting logic for API related requests. This is
/// the first interceptor in case of both request and response.
///
/// Primary purpose is to handle token injection and response success validation
///
/// Since this interceptor isn't responsible for error handling, if an exception
/// occurs it is passed on the next [Interceptor] or to [Dio].
class ApiInterceptor extends Interceptor {
late final Ref _ref;
ApiInterceptor(this._ref) : super();
/// This method intercepts an out-going request before it reaches the
/// destination.
///
/// [options] contains http request information and configuration.
/// [handler] is used to forward, resolve, or reject requests.
///
/// This method is used to inject any token/API keys in the request.
///
/// The [RequestInterceptorHandler] in each method controls the what will
/// happen to the intercepted request. It has 3 possible options:
///
/// - [handler.next]/[super.onRequest], if you want to forward the request.
/// - [handler.resolve]/[super.onResponse], if you want to resolve the
/// request with your custom [Response]. All ** request ** interceptors are ignored.
/// - [handler.reject]/[super.onError], if you want to fail the request
/// with your custom [DioError].
@override
Future<void> onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) async {
if (options.extra.containsKey('requiresAuthToken')) {
if (options.extra['requiresAuthToken'] == true) {
final token =
await _ref.watch(keyValueStorageServiceProvider).getAuthToken();
options.headers.addAll(
<String, Object?>{'Authorization': 'Bearer $token'},
);
}
options.extra.remove('requiresAuthToken');
}
return handler.next(options);
}
/// This method intercepts an incoming response before it reaches Dio.
///
/// [response] contains http [Response] info.
/// [handler] is used to forward, resolve, or reject responses.
///
/// This method is used to check the success of the response by verifying
/// its headers.
///
/// If response is successful, it is simply passed on. It may again be
/// intercepted if there are any after it. If none, it is passed to [Dio].
///
/// Else if response indicates failure, a [DioError] is thrown with the
/// response and original request's options.
///
/// ** The success criteria is dependant on the API and may not always be
/// the same. It might need changing according to your own API. **
///
/// The [RequestInterceptorHandler] in each method controls the what will
/// happen to the intercepted response. It has 3 possible options:
///
/// - [handler.next]/[super.onRequest], if you want to forward the [Response].
/// - [handler.resolve]/[super.onResponse], if you want to resolve the
/// [Response] with your custom data. All ** response ** interceptors are ignored.
/// - [handler.reject]/[super.onError], if you want to fail the response
/// with your custom [DioError].
@override
void onResponse(
Response response,
ResponseInterceptorHandler handler,
) {
final success = response.data['headers']['error'] == 0;
if (success) return handler.next(response);
//Reject all error codes from server except 402 and 200 OK
return handler.reject(
DioError(
requestOptions: response.requestOptions,
response: response,
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment