HTTP Proxy（Charles）を活用して開発効率をあげる

開発でHTTP通信の内容を確認する場合、CharlesというHTTPプロキシを使うと便利です。
今回はiOS開発での実例を挙げながらどのようなパターンで活用できるのかを解説したいと思います。
アプリ開発をする場合、特にWeb側の開発者とのやり取りをする時に通信ログをエビデンスとして渡すことで効率よく作業を進められます。
## 検証環境
- macOS Big Sur version 11.6
- charles v4.6.2
- iOS15.3.1
## Charlesについて
CharlesはHTTPプロキシとして動作するソフトウェアで、macOS等にインストールして使うことができます。
アプリ開発においては、例えばiOS端末にプロキシ設定をしてそのマシン経由で通信させることにより、通信内容をPC側で確認することができるようになります。
## Charlesで出来ること
- 通信内容を見る
- リクエストを変更する
- レスポンスを変更する
- 通信時にブレークポイントで止める
※上記以外にも色々できることはあります。
## 有料？
試用版は無料で使うことができますが、30分で終了するため定期的に再起動が必要です。
## 活用事例
iOS開発時の利用例をもとに解説したいと思います。
- iOS端末の通信内容を確認する
- iOSシミュレータの通信内容を確認する
- リクエストヘッダの内容を書き換える
- APIのスタブとして活用する
- IP制限のかかったページに端末からアクセス
## 使えるようにするための準備
事例を紹介する前に最低限の初期設定について解説していきます。

ダウンロードページURL
https://www.charlesproxy.com/download/

ちなみにmacOSで`homebrew cask`にてインストール可能です。
```
brew install --cask charles
```
### 1.プロキシ設定とポート番号の設定
メニューからProxy -> Proxy Settings...を選択して、ポート番号（デフォルトで8888になっています）を確認して、「Enable transparent HTTP proxying」のチェックをつけます。
ここで指定してあるポート番号はiOS端末側からアクセスする場合に使うものです。
![スクリーンショット 2022-03-29 3.39.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/d8730657-bd2d-2e6b-22c7-fe435230328e.png)
### 2.macOS proxyの設定
メニューからProxy -> Proxy Settings...を選択して、「macOS」タブ内にある「Enable macOS proxy」の設定を確認します。
Charlesを起動しているPC側の通信もキャプチャしたい場合はこのチェックを付ける必要があります。
ただ、常にチェックをしているとこの設定が原因でアクセスできないサイトがあったり、Rubyで開発しているときにGemが取得できなかったりしたことがあったため、私の場合は通常は外しておき、PC側のブラウザ通信やiOSシミューレータの通信を確認したいときだけチェックをつけるようにしています。
副作用があるというのだけ頭の片隅に入れておくと、これが原因のトラブルが起こった場合にハマらなくてすみます。
![スクリーンショット 2022-03-30 1.24.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/665f434d-3bdd-6c8c-1899-07bf92b356ae.png)
### 3.SSLの設定
HTTPSの通信をキャプチャする場合SSLプロキシの設定をする必要があります。
HTTPだけキャプチャするというのは珍しいと思うので、HTTPSは意地でもキャプチャしないという強い意志がある場合を除いてとりあえず設定しておけば良いと思います。
メニューからProxy -> SSL Proxy Settings...を選択して、「Enable SSL Proxying」にチェックをつけます。
続けて、Includeのところの「Add」ボタンを押して、Hostに「*」、Portに「443」を入力してOKボタンを押します。
![スクリーンショット 2022-03-30 1.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/a924376f-7ee0-1e40-c843-14bb2453a871.png)
### 4.SSL証明書をインストール
PCにCharlesのSSL証明書をインストールします。
メニューから、Help -> SSL Proxying -> Install Charles Root Certificateを選択します。
キーチェーンが開くので「Charles Proxy CA」を見つけて「常に信頼」に設定します。
![スクリーンショット 2022-03-30 2.55.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/251dbf9d-69ef-c52f-3e9e-f17f52cf1cf1.png)
## iOS端末の通信内容を確認する
iOS端末の通信内容を確認するためには、端末側にCharlesの証明書をインストールした上で、プロキシの設定をする必要があります。
### 1.Charlesを起動してIPアドレスを確認する。
通信内容を確認するためには当然Charlesを起動する必要があります、
iOS端末側からこのCharlesがインストールされているPC経由で通信させる必要があるため、PC側のIPアドレスを調べる必要があります。
メニューから、HELP -> Local IP Addressを選択するとPCのIPアドレスを確認できます。
IPアドレスが分かればいいので、ifconfigコマンドなどでも確認できれば問題ありません。
### 2.プロキシ設定
Wi-Fiの設定画面でHTTPプロキシ -> プロキシ構成を開いて、サーバにはCharlesが起動しているPCのIPアドレス、ポート番号はCharlesのProxy Settingsで確認した番号を設定します。
![IMG_0F7492CA1FC7-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/8edf8ecd-2cd9-3e44-91f0-3c9f67294c95.jpeg)
### 3.証明書インストール
`http://charlesproxy.com/getssl`に端末からアクセスして、ダイアログが表示されるので許可します。
![IMG_0356.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/d5683a57-8dcb-642b-1f97-9a1393a7e311.png)
許可した後は設定アプリトップの「プロファイルがダウンロード済み」をタップして証明書をインストールします。
証明書をインストールした後は証明書を信頼する必要があるため、設定アプリトップから一般 -> 情報 -> 証明書信頼設定を開いて信頼するのチェックを付けます。
![IMG_0362.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/26c0b9b5-ff23-f881-5732-a8b4608f2bce.png)
### 4.端末からWebサイトにアクセスして確認
下図のように、画面上からリクエストのリスト、ヘッダやCookie情報、Bodyなどが確認できます。
ヘッダ部もBODY部も「Raw」を選択すると整形されてない生のデータを見ることができます。
![スクリーンショット 2022-03-31 3.19.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/f27800ae-1e4f-8380-1562-6d3884bacad3.png)
## iOSシミュレータの通信内容を確認する
開発で使うiOSシミュレータの通信も実機と同様に通信内容を確認することができます。
### 1.iOSシミュレータに証明書をインストール
CharlesのメニューからHelp -> SSL Proxying -> Install Charles Root Certificate in iOS Simulatorsを選択します。
※記事執筆時点でcharlesの最新版は4.6.2でしたが、4.6.1を試したところ証明書をインストールできませんでした。最新版のCharlesをインストールし直すことで問題なくシミューレータに証明書をインストールできたので、最新版で試すことをおすすめします。
### 2.シミュレータ側でインストールした証明書を信頼する
シミュレータの設定アプリを開き、一般（General）-> 情報（About）-> 証明書信頼設定（Certificate Trust Settings）を選択して、Charles Proxyt CA.... のチェックをつけます。
![スクリーンショット 2022-03-31 15.41.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/3420eab6-d764-abc8-026e-51f2f2881331.png)
### 3.端末からWebサイトにアクセスして確認
実機と同じようにシミューレータで通信を行うとCharles側でキャプチャできます。
シミューレータの通信をキャプチャするためには、「macOS proxy」の設定が有効になっている必要があります。
## リクエストヘッダの内容を書き換える
Charlesを使ってリクエストヘッダを書き換えることでプログラム側に手を加えずに書き換えできます。
例えばアプリ側からAPI通信時にアプリのバージョンなどを送っている場合、アプリ側のプログラムを変更せずに送るバージョンを変えることができます。
リクエストヘッダを書き換えるためには、Rewriteの設定を行います。
### 1.Rewriteの設定画面を開く
メニューからTools -> Rewriteを開きます。
### 2.名前をつけて設定を追加する
Enable Rewriteのチェックを付けた状態で、Addボタンを押して追加します。
Nameのところをわかりやすい名前に書き換えます。
![スクリーンショット 2022-03-31 16.06.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/1e320a51-61c5-222b-8e5d-3dd77075b78a.png)
### 3.ロケーションを追加
書き換え対象のURLを指定します。
以下の例では、「api.mgre.jp」へのHTTPSリクエストすべてが対象になります。
特定のパスや特定のクエリパラメータを対象とする場合、path,queryにそれぞれ必要に応じて設定します。
![スクリーンショット 2022-03-31 16.23.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/ae3dd2e7-85e5-e22a-38fd-692064ef1b7a.png)
### 4.Rewrite Ruleを設定
次にルールを設定します。
以下の例では、x-app-versionというアプリから送っているヘッダをすべて100.0.0を送るように書き換えます。
![スクリーンショット 2022-03-31 16.23.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/01962c77-f69a-65ab-8d7a-980a28589198.png)
## APIのスタブとして活用する
レスポンスを書き換えることで、完成していないAPIのスタブとして動作させることができます。
やり方はMap Localを使う方法と、Map Remoteを使う方法があります。
Map Localは特定のエンドポイントからのレスポンスをローカルのJSONファイルなどにマッピングすることができます。
Map Remoteは、特定のエンドポイントからのレスポンスを、別のエンドポイントからのレスポンスに差し替えることができます。
今回はMap Localを使ってレスポンスをスタブ化します。
### 1.Map Localの設定を追加する
メニューから、Tools -> Map Localを開き、Addボタンを押して追加します。
以下の例は、`https://api.mgre.jp/foo/bar/baz`へのリクエストのレスポンスBODYを、PCのデスクトップに配置したJSONファイルの中身に置き換える設定です。
![スクリーンショット 2022-03-31 16.35.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5669/d7da5a15-50d1-a2a1-d090-cb1858da7dcd.png)
JSONファイルの中身
```
{
  "code": 500,
  "message": "Internal Server Error"
}
```
## IP制限のかかったページに端末からアクセス
実機などからCharlesを経由してアクセスした場合、アクセス元のIPはPCになるためPC側でVPN接続などをしてIP制限がかかっていない状態になっていれば実機からのアクセスもIP制限を回避することができます。
端末側にVPN設定をいれるのが面倒だったり、何かしらの理由があって設定できない場合など地味に便利なので活用しています。
## スマホアプリ版Charles
スマホアプリ版のCharlesも出ていて、iOS版を購入して入れてありますがほとんど使っていません。
やはり開発時などはPC経由で確認するのが便利です。