APIゲートウェイのテスト：Krakend

## APIゲートウェイのテスト：Krakend
[以前の投稿でも述べたように](https://qiita.com/dabiddo/items/d74418383b468a32a57e)、私たちはLaravelモノリスをNestJSマイクロサービスに移行しています。そのため、レガシーAPIと新しいAPIの両方を処理できるAPIゲートウェイが必要です。

調査中、[Krakend](https://www.krakend.io/)というアプリを見つけました。他にもTyk.ioを使用している人々がいることは知っていますが、私がKrakendに興味を持った理由は、それをDockerで実行できることと、設定にはJSONファイルのみが必要だからです。

私はこれをここに残しておきます。プレイグラウンドを使用すると、モニタリングのための非常に重いサービスが提供されますが、私はまだ学習中なので、ほとんどのものを削除し、docker-composeファイルにはKrakendのみを残しました。

### 前提条件

この例では、以前の投稿[「Laravel / NestJSでの共有認証」](https://github.com/dabiddo/laravel-nestjs-auth/tree/krakend-example)を使用していますので、それをクローンして、ファイルを確認するためにkrakend-exampleブランチに移動できます。

変更点

プロジェクトにKrakendを組み込むために、私はdocker-composeファイルを変更する必要がありました。
```yaml
version: '3'

services:
  mysql:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=laraveldb
    volumes:
      - db-data:/var/lib/mysql:cached

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:cached
      - ../:/app:cached
    depends_on:
      - workspace #must be the same name of the laravel container used above

  krakend_ce:
    # The :watch image restarts the service automatically when the configuration files change.
    # Do not use this image in production, it's meant to speed up your testing and development.
    image: devopsfaith/krakend:watch
    volumes:
      - ./krakend:/etc/krakend
    ports:
      - "1234:1234"
      - "8080:8080"
      - "8090:8090"
    command: ["run", "-d", "-c", "/etc/krakend/krakend.json"]

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"

volumes:
  db-data:
```
また、Dockerfile内でNestJsがDockerネットワーク内でアクセス可能になるように、HOST環境を設定する必要がありました。

`ENV HOST 0.0.0.0`
コントローラーエンドポイント

Krakendの設定を作成する前に、LaravelおよびNestJsのコントローラーにAPIエンドポイントを追加しました。

**例として、api/v1をハードコードしました。**
```php
//routes/api.php
Route::get('v1/cats',function(){
    return response(['message'=>'v1 cats']);
});
```

```ts
//app.controller.ts
@Get('api/v2/cats')
  getCats(): any {
    return { message: 'v2 Cats' };
  }
```
### Krakendの設定の追加

docker-composeにKrakendを追加した後、設定用のフォルダを作成する必要がありました。マップされたボリューム内の.devocontainer/krakend/から、krakend.jsonというファイルが格納されています。

以下は私の基本的なkrakendのJSON設定ファイルです。
```json
{
    "$schema": "https://www.krakend.io/schema/v3.json",
    "version": 3,
    "name": "KrakenD - API Gateway",
    "timeout": "3000ms",
    "cache_ttl": "300s",
    "output_encoding": "json",
    "debug_endpoint": true,
    "echo_endpoint": true,
    "endpoints": [
    {
      "endpoint": "/v1/cats",
      "method": "GET",
      "output_encoding": "json",
      "backend": [
        {
          "url_pattern": "/api/v1/cats",
          "encoding": "json",
          "method": "GET",
          "extra_config": {
            "github.com/devopsfaith/krakend-cors": {
              "allow_origins": ["*"],
              "allow_methods": ["GET"],
              "allow_headers": ["Content-Type"]
            }
          },
          "host": [
            "http://nginx"
          ],
          "disable_host_sanitize": true
        }
      ]
    },
    {
      "endpoint": "/v2/cats",
      "method": "GET",
      "output_encoding": "json",
      "backend": [
        {
          "url_pattern": "/api/v2/cats",
          "encoding": "json",
          "method": "GET",
          "extra_config": {
            "github.com/devopsfaith/krakend-cors": {
              "allow_origins": ["*"],
              "allow_methods": ["GET"],
              "allow_headers": ["Content-Type"]
            }
          },
          "host": [
            "http://workspace:3000"
          ],
          "disable_host_sanitize": true
        }
      ]
    }
  ]
}
```
### 注意事項:

Dockerはコンテナにエイリアスを設定するため、それらを呼び出すためにはエイリアスで参照する必要があります。

`artisan serve`を使用する場合

もしも偶然にも、Dockerから`php artisan serve`コマンドを使用している場合は、公開するためにホストとポートのパラメータを渡す必要があります。

`php artisan serve --host=0.0.0.0 --port=8000`

krakend.jsonファイルでは、ホストをLaravelアプリをホストしているコンテナの名前に変更することを忘れないでください。例えば、私の場合は`http://workspace:8000`になります。

テストの時間です

動作を確認するために、`http://localhost:8080/v1/cats` にアクセスしてみてください。

この応答はLaravelから返されます。`v2`に変更すると、NestJsからの応答が返されます。