Skip to content
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
13 changes: 11 additions & 2 deletions example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,17 @@ class ExampleEventListener implements SturdyHttpEventListener {
print('decoding error');
case AuthFailure():
print('auth failure');
case MutativeRequestSuccess():
print('mutative request success');
case RequestCompleted(
:final headers,
:final statusCode,
:final isSuccess,
:final shouldTriggerDataMutation,
):
print('request completed: $statusCode, success: $isSuccess');
print('headers: $headers');
if (shouldTriggerDataMutation) {
print('mutative request success');
}
}
}
}
14 changes: 12 additions & 2 deletions lib/src/sturdy_http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class SturdyHttp {
}
}
} on DioException catch (error) {
dioResponse = error.response;
switch (error.response?.statusCode) {
case 401:
await _onEvent(AuthFailure(request: error.requestOptions));
Expand Down Expand Up @@ -239,9 +240,18 @@ class SturdyHttp {
response = await send(request);
}

if (response.$2.isSuccess && request.shouldTriggerDataMutation) {
final dioResponse = response.$1;
if (dioResponse != null) {
await _onEvent(
MutativeRequestSuccess(request: response.$1!.requestOptions),
RequestCompleted(
request: dioResponse.requestOptions,
headers: dioResponse.headers.map.map(
(key, values) => MapEntry(key, values.join(', ')),
),
statusCode: dioResponse.statusCode,
isSuccess: response.$2.isSuccess,
shouldTriggerDataMutation: request.shouldTriggerDataMutation,
),
);
}

Expand Down
33 changes: 26 additions & 7 deletions lib/src/sturdy_http_event_listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,31 @@ final class AuthFailure extends SturdyHttpEvent {
AuthFailure({required super.request});
}

/// {@template mutative_request_success}
/// Indicates that a "mutative" request succeeded and the data on the client
/// likely does not match the data on the server.
/// See [NetworkRequest.shouldTriggerDataMutation].
/// {@template request_completed}
/// Indicates that a network request has completed and a response was received.
/// This event fires for all requests that receive any HTTP response,
/// regardless of success or error status.
/// {@endtemplate}
final class MutativeRequestSuccess extends SturdyHttpEvent {
/// {@macro mutative_request_success}
MutativeRequestSuccess({required super.request});
final class RequestCompleted extends SturdyHttpEvent {
/// The response headers.
final Map<String, String> headers;

/// The HTTP status code of the response, if available.
final int? statusCode;

/// Whether the response was successful (2xx status code).
final bool isSuccess;

/// Whether the request was marked as mutative (data-changing).
/// See [NetworkRequest.shouldTriggerDataMutation].
final bool shouldTriggerDataMutation;

/// {@macro request_completed}
RequestCompleted({
required super.request,
required this.headers,
required this.statusCode,
required this.isSuccess,
required this.shouldTriggerDataMutation,
});
}
33 changes: 33 additions & 0 deletions test/src/network_request_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:sturdy_http/sturdy_http.dart';
import 'package:test/test.dart';

void main() {
group('NetworkRequest', () {
group('shouldTriggerDataMutation defaults', () {
test('GetRequest defaults to false', () {
const request = GetRequest('/path');
expect(request.shouldTriggerDataMutation, isFalse);
});

test('PostRequest defaults to true', () {
final request = PostRequest('/path', data: JsonRequestBody({}));
expect(request.shouldTriggerDataMutation, isTrue);
});

test('PutRequest defaults to true', () {
final request = PutRequest('/path', data: JsonRequestBody({}));
expect(request.shouldTriggerDataMutation, isTrue);
});

test('DeleteRequest defaults to true', () {
const request = DeleteRequest('/path');
expect(request.shouldTriggerDataMutation, isTrue);
});

test('RawRequest defaults to true', () {
const request = RawRequest('/path', type: NetworkRequestType.Post);
expect(request.shouldTriggerDataMutation, isTrue);
});
});
});
}
Loading