Skip to content

Commit 3f8512b

Browse files
committed
feat: update remove HTTP Response body from context
1 parent b373bbd commit 3f8512b

File tree

5 files changed

+57
-73
lines changed

5 files changed

+57
-73
lines changed

dart/lib/src/http_client/failed_request_client.dart

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ import 'sentry_http_client.dart';
6666
class FailedRequestClient extends BaseClient {
6767
FailedRequestClient({
6868
this.maxRequestBodySize = MaxRequestBodySize.never,
69-
this.maxResponseBodySize = MaxResponseBodySize.never,
7069
this.failedRequestStatusCodes = const [],
7170
this.captureFailedRequests = true,
7271
this.sendDefaultPii = false,
@@ -89,10 +88,6 @@ class FailedRequestClient extends BaseClient {
8988
/// This does not change whether an event is captured.
9089
final MaxRequestBodySize maxRequestBodySize;
9190

92-
/// Configures up to which size response bodies should be included in events.
93-
/// This does not change whether an event is captured.
94-
final MaxResponseBodySize maxResponseBodySize;
95-
9691
/// Describes which HTTP status codes should be considered as a failed
9792
/// requests.
9893
///
@@ -196,7 +191,9 @@ class FailedRequestClient extends BaseClient {
196191
event.contexts.response = SentryResponse(
197192
headers: sendDefaultPii ? response.headers : null,
198193
redirected: response.isRedirect,
199-
body: sendDefaultPii ? null : null, // TODO response.stream
194+
// Body not captured yet.
195+
// See https://github.com/getsentry/sentry-dart/pull/1093#issuecomment-1293056244
196+
body: null,
200197
statusCode: response.statusCode,
201198
status: response.reasonPhrase,
202199
);

dart/lib/src/http_client/sentry_http_client.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ class SentryHttpClient extends BaseClient {
8181
Hub? hub,
8282
bool recordBreadcrumbs = true,
8383
MaxRequestBodySize maxRequestBodySize = MaxRequestBodySize.never,
84-
MaxResponseBodySize maxResponseBodySize = MaxResponseBodySize.never,
8584
List<SentryStatusCode> failedRequestStatusCodes = const [],
8685
bool captureFailedRequests = false,
8786
bool sendDefaultPii = false,
@@ -95,7 +94,6 @@ class SentryHttpClient extends BaseClient {
9594
failedRequestStatusCodes: failedRequestStatusCodes,
9695
captureFailedRequests: captureFailedRequests,
9796
maxRequestBodySize: maxRequestBodySize,
98-
maxResponseBodySize: maxResponseBodySize,
9997
sendDefaultPii: sendDefaultPii,
10098
hub: _hub,
10199
client: innerClient,

dart/lib/src/protocol/sentry_response.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ class SentryResponse {
5454
factory SentryResponse.fromJson(Map<String, dynamic> json) {
5555
return SentryResponse(
5656
url: json['url'],
57-
headers: json['headers'],
57+
headers: json.containsKey('headers')
58+
? (json['headers'] as Map<String, dynamic>)
59+
.map((key, value) => MapEntry(key, value as String))
60+
: null,
5861
other: json['other'],
5962
body: json['body'],
6063
statusCode: json['status_code'],

dart/test/http_client/failed_request_client_test.dart

Lines changed: 25 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void main() {
3030
expect(fixture.transport.calls, 0);
3131
});
3232

33-
test('exception gets reported if client throws', () async {
33+
test('event reported if client throws', () async {
3434
final sut = fixture.getSut(
3535
client: createThrowingClient(),
3636
captureFailedRequests: true,
@@ -61,9 +61,12 @@ void main() {
6161
expect(request?.other.keys.contains('duration'), true);
6262
// ignore: deprecated_member_use_from_same_package
6363
expect(request?.other.keys.contains('content_length'), true);
64+
65+
// Response is not captured in case of exception
66+
expect(eventCall.contexts.response, isNull);
6467
});
6568

66-
test('exception gets not reported if disabled', () async {
69+
test('event not reported if disabled', () async {
6770
final sut = fixture.getSut(
6871
client: createThrowingClient(),
6972
captureFailedRequests: false,
@@ -77,9 +80,10 @@ void main() {
7780
expect(fixture.transport.calls, 0);
7881
});
7982

80-
test('exception gets reported if bad status code occurs', () async {
83+
test('event reported if bad status code occurs', () async {
8184
final sut = fixture.getSut(
82-
client: fixture.getClient(statusCode: 404, reason: 'Not Found'),
85+
client: fixture.getClient(
86+
statusCode: 404, reason: 'Not Found', headers: {'lorem': 'ipsum'}),
8387
badStatusCodes: [SentryStatusCode(404)],
8488
);
8589

@@ -114,6 +118,15 @@ void main() {
114118
expect(request?.other.keys.contains('duration'), true);
115119
// ignore: deprecated_member_use_from_same_package
116120
expect(request?.other.keys.contains('content_length'), true);
121+
122+
final response = eventCall.contexts.response!;
123+
expect(response.body, isNull);
124+
expect(response.statusCode, 404);
125+
expect(response.status, 'Not Found');
126+
expect(response.headers, equals({'lorem': 'ipsum'}));
127+
expect(response.other, isEmpty);
128+
expect(response.redirected, false);
129+
expect(response.url, isNull);
117130
});
118131

119132
test(
@@ -160,6 +173,7 @@ void main() {
160173
expect(event.request?.headers.isEmpty, true);
161174
expect(event.request?.cookies, isNull);
162175
expect(event.request?.data, isNull);
176+
expect(event.contexts.response?.headers.isEmpty, true);
163177
});
164178

165179
test('pii is not send on invalid status code', () async {
@@ -176,6 +190,8 @@ void main() {
176190
expect(fixture.transport.calls, 1);
177191
expect(event.request?.headers.isEmpty, true);
178192
expect(event.request?.cookies, isNull);
193+
expect(event.request?.data, isNull);
194+
expect(event.contexts.response?.headers.isEmpty, true);
179195
});
180196

181197
test('request body is included according to $MaxRequestBodySize', () async {
@@ -225,56 +241,6 @@ void main() {
225241
expect(capturedRequest?.data, scenario.matcher);
226242
}
227243
});
228-
229-
test('response body is included according to $MaxResponseBodySize',
230-
() async {
231-
final scenarios = [
232-
// never
233-
MaxBodySizeTestConfig(MaxResponseBodySize.never, 0, false),
234-
MaxBodySizeTestConfig(MaxResponseBodySize.never, 4001, false),
235-
MaxBodySizeTestConfig(MaxResponseBodySize.never, 10001, false),
236-
// always
237-
MaxBodySizeTestConfig(MaxResponseBodySize.always, 0, true),
238-
MaxBodySizeTestConfig(MaxResponseBodySize.always, 4001, true),
239-
MaxBodySizeTestConfig(MaxResponseBodySize.always, 10001, true),
240-
// small
241-
MaxBodySizeTestConfig(MaxResponseBodySize.small, 0, true),
242-
MaxBodySizeTestConfig(MaxResponseBodySize.small, 4000, true),
243-
MaxBodySizeTestConfig(MaxResponseBodySize.small, 4001, false),
244-
// medium
245-
MaxBodySizeTestConfig(MaxResponseBodySize.medium, 0, true),
246-
MaxBodySizeTestConfig(MaxResponseBodySize.medium, 4001, true),
247-
MaxBodySizeTestConfig(MaxResponseBodySize.medium, 10000, true),
248-
MaxBodySizeTestConfig(MaxResponseBodySize.medium, 10001, false),
249-
];
250-
251-
const errCode = 500;
252-
const errReason = 'Internal Server Error';
253-
254-
for (final scenario in scenarios) {
255-
fixture.transport.reset();
256-
257-
final sut = fixture.getSut(
258-
client: MockClient((request) => Future.value(Response(
259-
' ' * scenario.contentLength, errCode,
260-
reasonPhrase: errReason))),
261-
badStatusCodes: [SentryStatusCode(errCode)],
262-
captureFailedRequests: true,
263-
maxResponseBodySize: scenario.maxBodySize,
264-
);
265-
266-
final response = await sut.send(Request('GET', requestUri));
267-
expect(response.statusCode, errCode);
268-
expect(response.reasonPhrase, errReason);
269-
270-
expect(fixture.transport.calls, 1);
271-
272-
final eventCall = fixture.transport.events.first;
273-
final capturedResponse = eventCall.contexts.response;
274-
expect(capturedResponse, isNotNull);
275-
expect(capturedResponse?.body, scenario.matcher);
276-
}
277-
});
278244
});
279245
}
280246

@@ -302,7 +268,6 @@ class Fixture {
302268
MockClient? client,
303269
bool captureFailedRequests = false,
304270
MaxRequestBodySize maxRequestBodySize = MaxRequestBodySize.small,
305-
MaxResponseBodySize maxResponseBodySize = MaxResponseBodySize.small,
306271
List<SentryStatusCode> badStatusCodes = const [],
307272
bool sendDefaultPii = true,
308273
}) {
@@ -313,15 +278,17 @@ class Fixture {
313278
captureFailedRequests: captureFailedRequests,
314279
failedRequestStatusCodes: badStatusCodes,
315280
maxRequestBodySize: maxRequestBodySize,
316-
maxResponseBodySize: maxResponseBodySize,
317281
sendDefaultPii: sendDefaultPii,
318282
);
319283
}
320284

321-
MockClient getClient({int statusCode = 200, String? reason}) {
285+
MockClient getClient(
286+
{int statusCode = 200,
287+
String? reason,
288+
Map<String, String> headers = const {}}) {
322289
return MockClient((request) async {
323290
expect(request.url, requestUri);
324-
return Response('', statusCode, reasonPhrase: reason);
291+
return Response('', statusCode, reasonPhrase: reason, headers: headers);
325292
});
326293
}
327294
}

dart/test/mocks/mock_transport.dart

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,38 @@
11
import 'dart:convert';
22

33
import 'package:sentry/sentry.dart';
4+
import 'package:test/expect.dart';
45

56
class MockTransport implements Transport {
67
List<SentryEnvelope> envelopes = [];
78
List<SentryEvent> events = [];
8-
int calls = 0;
9+
10+
int _calls = 0;
11+
String _exceptions = '';
12+
13+
int get calls {
14+
expect(_exceptions, isEmpty);
15+
return _calls;
16+
}
917

1018
bool called(int calls) {
1119
return calls == calls;
1220
}
1321

1422
@override
1523
Future<SentryId> send(SentryEnvelope envelope) async {
16-
calls++;
24+
_calls++;
1725

18-
envelopes.add(envelope);
19-
final event = await _eventFromEnvelope(envelope);
20-
events.add(event);
26+
// Exception here would be swallowed by Sentry, making it hard to find test
27+
// failure causes. Instead, we log them and check on access to [calls].
28+
try {
29+
envelopes.add(envelope);
30+
final event = await _eventFromEnvelope(envelope);
31+
events.add(event);
32+
} catch (e, stack) {
33+
_exceptions += "$e\n$stack\n\n";
34+
rethrow;
35+
}
2136

2237
return envelope.header.eventId ?? SentryId.empty();
2338
}
@@ -31,6 +46,10 @@ class MockTransport implements Transport {
3146
final envelopeMap = envelopeItemJson as Map<String, dynamic>;
3247
final requestJson = envelopeMap['request'] as Map<String, dynamic>?;
3348

49+
// TODO the following code should really be part of fromJson() that handle those keys.
50+
// JSON being Map<String, dynamic> is nothing out of ordinary.
51+
// See [SentryResponse.fromJson()] as an example.
52+
3453
// '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, String>'
3554
final headersMap = requestJson?['headers'] as Map<String, dynamic>?;
3655
final newHeadersMap = <String, String>{};
@@ -56,7 +75,7 @@ class MockTransport implements Transport {
5675
void reset() {
5776
envelopes.clear();
5877
events.clear();
59-
calls = 0;
78+
_calls = 0;
6079
}
6180
}
6281

0 commit comments

Comments
 (0)