コンテナから外へのHTTPリクエストをキャプチャしたい！

# はじめに

はじめて触るアプリケーションの開発の担当になったときや、アプリケーションの調査やデバックをしたいときに、アプリケーションから呼び出しているAPIリクエストの内容やそのレスポンス内容を確認したいときがあったりします。
あとは、レスポンス内容を少し変えてアプリケーションの挙動の確認をしてみたかりもしたかったり。

前者は特定のログで見れるようにしてる場合もあるかもですが、必ずしもそうなっているとは限らないし、後者の特定のレスポンス時の挙動確認は、データかコードをいじらないとできなかったりするから結構大変だったりします。

そんなことが、アプリの変更（ほとんど）なしでできるツール、[http-request-capture](https://github.com/s-shirayama/http-request-capture) を作ってみました。

# どんなツールなの？

対象のアプリケーションがローカルのDockerで動いていることが前提になります。
Webアプリのコンテナの横に`http-request-capture`のコンテナを起動させるだけで、Webアプリから呼び出されるHTTP APIのリクエスト／レスポンスをキャプチャでき、さらには、レスポンス内容を編集して、同じリクエストが来た場合に編集したレスポンスを返すように設定することもできます。

基本的にはWebアプリのコード編集がなくてもHTTP APIのキャプチャができますが、HTTPSのAPIを呼び出している場合は、証明書エラーを無視するような設定をアプリ側に入れる必要があります。

また、特別なプロキシを経由するようなリクエストの場合もキャプチャすることが可能です。

# 何ができるの？

サンプルとして、レポジトリのREADMEに、[Wordpressのリクエストをキャプチャする例](https://github.com/s-shirayama/http-request-capture#try-it-with-example-application)を載せてあるので、是非手元で動かしてみてください。

ここでは、READMEと同じ内容を日本語でも書いておきます。どんなことができるのかのイメージがつくと思います。

## Wordpressのリクエストをキャプチャしてみる

ここでは、Wordpressの公式イメージをローカルで動かしてみて、コンテナから出ているAPIのリクエストをキャプチャし、さらにレスポンス内容を少し編集してアプリの挙動にどんな違いがでるか見てみたいと思います。

### 1. Wordpressコンテナのセットアップ

```
git clone https://github.com/s-shirayama/http-request-capture.git
docker-compose -f example/docker-compose.yaml up -d
```

1. http://localhost:8000/ を開く
1. 適当な値でWordpressの初期設定を行う
1. 設定したID/PWでADMIN画面にログインする

### 2. HTTP APIのリクエストのキャプチャ

#### 2-1. `http-request-capture`コンテナを起動

```
CONTAINER_NAME=example_wordpress_1 \
NETWORK_NAME= \
docker-compose up -d
```

#### 2-2. `http-request-capture` UI画面を開く
http://localhost:18080/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315538/763a1092-faf6-58ac-da0d-6cb1edf16005.png)


#### 2-3. Check request/response
- プラグイン一覧ページを開く
  - http://localhost:8000/wp-admin/plugin-install.php?s&tab=search&type=term
-  http://localhost:18080/　のページで　"update mappings / requests" をクリックする
- → ページを開く際に、裏側でリクエストされたAPIのリクエストとレスポンスを見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315538/33fbd654-906d-bae6-2080-d640d75f4e13.png)

- "show response body"をクリックすると、レスポンスの中身も見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315538/e9bdb107-f656-5013-4937-7beeb32d182b.png)

#### 2-4. レスポンスを修正してみる。

- "add" をクリックして、モックレスポンスの登録をする。
- "update" をクリックして、レスポンスの修正モードに入る。
- "responseBody"のJSONの`info.results`を修正してみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315538/b1f04cce-b45b-5843-fd21-81a391c27279.png)

- "update"をクリックして編集を完了する。
- もう一度プラグイン一覧画面を表示する。
  - http://localhost:8000/wp-admin/plugin-install.php?s&tab=search&type=term
- → ページング部分に表示されている数字が変更される。

Before

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315538/b29ec8ab-7bd7-cfae-4a8b-3d65437e3bf1.png)

After

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315538/3d35ca3e-3adb-5f87-c835-2b1cf93c33e4.png)

#### 3. HTTPS APIのリクエストやプロキシ経由のリクエストをキャプチャしてみる。

`http-request-capture`が、大体どんな感じで動くのかのイメージができたかと思いますので、続きはレポジトリのREADMEの[Wordpressのリクエストをキャプチャする例](https://github.com/s-shirayama/http-request-capture#try-it-with-example-application)を参照ください。

# どうやって動いているの？

最後に、`http-request-capture`がどうやってリクエストをキャプチャしているのかを説明します。
こんな感じで、コンテナからでるリクエストを、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315538/8521e44f-2c1c-e34e-692b-f96200099ffd.png)

iptablesで`http-request-capture`に対して、ルーティングされるようにしています。このやり方は、Istioで外向けのリクエストをサイドカーのEnvoyにルーティングしているやり方を真似ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315538/4bfa0290-64fe-a32c-0810-bfc0ce6a3c42.png)

`http-request-capture`では、透過プロキシ([elazarl/goproxy](https://github.com/elazarl/goproxy))をGolangで動かして、リクエストとレスポンスをキャプチャしています。そのキャプチャした内容を`admin`のUIを通してブラウザで見ることができるって感じです。さらには、UIから特定のリクエストに対してのレスポンスの編集ができたりします。この辺は[Wiremock](http://wiremock.org/)というモックツールを参考にしています。

この辺の挙動も[Wordpressのリクエストをキャプチャする例](https://github.com/s-shirayama/http-request-capture#try-it-with-example-application)で手元で確認できるので、是非見てみてください。