Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unhandled exception #29

Merged
merged 2 commits into from
Jan 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/src/data_classes/directus_error.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class DirectusError implements Exception {
/// Additional info that can be provided to error.
late final Map<String, Object?>? additionalInfo;

/// Original DioError from error.
late final DioError? dioError;

/// Constructor
DirectusError({
required this.message,
Expand Down Expand Up @@ -56,5 +59,6 @@ class DirectusError implements Exception {
'codeMessage': error.response?.statusMessage ?? 'Error',
'response': error.response
};
dioError = error;
}
}
14 changes: 9 additions & 5 deletions lib/src/modules/auth/auth_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,15 @@ class AuthHandler with StaticToken {
return handler.next(options);
}

final response = await manuallyRefresh();
if (response?.accessToken != null) {
options.headers['Authorization'] = response!.accessToken;
} else {
options.headers.remove('Authorization');
try {
final response = await manuallyRefresh();
if (response?.accessToken != null) {
options.headers['Authorization'] = response!.accessToken;
} else {
options.headers.remove('Authorization');
}
} on DirectusError catch (e) {
return handler.reject(e.dioError!);
}

return handler.next(options);
Expand Down
19 changes: 19 additions & 0 deletions test/src/data_classes/directus_error_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,23 @@ void main() {
expect(error.code, 400);
expect(error.message, 'API message');
});

test('that DirectusError will keep the original DioError', () {
final dioError = DioError(
requestOptions: RequestOptions(path: '/'),
response: Response(
requestOptions: RequestOptions(path: '/'),
data: {
'errors': [
{'message': 'API message'}
]
},
statusCode: 400,
statusMessage: 'Bad Request',
),
);
final error = DirectusError.fromDio(dioError);

expect(error.dioError, dioError);
});
}
30 changes: 30 additions & 0 deletions test/src/modules/auth/auth_handler_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,36 @@ void main() {
verify(interceptorHandler.next(any)).called(1);
});

test('refreshing token rethrows DioError when manuallyRefresh failed',
() async {
final dioError = DioError(
requestOptions: RequestOptions(path: '/'),
response: Response(
requestOptions: RequestOptions(path: '/'),
data: 'error',
));
final interceptorHandler = MockRequestInterceptorHandler();

when(refreshClient.post(any, data: anyNamed('data'))).thenAnswer(
(realInvocation) {
throw dioError;
},
);

// Setup for forcing refresh token
auth.tokens = mockAuthResponse();
auth.tokens!.accessTokenExpiresAt =
DateTime.now().add(Duration(seconds: 4));

await auth.refreshExpiredTokenInterceptor(
RequestOptions(path: '/'),
interceptorHandler,
);

// Check for the same dioError is thrown
verify(interceptorHandler.reject(dioError)).called(1);
});

test('client is unlocked if refresh throws an error', () async {
when(refreshClient.post(any, data: anyNamed('data')))
.thenAnswer((realInvocation) {
Expand Down