I'm developing mobile application using Flutter/Dart. What I need is to debug/test my application's network traffic with Charles proxy/Fiddler. It's easy to inspect http requests/responses in dart/flutter using Charles proxy. We only need to tell HttpClient an address of proxy server (IP address of machine where Charles is installed) like this:
final client = HttpClient();
client.findProxy = (uri) {
String proxy = '1.2.3.4:8888';
return "PROXY $proxy;";
};
client.badCertificateCallback =
((X509Certificate cert, String host, int port) => Platform.isAndroid);
But how can I debug WebSocket traffic created via
WebSocket.connect('wss://server_address');
? WebSocket doesn't have any api for setting proxy settings and I couldn't find anything on forums.
That being said, I already did such things in the past in another mobile app written on C# and it was pretty easy.
Figured it out. There are actually multiple ways to do that:
Global Proxy settings:
class ProxiedHttpOverrides extends HttpOverrides {
String _proxy;
ProxiedHttpOverrides(this. _proxy);
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..findProxy = (uri) {
return _proxy.isNotEmpty ? "PROXY $_proxy;" : 'DIRECT';
}
..badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
}
}
void main() {
String proxy = '1.2.3.4:8888';
HttpOverrides.global = new ProxiedHttpOverrides(proxy);
runApp(MyApp());
}
Custom HttpClient passed into WebSocket.connect
HttpClient client = HttpClient();
client.findProxy = (uri) => "PROXY $proxy;";
client.badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
WebSocket.connect(url, customClient: client);
Manual way: We need to upgrade to WebSocket using simple HttpClient with specified proxy settings. In that case we will be able to inspect WebSocket traffic in Charles/Fiddler.
Future<WebSocket> createProxySocket() async {
String url = 'https://echo.websocket.org:443';//address must start from http(s)://, not from ws(s)://, as we are connecting using http
String proxy = '1.2.3.4:8888';//your machine address (or localhost if debugging on the same machine)
Random r = new Random();
String key = base64.encode(List<int>.generate(8, (_) => r.nextInt(255)));
HttpClient client = HttpClient();
client.findProxy = (uri) => "PROXY $proxy;";
client.badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
Uri uri = Uri.parse(url);
HttpClientRequest request = await client.getUrl(uri);
request.headers.add('Connection', 'upgrade');
request.headers.add('Upgrade', 'websocket');
request.headers.add('Sec-WebSocket-Version', '13');
request.headers.add('Sec-WebSocket-Key', key);
HttpClientResponse response = await request.close();
Socket socket = await response.detachSocket();
return WebSocket.fromUpgradedSocket(socket, serverSide: false);
}