Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
attach response data in dio event processor
  • Loading branch information
denrase committed Jul 18, 2023
commit aa95370b7e7e2d174cff065adefc7029f38fb25b
18 changes: 18 additions & 0 deletions dio/lib/src/dio_event_processor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,24 @@ class DioEventProcessor implements EventProcessor {
headers: _options.sendDefaultPii ? headers : null,
bodySize: dioError.response?.data?.length as int?,
statusCode: response?.statusCode,
data: _getResponseData(dioError.response?.data),
);
}

/// Returns the response data, if possible according to the users settings.
Object? _getResponseData(dynamic data) {
if (!_options.sendDefaultPii) {
return null;
}
if (data is String) {
if (_options.maxResponseBodySize.shouldAddBody(data.codeUnits.length)) {
return data;
}
} else if (data is List<int>) {
if (_options.maxResponseBodySize.shouldAddBody(data.length)) {
return data;
}
}
return null;
}
}
141 changes: 138 additions & 3 deletions dio/test/dio_event_processor_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,122 @@ void main() {
expect(processedEvent.exceptions?[1].value, exception.toString());
expect(processedEvent.exceptions?[1].stackTrace, isNotNull);
});

test('request body is included according to $MaxResponseBodySize', () async {
final scenarios = [
// never
MaxBodySizeTestConfig(MaxRequestBodySize.never, 0, false),
MaxBodySizeTestConfig(MaxRequestBodySize.never, 4001, false),
MaxBodySizeTestConfig(MaxRequestBodySize.never, 10001, false),
// always
MaxBodySizeTestConfig(MaxRequestBodySize.always, 0, true),
MaxBodySizeTestConfig(MaxRequestBodySize.always, 4001, true),
MaxBodySizeTestConfig(MaxRequestBodySize.always, 10001, true),
// small
MaxBodySizeTestConfig(MaxRequestBodySize.small, 0, true),
MaxBodySizeTestConfig(MaxRequestBodySize.small, 4000, true),
MaxBodySizeTestConfig(MaxRequestBodySize.small, 4001, false),
// medium
MaxBodySizeTestConfig(MaxRequestBodySize.medium, 0, true),
MaxBodySizeTestConfig(MaxRequestBodySize.medium, 4001, true),
MaxBodySizeTestConfig(MaxRequestBodySize.medium, 10000, true),
MaxBodySizeTestConfig(MaxRequestBodySize.medium, 10001, false),
];

for (final scenario in scenarios) {
final sut = fixture.getSut(
sendDefaultPii: true,
captureFailedRequests: true,
maxRequestBodySize: scenario.maxBodySize,
);

final data = List.generate(scenario.contentLength, (index) => 0);
final request = requestOptions.copyWith(method: 'POST', data: data);
final throwable = Exception();
final dioError = DioError(
requestOptions: request,
response: Response<dynamic>(
requestOptions: request,
statusCode: 401,
data: data,
),
);
final event = SentryEvent(
throwable: throwable,
exceptions: [
fixture.sentryError(throwable),
fixture.sentryError(dioError)
],
);
final processedEvent = sut.apply(event) as SentryEvent;
final capturedRequest = processedEvent.request;

expect(capturedRequest, isNotNull);
expect(
capturedRequest?.data,
scenario.shouldBeIncluded ? isNotNull : isNull,
);
}
});

test('response body is included according to $MaxResponseBodySize', () async {
final scenarios = [
// never
MaxBodySizeTestConfig(MaxResponseBodySize.never, 0, false),
MaxBodySizeTestConfig(MaxResponseBodySize.never, 4001, false),
MaxBodySizeTestConfig(MaxResponseBodySize.never, 10001, false),
// always
MaxBodySizeTestConfig(MaxResponseBodySize.always, 0, true),
MaxBodySizeTestConfig(MaxResponseBodySize.always, 4001, true),
MaxBodySizeTestConfig(MaxResponseBodySize.always, 10001, true),
// small
MaxBodySizeTestConfig(MaxResponseBodySize.small, 0, true),
MaxBodySizeTestConfig(MaxResponseBodySize.small, 4000, true),
MaxBodySizeTestConfig(MaxResponseBodySize.small, 4001, false),
// medium
MaxBodySizeTestConfig(MaxResponseBodySize.medium, 0, true),
MaxBodySizeTestConfig(MaxResponseBodySize.medium, 4001, true),
MaxBodySizeTestConfig(MaxResponseBodySize.medium, 10000, true),
MaxBodySizeTestConfig(MaxResponseBodySize.medium, 10001, false),
];

fixture.options.captureFailedRequests = true;

for (final scenario in scenarios) {
final sut = fixture.getSut(
sendDefaultPii: true,
captureFailedRequests: true,
maxResponseBodySize: scenario.maxBodySize,
);

final data = List.generate(scenario.contentLength, (index) => 0);
final request = requestOptions.copyWith(method: 'POST', data: data);
final throwable = Exception();
final dioError = DioError(
requestOptions: request,
response: Response<dynamic>(
requestOptions: request,
statusCode: 401,
data: data,
),
);
final event = SentryEvent(
throwable: throwable,
exceptions: [
fixture.sentryError(throwable),
fixture.sentryError(dioError)
],
);
final processedEvent = sut.apply(event) as SentryEvent;
final capturedResponse = processedEvent.contexts.response;

expect(capturedResponse, isNotNull);
expect(
capturedResponse?.data,
scenario.shouldBeIncluded ? isNotNull : isNull,
);
}
});
}

final requestOptions = RequestOptions(
Expand All @@ -266,12 +382,17 @@ class Fixture {
// ignore: invalid_use_of_internal_member
SentryExceptionFactory get exceptionFactory => options.exceptionFactory;

DioEventProcessor getSut({bool sendDefaultPii = false}) {
DioEventProcessor getSut({
bool sendDefaultPii = false,
bool captureFailedRequests = true,
MaxRequestBodySize maxRequestBodySize = MaxRequestBodySize.always,
MaxResponseBodySize maxResponseBodySize = MaxResponseBodySize.always,
}) {
return DioEventProcessor(
options
..sendDefaultPii = sendDefaultPii
..maxRequestBodySize = MaxRequestBodySize.always
..maxResponseBodySize = MaxResponseBodySize.always,
..maxRequestBodySize = maxRequestBodySize
..maxResponseBodySize = maxResponseBodySize,
);
}

Expand All @@ -283,3 +404,17 @@ class Fixture {
);
}
}

class MaxBodySizeTestConfig<T> {
MaxBodySizeTestConfig(
this.maxBodySize,
this.contentLength,
this.shouldBeIncluded,
);

final T maxBodySize;
final int contentLength;
final bool shouldBeIncluded;

Matcher get matcher => shouldBeIncluded ? isNotNull : isNull;
}