在 Flutter 应用程序中使用 Charles 代理检查 WebSocket 包

Inspect WebSocket packages with Charles proxy in Flutter app

我正在使用 Flutter/Dart 开发移动应用程序。我需要的是 debug/test 我的应用程序与 Charles proxy/Fiddler 的网络流量。使用 Charles 代理检查 dart/flutter 中的 http requests/responses 很容易。我们只需要告诉 HttpClient 一个代理服务器的地址(安装 Charles 的机器的 IP 地址)这样:

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);

但是我如何调试通过创建的 WebSocket 流量 WebSocket.connect('wss://server_address');? WebSocket 没有任何 api 用于设置代理设置,我在论坛上找不到任何东西。 话虽这么说,我过去已经在另一个用 C# 编写的移动应用程序中做过这样的事情,这很容易。

想通了。实际上有多种方法可以做到这一点:

全局代理设置:

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());
}

自定义 HttpClient 传入 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);

手动方式:我们需要使用简单的 HttpClient 和指定的代理设置升级到 WebSocket。在这种情况下,我们将能够检查 Charles/Fiddler.

中的 WebSocket 流量
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);
}