@@ -2,11 +2,9 @@ import 'dart:async';
22import 'dart:convert' ;
33
44import 'package:http/http.dart' ;
5+ import '../utils/transport_utils.dart' ;
6+ import 'http_transport_request_handler.dart' ;
57
6- import '../client_reports/client_report_recorder.dart' ;
7- import '../client_reports/discard_reason.dart' ;
8- import 'data_category.dart' ;
9- import 'noop_encode.dart' if (dart.library.io) 'encode.dart' ;
108import '../noop_client.dart' ;
119import '../protocol.dart' ;
1210import '../sentry_options.dart' ;
@@ -18,15 +16,9 @@ import 'rate_limiter.dart';
1816class HttpTransport implements Transport {
1917 final SentryOptions _options;
2018
21- final Dsn _dsn;
22-
2319 final RateLimiter _rateLimiter;
2420
25- final ClientReportRecorder _recorder;
26-
27- late _CredentialBuilder _credentialBuilder;
28-
29- final Map <String , String > _headers;
21+ final HttpTransportRequestHandler _requestHandler;
3022
3123 factory HttpTransport (SentryOptions options, RateLimiter rateLimiter) {
3224 if (options.httpClient is NoOpClient ) {
@@ -37,17 +29,8 @@ class HttpTransport implements Transport {
3729 }
3830
3931 HttpTransport ._(this ._options, this ._rateLimiter)
40- : _dsn = Dsn .parse (_options.dsn! ),
41- _recorder = _options.recorder,
42- _headers = _buildHeaders (
43- _options.platformChecker.isWeb,
44- _options.sentryClientName,
45- ) {
46- _credentialBuilder = _CredentialBuilder (
47- _dsn,
48- _options.sentryClientName,
49- );
50- }
32+ : _requestHandler = HttpTransportRequestHandler (
33+ _options, Dsn .parse (_options.dsn! ).postUri);
5134
5235 @override
5336 Future <SentryId ?> send (SentryEnvelope envelope) async {
@@ -57,63 +40,31 @@ class HttpTransport implements Transport {
5740 }
5841 filteredEnvelope.header.sentAt = _options.clock ();
5942
60- final streamedRequest = await _createStreamedRequest (filteredEnvelope);
43+ final streamedRequest =
44+ await _requestHandler.createRequest (filteredEnvelope);
45+
6146 final response = await _options.httpClient
6247 .send (streamedRequest)
6348 .then (Response .fromStream);
6449
6550 _updateRetryAfterLimits (response);
6651
67- if (response.statusCode != 200 ) {
68- // body guard to not log the error as it has performance impact to allocate
69- // the body String.
70- if (_options.debug) {
71- _options.logger (
72- SentryLevel .error,
73- 'API returned an error, statusCode = ${response .statusCode }, '
74- 'body = ${response .body }' ,
75- );
76- }
77-
78- if (response.statusCode >= 400 && response.statusCode != 429 ) {
79- _recorder.recordLostEvent (
80- DiscardReason .networkError, DataCategory .error);
81- }
82-
83- return SentryId .empty ();
84- } else {
85- _options.logger (
86- SentryLevel .debug,
87- 'Envelope ${envelope .header .eventId ?? "--" } was sent successfully.' ,
88- );
89- }
52+ TransportUtils .logResponse (_options, envelope, response, target: 'Sentry' );
9053
91- final eventId = json.decode (response.body)['id' ];
92- if (eventId == null ) {
93- return null ;
54+ if (response.statusCode == 200 ) {
55+ return _parseEventId (response);
9456 }
95- return SentryId .fromId (eventId );
57+ return SentryId .empty ( );
9658 }
9759
98- Future <StreamedRequest > _createStreamedRequest (
99- SentryEnvelope envelope) async {
100- final streamedRequest = StreamedRequest ('POST' , _dsn.postUri);
101-
102- if (_options.compressPayload) {
103- final compressionSink = compressInSink (streamedRequest.sink, _headers);
104- envelope
105- .envelopeStream (_options)
106- .listen (compressionSink.add)
107- .onDone (compressionSink.close);
108- } else {
109- envelope
110- .envelopeStream (_options)
111- .listen (streamedRequest.sink.add)
112- .onDone (streamedRequest.sink.close);
60+ SentryId ? _parseEventId (Response response) {
61+ try {
62+ final eventId = json.decode (response.body)['id' ];
63+ return eventId != null ? SentryId .fromId (eventId) : null ;
64+ } catch (e) {
65+ _options.logger (SentryLevel .error, 'Error parsing response: $e ' );
66+ return null ;
11367 }
114- streamedRequest.headers.addAll (_credentialBuilder.configure (_headers));
115-
116- return streamedRequest;
11768 }
11869
11970 void _updateRetryAfterLimits (Response response) {
@@ -131,51 +82,3 @@ class HttpTransport implements Transport {
13182 sentryRateLimitHeader, retryAfterHeader, response.statusCode);
13283 }
13384}
134-
135- class _CredentialBuilder {
136- final String _authHeader;
137-
138- _CredentialBuilder ._(String authHeader) : _authHeader = authHeader;
139-
140- factory _CredentialBuilder (Dsn dsn, String sdkIdentifier) {
141- final authHeader = _buildAuthHeader (
142- publicKey: dsn.publicKey,
143- secretKey: dsn.secretKey,
144- sdkIdentifier: sdkIdentifier,
145- );
146-
147- return _CredentialBuilder ._(authHeader);
148- }
149-
150- static String _buildAuthHeader ({
151- required String publicKey,
152- String ? secretKey,
153- required String sdkIdentifier,
154- }) {
155- var header = 'Sentry sentry_version=7, sentry_client=$sdkIdentifier , '
156- 'sentry_key=$publicKey ' ;
157-
158- if (secretKey != null ) {
159- header += ', sentry_secret=$secretKey ' ;
160- }
161-
162- return header;
163- }
164-
165- Map <String , String > configure (Map <String , String > headers) {
166- return headers
167- ..addAll (
168- < String , String > {'X-Sentry-Auth' : _authHeader},
169- );
170- }
171- }
172-
173- Map <String , String > _buildHeaders (bool isWeb, String sdkIdentifier) {
174- final headers = {'Content-Type' : 'application/x-sentry-envelope' };
175- // NOTE(lejard_h) overriding user agent on VM and Flutter not sure why
176- // for web it use browser user agent
177- if (! isWeb) {
178- headers['User-Agent' ] = sdkIdentifier;
179- }
180- return headers;
181- }
0 commit comments