Skip to content

Commit

Permalink
feat(neon_http_client): Do not wrap http.ClientException with Interce…
Browse files Browse the repository at this point in the history
…ptionException during interception

Signed-off-by: provokateurin <[email protected]>
  • Loading branch information
provokateurin committed Sep 9, 2024
1 parent f6b709a commit 5471fae
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ abstract interface class HttpInterceptor {
///
/// Provided requests are not finalized yet. It is an error for an interceptor
/// to finalize it by executing them.
///
/// Exceptions might be thrown during interception.
/// If the exception is an [http.ClientException] it will be thrown as is,
/// otherwise it wrapped as an `InterceptionException`.
FutureOr<http.BaseRequest> interceptRequest({required http.BaseRequest request});

/// Whether this interceptor should intercept response.
Expand All @@ -19,6 +23,10 @@ abstract interface class HttpInterceptor {
/// Intercepts the given [response].
///
/// Until package:http 2.0 makes [http.BaseResponseWithUrl] mandatory the request url is used.
///
/// Exceptions might be thrown during interception.
/// If the exception is an [http.ClientException] it will be thrown as is,
/// otherwise it wrapped as an `InterceptionException`.
FutureOr<http.StreamedResponse> interceptResponse({
required http.StreamedResponse response,
required Uri url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ final class NeonHttpClient with http.BaseClient {
interceptedRequest = await interceptor.interceptRequest(
request: interceptedRequest,
);
} catch (_, stackTrace) {
} catch (error, stackTrace) {
if (error is http.ClientException) {
rethrow;
}

Error.throwWithStackTrace(
InterceptionException('Failed to intercept request', request.url),
stackTrace,
Expand Down Expand Up @@ -131,7 +135,11 @@ final class NeonHttpClient with http.BaseClient {
response: interceptedResponse,
url: url,
);
} catch (_, stackTrace) {
} catch (error, stackTrace) {
if (error is http.ClientException) {
rethrow;
}

Error.throwWithStackTrace(
InterceptionException('Failed to intercept response', request.url),
stackTrace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:http/testing.dart';
import 'package:mocktail/mocktail.dart';
import 'package:neon_http_client/src/interceptors/interceptors.dart';
import 'package:neon_http_client/src/neon_http_client.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:test/test.dart';

class _MockCookieStore extends Mock implements CookieStore {}
Expand Down Expand Up @@ -137,7 +138,26 @@ void main() {
).called(1);
});

test('rethrows errors as InterceptionFailure', () async {
test('rethrows http.ClientExceptions', () async {
final exception = DynamiteStatusCodeException(Response('', 404));
when(() => interceptor.shouldInterceptRequest(any())).thenReturn(true);
when(
() => interceptor.interceptRequest(request: any(named: 'request')),
).thenThrow(exception);

expect(client.get(uri), throwsA(exception));

when(() => interceptor.shouldInterceptRequest(any())).thenReturn(true);
when(() => interceptor.interceptRequest(request: any(named: 'request'))).thenReturn(fakeRequest());
when(() => interceptor.shouldInterceptResponse(any())).thenReturn(true);
when(
() => interceptor.interceptResponse(response: any(named: 'response'), url: any(named: 'url')),
).thenThrow(exception);

expect(client.get(uri), throwsA(exception));
});

test('rethrows non-http.ClientExceptions as InterceptionFailure', () async {
when(() => interceptor.shouldInterceptRequest(any())).thenReturn(true);
when(
() => interceptor.interceptRequest(request: any(named: 'request')),
Expand Down

0 comments on commit 5471fae

Please sign in to comment.