Server-Side Swift with Kitura を試してみた

# Server-Side Swift with Kitura を試してみた

try! Swift Tokyo 2018 の「使える！Kituraを使ってサーバーサイドSwiftアプリを作ろう！」というワークショップに参加しました。
内容としてはこちらを上から順番に実施した形になりますので、細かい作業内容は以下のリンクを参照ください。

https://github.com/IBM/FoodTrackerBackend

## 事前準備
- Xcode9.2 のインストール
- コマンドラインツールのインストール  
```
$ xcode-select --install
```
- Homebrewのインストール  
[こちら](https://brew.sh)を参照。

## サーバ構築
簡単です。`kitura init`コマンドを打つだけ。
カレントディレクトリ名のXcodeプロジェクトが作成されます。

```console
$ mkdir YOUR_PROJECT_NAME
$ cd ./YOUR_PROJECT_NAME
$ kitura init
```
## サーバの起動
- 実行するSchemeの切り替え  
YOUR_PROJECT_NAME-Packageになっているので、YOUR_PROJECT_NAME -> My Macを選ぶ
- 起動  
`Command + R`で実行するとサーバが起動します。
- 起動確認  
ブラウザで`localhost:8080`にアクセスして、Welcome to Kituraのページが表示されれば完了です。

## ルーティング
チュートリアルでは、`Application.swift`の`postInit()`メソッド内で定義していきます。

```swift:routing
router.get("/hoge", get_hoge_handler)
router.post("/hoge", post_hoge_handler)
```
のような形ですね。
`/hoge`へのGETリクエストの動作を`get_hoge_handler`で実装し、
`/hoge`へのPOSTリクエストの動作を`post_hoge_handler`で実装します。

KituraのhandlerはCodableを利用しますので、JSONのデータのやり取りが非常に楽ですね。

これでローカルサーバでの処理ができるようになりました。

## 注意事項
[FoodTrackerBackend](https://github.com/IBM/FoodTrackerBackend)では、PostgreSQLを利用する際に、Swift Package Managerに以下を記載するように書かれていますが、ReadMeに誤りがあり、`"Configuration"`は不要とのことでした。
試していませんが、`"Configuration"`を削除しないとエラーになるそうです。

```text:誤
.target(name: "Application", dependencies: [ "Kitura", "Configuration", "CloudEnvironment","SwiftMetrics","Health", "SwiftKueryORM", "SwiftKueryPostgreSQL"]),
```

```text:正
.target(name: "Application", dependencies: [ "Kitura", "CloudEnvironment","SwiftMetrics","Health", "SwiftKueryORM", "SwiftKueryPostgreSQL"]),
```

## おまけ (Website Frontend using the Stencil Template Engine)
Next Stepsに記載されている[Website Frontend using the Stencil Template Engine](https://github.com/IBM/FoodTrackerBackend/blob/master/StencilFrontend.md)の内容を追加で試しました。

HTMLとの連動部分ですね。
`.stencil`というファイルを使用してHTMLを記述するようです。
`.stencil`内部では`{{}}`で囲んで各種データを扱うようです。
jinja2と似ていて簡単ですね。

```text:例
<div>{{ meal.name }}</div>
```


### 注意事項
- Swift Package Managerへの追加について
`KituraStencil`をSwift Package Managerに追加する際、先ほどと同様に`Configuration`は不要ですので注意が必要です。

- PostgreSQL対応
このチュートリアルは、Next Stepsの位置付けで、[FoodTrackerBackend](https://github.com/IBM/FoodTrackerBackend)をやってからやるような位置付けになっています。
しかし、[Website Frontend using the Stencil Template Engine](https://github.com/IBM/FoodTrackerBackend/blob/master/StencilFrontend.md)では、PostgreSQLからのデータ取得をしない前提で記載されています。
PostgreSQLを利用する場合は、そのままコピペしていくとエラーになりますので、若干の修正が必要です。

```swift:エラーとなるコード
router.get("/foodtracker") { request, response, next in
    let meals: [Meal] = self.mealStore.map({ $0.value })
    var allMeals : [String: [[String:Any]]] = ["meals" : []]
    for meal in meals {
        allMeals["meals"]?.append(["name": meal.name, "rating": meal.rating])
    }
    try response.render("FoodTemplate.stencil", context: allMeals)
    next()
}
```

```swift:PostgreSQL対応コード
router.get("/foodtracker") { request, response, next in
    Meal.findAll({
        (_meals : [Meal]?, _error: RequestError?) -> Void in
        
        guard let meals : [Meal] = _meals else {
            return
        }
        
        var allMeals : [String: [[String:Any]]] = ["meals" : []]
        for meal in meals {
            allMeals["meals"]?.append(["name": meal.name, "rating": meal.rating])
        }
        do {
            try response.render("FoodTemplate.stencil", context: allMeals)
        } catch {
            // TODO: some error handling
        }
        next()
    })
}
```

## 所感
初めてKituraを利用しましたが、簡単にローカルサーバを構築することができました。
今回はローカルでしか動かしていないので、サーバで動作させるとなるともう少しハードルが高いのかもしれません。

私自身はGoogleのAppEngineを普段利用していますので使う機会が少ないかもしれませんが、Swift自体は素晴らしい言語だと思うのでiOSだけでなくどんどん利用用途が拡がっていくと嬉しいですね！

せっかくなので次はサーバにアップロードするところと、Vaporも試してみようと思います。