動作環境
この記事では以下の環境で動作を確認しています。
- Xcode9.0
- macOS Sierra バージョン 10.12.6
- MacBook Pro (13-inch,2017,Four Thunderbolt 3 Ports)
- Homebrew 1.3.2
- ruby 2.1.8p440 (2015-12-16 revision 53160) [x86_64-darwin15.0]
- Vapor Toolbox: 2.0.4
- Vapor Framework: 2.2.2
ルーティング-グループ編
前回のVaporのルーティングについて(基礎編)ではルーティングの基礎をみていきました。
この章ではVaporのルーティングをグループ化する方法と1つのクラスで設定するコレクションを見ていきたいと思います。
この方法を利用すれば、WebAPIを設計する際にバージョン指定が簡単にできるようになり、また可読性の高いアプリケーションが作成できます。
Groupメソッド
Droplet
のgroup
メソッドを実行するとクロージャーにRouteBuilder
が渡されます。
これにエンドポイントを設定することでルーティングをグループ化することができます。
GET /v1/users
とGET /v1/users/:id
(idはInt型)を設定してみます。
drop.group("v1") { v1 in
//GET /v1/users
v1.get("users") { req in
return "users"
}
//GET /v1/users/:id
v1.get("users", Int.parameter) { req in
let userId = try req.parameters.next(Int.self)
return "You requested User #\(userId)"
}
}
ビルドしてローカルでサーバーを起動してみます。
$ vapor build
$ vapor run
http://0.0.0.0:8080/v1/users/
にアクセスするとusers
という文字列が返却されます。
http://0.0.0.0:8080/v1/users/1
にアクセスするとYou requested User #1
という文字列が返却されます。
Groupedメソッド
GroupedメソッドはRouteBuilder
を返却します。
先程の例をv2
以下に設定し直してみます。
GET /v2/users
とGET /v2/users/:id
(idはInt型)のエンドポイントを作成します。
let v2 = grouped("v2")
v2.get("users"){ req in
return "users"
}
v2.get("users", Int.parameter) { req in
let userId = try req.parameters.next(Int.self)
return "You requested User #\(userId)"
}
先程と同じようにビルドしてローカルでサーバーを起動してみます。
$ vapor build
$ vapor run
http://0.0.0.0:8080/v2/users/
にアクセスするとusers
という文字列が返却されます。
http://0.0.0.0:8080/v2/users/1
にアクセスするとYou requested User #1
という文字列が返却されます。
これを利用することで、Web APIのバージョン指定が簡単に実現できるでしょう。
ルーティング-コレクション編
ルーティングの基礎編とグループ編でルーティング指定について説明しました。
ここではルーティング指定を一つのクラスにまとめる方法をみていきます。
RouteCollection
プロトコルを適応するクラスを作成すると、ルーティング指定を一つのクラスにまとめることができます。
GET /v3/users
というエンドポイントとGET /v3/articles
というエンドポイントをRouteCollection
に適応したクラスV3Collection
で作成してみます。
import Vapor
import HTTP
import Routing
class V3Collection: RouteCollection {
func build(_ builder: RouteBuilder) {
let v3 = builder.grouped(“v3”)
let users = v3.grouped(“users”)
let articles = v3.grouped(“articles”)
users.get { request in
return “Requested all users.”
}
articles.get(Article.init) { request, article in
return “Requested \(article.name)”
}
}
}
ルート設定をクラスにすることでどんな場所でも記述することができるようになり可読性が高まるでしょう。
Droplet
クラスのcollection
プロパティにこのクラスのインスタンスを渡すことでルーティングを追加できます。
let v3 = V3Collection()
drop.collection(v3)
Droplet
がルートコレクションのbuild(_:)
に渡されてルーティングが追加されます。
初期化で何もしない場合
ルートコレクションの初期化で何もしない場合はEmptyInitializable
も適応することができます。
そうするとルートを追加する際に型を指定するだけで追加できるようになります。
class V3Collection: RouteCollection,EmptyInitializable {
init() { }
...
こうすると、Droplet
にルートを追加するとき、インスタンス化しなくてもよくなります。
drop.collection(V3Collection.self)
参考
Route Groups
https://docs.vapor.codes/2.0/routing/group/
Route Collections
https://docs.vapor.codes/2.0/routing/collection/