Flutter & Proxymanで通信デバッグをする

こんにちは。YOUTRUSTでアプリエンジニアをしている@endoidouです。

twitter.com

最近AmazonでTIME TIMERを購入し、ポモドーロテクニックをしながら作業をしています。

個人的にはタイマーアプリよりも物理タイマーのほうが好みなので中々捗っています。

www.amazon.co.jp

さて、YOUTRUSTのモバイルアプリはFlutterで作成されています。

今回は Flutter & Proxyman で通信デバッグする方法をご紹介します。

目次

通信を書き換えられると何がうれしいのか?

クライアント開発をしているとAPIがまだ出来ておらず実装の手が止まってしまうことや、複雑な操作をしないと望んだデータを受け取れないこと等がしばしばあります。

そういった場合に、通信データを操作することでクライアントに任意のデータを受け取らせることができます。

例えばUserのStatusを見て画面の表示を変えたい場合など

{
  "user": {
    "name" : "user-name",
    "status" : 1
  }
}

という通信をプロキシツールを使用して、以下のようにデータを編集することで実装やテストを行うことが可能になります。

{
  "user": {
    "name" : "user-name",
    "status" : 2 // 1 → 2
  }
}

Proxymanとは

今回はプロキシツールとしてProxymanを紹介します。

proxyman.io

他にも有名どころだとCharlesやmitmproxyなどのプロキシツールがありますが、Proxymanの優れている点として以下があります。

  • UIがモダンで使いやすい
  • 無料で時間制限なく利用できる(機能制限あり)

    You can try all debugging tools with the Trial version , it is limited to 2 pinned domains, 2 rules for each debugging tool, and no new tabs.

セッティング方法

セッティング方法についてはこちらをご参考ください。

GUIでステップ毎に設定していく形式でとてもわかりやすいです。

Flutterでの使用方法

早速動かしてみたいところですが、こちらのページにかかれているようにFlutterでProxymanを使用するには手動でプロキシ設定をする必要があります。

Currently, Flutter does not use the system-level proxy , so if you use Proxyman, you might not see any traffic from your Flutter Project.

今回は通信ライブラリのdioを使用して通信をすると仮定し、dio_proxy_adapterを使用して設定をします。

dioインスタンス化した後に useProxy を使用してプロキシを指定しました。

String proxy = Platform.isAndroid ? '10.0.2.2:9090' : 'localhost:9090';
_dio = Dio()
    ..options.baseUrl = 'https://api.github.com/'
    ..useProxy(proxy);

実際に使用する

今回はiOSシミュレータ上で通信デバッグのデモを行います。

+ボタンを押すことでgithubから /users/octocat のデータを取得して、リストに追加するという簡単なサンプルアプリをつくりました。

github.com

スクリーンショット

タップするたびに追加される

サンプルコード

class _MyHomePageState extends State<MyHomePage> {
  final List<User> _users = [];
  late final Dio _dio;

  @override
  void initState() {
    super.initState();

    String proxy = Platform.isAndroid ? '10.0.2.2:9090' : 'localhost:9090';
    _dio = Dio()
      ..options.baseUrl = 'https://api.github.com/'
      ..useProxy(proxy);
  }

  Future<void> _fetchUser() async {
    try {
      final response = await _dio.get('/users/octocat');
      final user = User.fromJson(response.data);
      setState(() {
        _users.add(user);
      });
    } catch (e) {
      // do nothing
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: _users.isEmpty
          ? const SizedBox.shrink()
          : ListView.builder(
              itemBuilder: (_, index) {
                final user = _users[index];
                return ListTile(
                  leading: CircleAvatar(
                    backgroundImage: NetworkImage(user.avatarUrl),
                  ),
                  title: Text(user.name),
                );
              },
              itemCount: _users.length,
            ),
      floatingActionButton: FloatingActionButton(
        onPressed: _fetchUser,
        child: const Icon(Icons.add),
      ),
    );
  }
}

この状態でProxymanを起動して通信をしてみると、こちらの画面のようにSSL proxyingを有効にするように求められます。 Enable all domains from "proxy_test" を選択しこのアプリの全ての通信を閲覧できるように設定しましょう。

有効にした後、再度APIを叩くとこのようにAPI Responseが見れるようになりました 🙌

Responseの値を変更してみましょう! 今回はMap Localを使用して値を変更しようと思います。

値を変更したいResponse上で右クリックを押し、Tools > Map Local と進みます。

するとエディター画面が表示されるので、変更したい値にjsonを書き換えましょう!

今回はNameを The Octocat から HogeHoge と変更しました。

忘れずにSaveをして再度APIを叩きましょう。 この状態でAPIを叩くとHogeHogeに変更されていることがわかります。

アプリで表示を確認してみると、 HogeHoge にしっかりと変更されていますね。

HogeHogeが表示される

まとめ

このように通信内容を書き換えることで開発効率を上げることが可能になります。

またProxymanではブレークポイントを追加したり、Scripting Toolというrequest/responseをJavaScriptで編集出来る機能もあります。

気になる方はこちらをご覧ください。

proxyman.io

エンジニア募集

YOUTRUSTでは、エンジニアを募集しています! YOUTRUSTに興味を持っていただけた方は下のリンクよりご応募お待ちしております!

herp.careers