はじめに
この記事ではIBM製のSwiftでサーバーサイドを実装することのできるフレームワークのKituraを使用してRESTful APIを作成するときの大まかなポイントをまとめていきます。ハンズオンではないです。
今回は、PostgreSQLのORMを併用してデータを保存と取得ができるAPIを作る想定で進めていきます。
今回使用するライブラリのうち、自分で追加する必要のあるライブラリ
ライブラリ名 | バージョン |
---|---|
SwiftKueryORM | 0.6.1 |
SwiftKueryPostgreSQL | 2.1.1 |
Model
まずは、永続化するモデルの定義から。
SwiftKueryORMにはModel
というプロトコルがあり、それに準拠してモデルを作成します。ModelはCodableに準拠しています。
また、var id: Int?
と記述しておくと、idがnilの場合に自動でidを振り与えてくれるらしいです。注意としては、手動でもidを設定することができるのでそのidがもう既に存在していないかは保存する前に確認した方が良いようです。
// id以外のプロパティは適当です。
struct Diary: Model, Equatable {
var id: Int?
var title: String?
var content: String?
var posterName: String?
var likedCount: Int?
var createdAt: Date?
var updatedAt: Date?
}
このあと、PostgreSQLをインストールしたり、Terminal上で
createdb データベース名
などを叩いて、初期の設定しなければならないのですが今回は省略します。
それでは、本題に入ります!
GET
KituraはRouter
というクラスを使用してルーティングを設定します。App
クラスからプロパティとして取得できるのでそれを使用します。
app.router.get("/api/v1/diary/read") { (request, response, next) in
}
getメソッドの第一引数はルーティングを指定します。この場合、ローカル環境なら http://localhost:8080/api/v1/diary/read
にアクセスすればコールバックが呼ばれます。
もしクエリパラメータ ?id=1234
みたいなものを取得したい場合は、request.queryParameters
で取得できます。
let id = request.queryParameters["id"]
READ (PostgreSQL)
GETリクエストを受け取ったら全件取得をします。
ORMを使用して非常に簡潔にかけます。
取得したいエンティティクラスから**.findAll
**メソッドを呼ぶだけです。例えば、上のDiaryモデルとして保存したデータを取得したい場合は
Diary.findAll { (diaries: [Diary]?, error: RequestError?) in
}
このような感じで取得することができます。
まとめると、
app.router.get("/api/v1/diary/read") { (request, response, next) in
Diary.findAll { (diaries: [Diary]?, error: RequestError?) in
guard let diaries = diaries else { return next() }
response.send(diaries)
next()
}
}
これで、データを取得してレスポンスで返せると思います。
POST
postは初見でやったときは結構はまりました。。。まとめにも記載しますが、Codable Routingを使用しないでrequest.body?.asRaw
でData型を取得するにはミドルウェアを指定する必要があるようです。
app.router.post("/api/v1/diary/create", middleware: BodyParser())
このBodyParser()によって、送られてきたBody部分を適切なプロパティに流してくれるのだと僕は考えています。
Note: If you have not declared a Content-Type header, ParsedBody will be nil.
引用: https://ibm-swift.github.io/Kitura/Classes/BodyParser.html
ただ、リクエスト時に**Content-Type
を指定しないとBody部分はnilになってしまう**ので注意です。
また、今回はCodableなので、asRaw
プロパティにアクセスします。
app.router.post("/api/v1/diary/create") { (request, response, next) in
guard let data = request.body?.asRaw else {
return next()
}
guard let diary = try? JSONDecoder().decode(Diary.self, from: data) else {
return next()
}
}
上のような流れで、送られてきたBody部分をDiaryモデルにデコードしています。
CREATE (PostgreSQL)
KueryORMがsave
メソッドを用意してくれているのでそれを使いましょう。
// 本当は、保存する前に、idがユニークなものかを確認した方が良いです。。。
diary.save() { (diary: Diary?, error: RequestError?) in
if let error = error {
print(error)
return next()
}
guard let diary = diary else {
return next()
}
response.send(diary)
}
app.router.post("/api/v1/diary/create", middleware: BodyParser())
app.router.post("/api/v1/diary/create") { (request, response, next) in
guard let data = request.body?.asRaw else {
return next()
}
guard let diary = try? JSONDecoder().decode(Diary.self, from: data) else {
return next()
}
diary.save() { (diary: Diary?, error: RequestError?) in
if let error = error {
print(error)
return next()
}
guard let diary = diary else {
return next()
}
response.send(diary)
}
}
まとめ
今回は、
- KituraでGETリクエスト・POSTリクエストをどのように行うのか。
- KituraでORMを使用したときにどのような流れでデータの取得・保存を行うのか。
がなんとなくでも掴めていただけたらめちゃくちゃ嬉しいです。
自分もまだ分かっていない部分が多いので、もっとKituraに強くなりたいと思います。
ちなみに、Codable Routingを使用して書くともう少しスマートに書けるので別記事で紹介したいです。