Skip to content

Commit 33527b4

Browse files
authored
Add proxy support (#2192)
1 parent 6e9c5a2 commit 33527b4

File tree

16 files changed

+699
-9
lines changed

16 files changed

+699
-9
lines changed

CHANGELOG.md

+22-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,27 @@
1717
appRunner: () => runApp(MyApp()),
1818
);
1919
```
20+
- Add proxy support ([#2192](https://github.com/getsentry/sentry-dart/pull/2192))
21+
- Configure a `SentryProxy` object and set it on `SentryFlutter.init`
22+
```dart
23+
import 'package:flutter/widgets.dart';
24+
import 'package:sentry_flutter/sentry_flutter.dart';
25+
26+
Future<void> main() async {
27+
await SentryFlutter.init(
28+
(options) {
29+
options.dsn = 'https://[email protected]/add-your-dsn-here';
30+
options.proxy = SentryProxy(
31+
type: SenryProxyType.http,
32+
host: 'localhost',
33+
port: 8080,
34+
);
35+
},
36+
// Init your App.
37+
appRunner: () => runApp(MyApp()),
38+
);
39+
}
40+
```
2041

2142
### Improvements
2243

@@ -72,7 +93,7 @@ SentryFlutter.init((options) =>
7293
- This allows viewing the correct dart formatted raw stacktrace in the Sentry UI
7394
- Support `ignoredExceptionsForType` ([#2150](https://github.com/getsentry/sentry-dart/pull/2150))
7495
- Filter out exception types by calling `SentryOptions.addExceptionFilterForType(Type exceptionType)`
75-
96+
7697
### Fixes
7798

7899
- Disable sff & frame delay detection on web, linux and windows ([#2182](https://github.com/getsentry/sentry-dart/pull/2182))

dart/lib/sentry.dart

+2
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,5 @@ export 'src/sentry_span_operations.dart';
5656
export 'src/utils.dart';
5757
// spotlight debugging
5858
export 'src/spotlight.dart';
59+
// proxy
60+
export 'src/protocol/sentry_proxy.dart';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import 'package:meta/meta.dart';
2+
import 'package:http/http.dart';
3+
4+
import '../sentry_options.dart';
5+
6+
@internal
7+
ClientProvider getClientProvider() {
8+
return ClientProvider();
9+
}
10+
11+
@internal
12+
class ClientProvider {
13+
Client getClient(SentryOptions options) {
14+
return Client();
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import 'dart:io';
2+
3+
import 'package:http/http.dart';
4+
import 'package:http/io_client.dart';
5+
import 'package:meta/meta.dart';
6+
7+
import '../protocol.dart';
8+
import '../protocol/sentry_proxy.dart';
9+
import '../sentry_options.dart';
10+
import 'client_provider.dart';
11+
12+
@internal
13+
ClientProvider getClientProvider() {
14+
return IoClientProvider(
15+
() {
16+
return HttpClient();
17+
},
18+
(user, pass) {
19+
return HttpClientBasicCredentials(user, pass);
20+
},
21+
);
22+
}
23+
24+
@internal
25+
class IoClientProvider implements ClientProvider {
26+
final HttpClient Function() _httpClient;
27+
final HttpClientCredentials Function(String, String) _httpClientCredentials;
28+
29+
IoClientProvider(this._httpClient, this._httpClientCredentials);
30+
31+
@override
32+
Client getClient(SentryOptions options) {
33+
final proxy = options.proxy;
34+
if (proxy == null) {
35+
return Client();
36+
}
37+
final pac = proxy.toPacString();
38+
if (proxy.type == SentryProxyType.socks) {
39+
options.logger(
40+
SentryLevel.warning,
41+
"Setting proxy '$pac' is not supported.",
42+
);
43+
return Client();
44+
}
45+
options.logger(
46+
SentryLevel.info,
47+
"Setting proxy '$pac'",
48+
);
49+
final httpClient = _httpClient();
50+
httpClient.findProxy = (url) => pac;
51+
52+
final host = proxy.host;
53+
final port = proxy.port;
54+
final user = proxy.user;
55+
final pass = proxy.pass;
56+
57+
if (host != null && port != null && user != null && pass != null) {
58+
httpClient.addProxyCredentials(
59+
host,
60+
port,
61+
'',
62+
_httpClientCredentials(user, pass),
63+
);
64+
}
65+
return IOClient(httpClient);
66+
}
67+
}
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
class SentryProxy {
2+
final SentryProxyType type;
3+
final String? host;
4+
final int? port;
5+
final String? user;
6+
final String? pass;
7+
8+
SentryProxy({required this.type, this.host, this.port, this.user, this.pass});
9+
10+
String toPacString() {
11+
String type = 'DIRECT';
12+
switch (this.type) {
13+
case SentryProxyType.direct:
14+
return 'DIRECT';
15+
case SentryProxyType.http:
16+
type = 'PROXY';
17+
break;
18+
case SentryProxyType.socks:
19+
type = 'SOCKS';
20+
break;
21+
}
22+
if (host != null && port != null) {
23+
return '$type $host:$port';
24+
} else if (host != null) {
25+
return '$type $host';
26+
} else {
27+
return 'DIRECT';
28+
}
29+
}
30+
31+
/// Produces a [Map] that can be serialized to JSON.
32+
Map<String, dynamic> toJson() {
33+
return {
34+
if (host != null) 'host': host,
35+
if (port != null) 'port': port,
36+
'type': type.toString().split('.').last.toUpperCase(),
37+
if (user != null) 'user': user,
38+
if (pass != null) 'pass': pass,
39+
};
40+
}
41+
42+
SentryProxy copyWith({
43+
String? host,
44+
int? port,
45+
SentryProxyType? type,
46+
String? user,
47+
String? pass,
48+
}) =>
49+
SentryProxy(
50+
host: host ?? this.host,
51+
port: port ?? this.port,
52+
type: type ?? this.type,
53+
user: user ?? this.user,
54+
pass: pass ?? this.pass,
55+
);
56+
}
57+
58+
enum SentryProxyType {
59+
direct,
60+
http,
61+
socks;
62+
}

dart/lib/src/sentry_options.dart

+13
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,19 @@ class SentryOptions {
496496
/// ```
497497
Spotlight spotlight = Spotlight(enabled: false);
498498

499+
/// Configure a proxy to use for SDK API calls.
500+
///
501+
/// On io platforms without native SDKs (dart, linux, windows), this will use
502+
/// an 'IOClient' with inner 'HTTPClient' for http communication.
503+
/// A http proxy will be set in returned for 'HttpClient.findProxy' in the
504+
/// form 'PROXY <your_host>:<your_port>'.
505+
/// When setting 'user' and 'pass', the 'HttpClient.addProxyCredentials'
506+
/// method will be called with empty 'realm'.
507+
///
508+
/// On Android & iOS, the proxy settings are handled by the native SDK.
509+
/// iOS only supports http proxies, while macOS also supports socks.
510+
SentryProxy? proxy;
511+
499512
SentryOptions({this.dsn, PlatformChecker? checker}) {
500513
if (checker != null) {
501514
platformChecker = checker;

dart/lib/src/transport/http_transport.dart

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import '../sentry_options.dart';
1111
import '../sentry_envelope.dart';
1212
import 'transport.dart';
1313
import 'rate_limiter.dart';
14+
import '../http_client/client_provider.dart'
15+
if (dart.library.io) '../http_client/io_client_provider.dart';
1416

1517
/// A transport is in charge of sending the event to the Sentry server.
1618
class HttpTransport implements Transport {
@@ -22,9 +24,8 @@ class HttpTransport implements Transport {
2224

2325
factory HttpTransport(SentryOptions options, RateLimiter rateLimiter) {
2426
if (options.httpClient is NoOpClient) {
25-
options.httpClient = Client();
27+
options.httpClient = getClientProvider().getClient(options);
2628
}
27-
2829
return HttpTransport._(options, rateLimiter);
2930
}
3031

dart/lib/src/transport/spotlight_http_transport.dart

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import 'http_transport_request_handler.dart';
44

55
import '../../sentry.dart';
66
import '../noop_client.dart';
7+
import '../http_client/client_provider.dart'
8+
if (dart.library.io) '../http_client/io_client_provider.dart';
79

810
/// Spotlight HTTP transport decorator that sends Sentry envelopes to both Sentry and Spotlight.
911
class SpotlightHttpTransport extends Transport {
@@ -13,7 +15,7 @@ class SpotlightHttpTransport extends Transport {
1315

1416
factory SpotlightHttpTransport(SentryOptions options, Transport transport) {
1517
if (options.httpClient is NoOpClient) {
16-
options.httpClient = Client();
18+
options.httpClient = getClientProvider().getClient(options);
1719
}
1820
return SpotlightHttpTransport._(options, transport);
1921
}

0 commit comments

Comments
 (0)