Server-Side Swift with Kitura を試してみた
try! Swift Tokyo 2018 の「使える!Kituraを使ってサーバーサイドSwiftアプリを作ろう!」というワークショップに参加しました。
内容としてはこちらを上から順番に実施した形になりますので、細かい作業内容は以下のリンクを参照ください。
事前準備
- Xcode9.2 のインストール
- コマンドラインツールのインストール
$ xcode-select --install
- Homebrewのインストール
こちらを参照。
サーバ構築
簡単です。kitura init
コマンドを打つだけ。
カレントディレクトリ名のXcodeプロジェクトが作成されます。
$ 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()
メソッド内で定義していきます。
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では、PostgreSQLを利用する際に、Swift Package Managerに以下を記載するように書かれていますが、ReadMeに誤りがあり、"Configuration"
は不要とのことでした。
試していませんが、"Configuration"
を削除しないとエラーになるそうです。
.target(name: "Application", dependencies: [ "Kitura", "Configuration", "CloudEnvironment","SwiftMetrics","Health", "SwiftKueryORM", "SwiftKueryPostgreSQL"]),
.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の内容を追加で試しました。
HTMLとの連動部分ですね。
.stencil
というファイルを使用してHTMLを記述するようです。
.stencil
内部では{{}}
で囲んで各種データを扱うようです。
jinja2と似ていて簡単ですね。
<div>{{ meal.name }}</div>
注意事項
Swift Package Managerへの追加について
KituraStencil
をSwift Package Managerに追加する際、先ほどと同様にConfiguration
は不要ですので注意が必要です。PostgreSQL対応
このチュートリアルは、Next Stepsの位置付けで、FoodTrackerBackendをやってからやるような位置付けになっています。
しかし、Website Frontend using the Stencil Template Engineでは、PostgreSQLからのデータ取得をしない前提で記載されています。
PostgreSQLを利用する場合は、そのままコピペしていくとエラーになりますので、若干の修正が必要です。
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()
}
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も試してみようと思います。