VaporのConfigについて

# 動作環境
この記事では以下の環境で動作を確認しています。

* Xcode9.0
* macOS Sierra バージョン 10.12.6
* Vapor Toolbox: 2.0.4
* Vapor Framework: 2.2.2


# Config
Vaporアプリケーションの設定について説明します。
サーバーサイドのアプリケーションは開発環境、ステージング環境、本番環境等、環境に分かれて開発されるのが一般的です。

Vaporでは`Config`ディレクトリの下にJSONファイルを置くことでアプリケーションの設定をすることができます。

# とりあえず使ってみる
Vaporのアプリケーションを作成すると`Config`ディレクトリが作成されていることがわかります。
サーバーの設定ファイルを指定する`server.json`の中身をみます。

```
./
├── Config/
│   ├── server.json
```

デフォルトでは以下のような内容になっているかと思います。

```json
{
    "host": "0.0.0.0",
    "port": 8080,
    "securityLayer": "none"
}
```
この意味は、アプリケーションが立ち上がった時、ホストは`0.0.0.0`、ポートは`8080`を指定するという意味です。
実際に`vapor run`でアプリケーションを立ち上げると`http://localhost:8080`で立ち上がることがわかります。

## カスタムキー
Configは独自のキーを指定することもできます。
実際に`server.json`に下記のように`custom-key`キーを追加してみましょう。

```json
{
    "host": "0.0.0.0",
    "port": 8080,
    "securityLayer": "none",
    "custom-key": "custom value" 
}
```

アプリケーションで呼び出す際は以下のようにします。

```swift
let customeValue = drop.config["server", "custom-key"]?.string ?? "default"
```

# 設定の構文
`Config`ディレクトリの設定にアクセスする構文は`drop.config[fileName, path, to, key]`となります。
`Config/app.json`を開いて下記のようなJSONファイルを作ってみます。

```json
{
  "test-names": [
    "joe",
    "jane",
    "sara"
  ],
  "mongo": {
    "url" : "www.customMongoUrl.com"
  }
}
```

`test-names`配列の1番目のインデックスにアクセスするには以下のようなコードを書きます。

```swift
// Sources/Run/main.swift
//Config/app.jsonのtest-nameを呼び出す
let firstTestName = drop.config["app", "test-names", 0]?.string ?? "default"
print(firstTestName)
```

アプリケーションを実行すると
```
joe
```
が出力されます。

次に`mongo`の`url`キーの値にアクセスしてみます。

```swift
// Sources/Run/main.swift
//Config/app.jsonのmongoを呼び出す
let monogoURL = drop.config["app", "mongo", "url"]?.string ?? "default"
print(monogoURL)
```

アプリケーションを実行すると
```
www.customMongoUrl.com
```
が出力されます。

# 高度な設定
デフォルトで作成される`server.json`はそのままでとてもよいのですが、実際に運用するにあたっては各環境で設定を分けたい時があります。
Vaporでは`Config/`ディレクトリの下に各環境に対応したディレクトリを作成することで環境ごとの設定を指定することができます。

```
./
├── Config/
│   ├── server.json
│   ├── production/
│   │   └── server.json
│   ├── development/
│   │   └── server.json
│   └── secrets/
│       └── server.json
```

環境を指定する方法は、コマンドラインで`--env`オプションを指定することでできます。
例えば本番環境を指定するには下記のように実行します。
```
vapor run --env=production
```

こうすることで`Config/production/server.json`の値が読み込まれたアプリケーションを実行することができます。

# 優先度
設定ファイルの優先度は以下のとおりです。

* CLI
* Config/secrets/ 以下のファイル
* Config/＜環境名＞/ 以下のファイル
* Config/

例えば、`drop.config["server", "host"]` を実行した際に検索される順番はCLIが最初で、次に`secrets/`ディレクトリで続いて`Config/production/`などの各環境ディレクトリ、最後に`Config/`直下のものになります。

> `secrets/`はgitignoreファイルに追加することをおすすめします。

## 優先度の例
優先度の例をみてみます。
以下のような`Config/server.json`を作成します。

```json
{
    "port": "9000",
    "host": "0.0.0.0"
}
```

続いて`Config/production/server.json`を作成します。

```
{
    "port": "$PORT:8080",
    "host": "127.0.1"
}
```
> `$NAME`と書くことで環境変数にアクセスすることができます。`$NAME:value`で$NAMEがない場合のデフォルト値を設定することができます。

アプリケーションでserver.jsonを読み込むコードを書いてみます。

```swift
let host = drop.config["server", "host"]?.string ?? "0.0.0.0"
let port = drop.config["server", "port"]?.int ?? 9000
```

本番環境を指定してアプリケーションを実行してみます。
```
vapor run --env=production
```

そうすると`host`変数は`127.0.1`、`port`変数は環境変数の値をとります。

`--env`オプションを指定しないでアプリケーションを実行してみましょう。

```
vapor run
```
そうすると`host`変数は`0.0.0.0`、`port`変数は`9000`の値をとります。

# コマンドラインでの指定
`Config/`ディレクトリにJSONファイルを配置せずともコマンドラインで設定の指定ができます。
下記のようにアプリケーション実行時に`--config`オプションを指定します。

```
vapor run --config:keys.analytics=124ZH61F
```

アプリケーションからは以下のように設定値を取得することができます。

```
let analyticsKey = drop.config["keys", "analytics"]?.string ?? "default"
print(analyticsKey)
```

コンソールにて`124ZH61F`が出力されるはずです。

# Xcodeで各環境を指定して実行する
開発でXcodeを利用している人はRunスキーマーを編集することで、各環境ごとの設定を読み込めます。

`Run`スキーマーをクリックして`Edit Schema...`をクリックします。

<img width="279" alt="config_fig1.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/31587/f81dca28-a011-0210-7dd0-0775828855ef.jpeg">


`▶Run`>`Arguments`>`Arguments Passed On Launch`から指定したいオプションを追加します。


<img width="1069" alt="config_fig2.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/31587/5b5368bd-5acf-5764-4275-afa598b4b79a.jpeg">
例えば`--env=production`を追加し、チェックマークをONにします。
そして実行すると本番環境の設定値が読み込まれてアプリケーションが実行されます。

# 参考
Configs  Config
https://docs.vapor.codes/2.0/configs/config/