Swift製Webフレームワーク VaporのDropletってなに？

## Vaporとは
Vaporは、Swift製のWebフレームワークです。
公式URL: https://vapor.codes/
リポジトリ: https://github.com/vapor/vapor

## Dropletってやつが気になる
全く触ったことがない状態でアドベントカレンダーに招待されたので、とりあえずドキュメントを読んでいたら **Droplet** っていう単語がやけに出てくるので調べてみた。

単純に英語の意味がわからなかったので調べてみると、
> Droplet: 滴（しずく)

って意味らしい。Vapor（蒸気）を構成する要素だからDroplet=滴:droplet:にしたのかな...？（おしゃん✨

## Dropletはサービスコンテナ
[公式ドキュメント](https://docs.vapor.codes/2.0/vapor/droplet/#droplet)には、Dropletはサービスコンテナでルーティングやサーバー起動、ミドルウェアの追加などを担うと書いてある。
> The Droplet is a service container that gives you access to many of Vapor's facilities. It is responsible for registering routes, starting the server, appending middleware, and more.

（やっぱりVapor（蒸気）だから滴で構成されて（ry

## 使い方
以下、具体的なユースケースとともにDropletの仕組みについて理解していく。
（コードは公式ドキュメントのものをそのまま流用してます:bow:)

### 初期化
```swift:main.swift
import Vapor

let drop = try Droplet()

// 何かしらの設定

try drop.run()
```
単純にVaporを使用したいだけなら、これだけでOK。

### 環境ごとに設定を分けたい
```swift:main.swift
if drop.config.environment == .production {
    ...
}
```
上記のようにdevelopment、testing、productionなど、環境に応じた分岐を記述できる。
また、環境変数の切り替えは起動時のオプションで以下のようにできる。（デフォルトはdevelopment）

```shell
vapor run serve --env=production
```

### 環境ごとにログを出し分けたい
例えば、本番（production）でEmail送信でエラーが発生した場合のみ独自のloggerを利用したいときは以下のようにコードを記述し、

```swift:main.swift
let config = try Config()
config.addConfigurable(log: MyEmailLogger.init, name: "email")

let drop = Droplet(config)
```

本番用のdroplet.json（`Config/production/droplet.json`)に以下のように設定をしておく。

```javascript
{
    "log": "email"
}
```

ログ以外に、[serverやcipherなども設定可能](https://docs.vapor.codes/2.0/vapor/droplet/#supported-properties)みたい。

### サーバーのポート番号とかを環境ごとに設定したい
下記のように、 `config["jsonファイル名", "プロパティ名"]` で設定値を取り出すことができる。

```swift:main.swift
final class MyServer: ServerProtocol {
    let host: String
    let port: Int

    init(_ host: String, _ port: Int) {
        self.host = host
        self.port = port
    }
}

extension MyServer: ConfigInitializable {
    convenience init(config: Config) throws {
        // config["jsonファイル名", "プロパティ名"] で値を取り出せる
        let host = config["server", "host"]?.string ?? "127.0.0.1"
        let port = config["server", "port"]?.int ?? 8080

        self.init(host, port)
    }
}
```

あとは環境ごとに、以下のようなjsonファイルを用意しておけば勝手に設定が切り替わる。

```javascript:Config/production/server.json
{
    "host": "0.0.0.0",
    "port": 8080
}
```

```javascript:Config/development/server.json
{
    "host": "127.0.0.1",
    "port": 9000
}
```
### MySQLを使う場合の実際の設定
そもそも `MySQLProvider` なるものが提供されている。（[事前準備が必要](https://docs.vapor.codes/2.0/mysql/package/)だが省略）
以下のような記述を行い、

```swift:main.swift
import Vapor
import MySQLProvider

let config = try Config()
try config.addProvider(MySQLProvider.Provider.self)

let drop = try Droplet(config)

...
```
fluent（swift製のORMらしい）とMySQL関係の設定jsonを用意すればOK！

```Config/fluent.json
{
    "driver": "mysql"
}
```

```Config/mysql.json
{
    "hostname": "127.0.0.1",
    "user": "root",
    "password": "password",
    "database": "hello"
}
```
前項で記載したように、それぞれの設定jsonを内部的に読み込んでてコンフィグレーションをしているんですね、きっと。
なるほど、よくできている...。

## まとめ
- DropletはVaporによるアプリケーションを構成するサービスコンテナ
- 環境に応じたコンフィグレーションが可能
- カスタム値を設定することも可能
- 標準Providerの設定もDropletを介して行われているみたい
- jsonに設定を書いてあげれば基本的になんとかなるんだなぁという仕組みになっている（感心）