Kituraのチュートリアル(ToDoBackend)を試してみた
はじめに
こんにちは。toosaaです。
前回IBM製のフレームワークKituraのGetting Startedに従ってサーバーサイドのHello, World!を行いました。今回は、Getting Startedに続いてチュートリアルとして用意されているToDoBackendを試してみます。そして次回、その内容の一部を調査しようと思います。
動作環境
- macOS High Sierra ver 10.13.3
- Xcode ver 9.2
- Homebrew 1.5.2
事前準備
ToDoBbackendに対して、todo-backend-js-specによるテストをグリーンにしていくことで開発していきます。テスト駆動ですね。そのため、ToDoBackendとtodo-backend-js-specの二つのプロジェクトを用意します。
$ git clone http://github.com/IBM/ToDoBackend
$ git clone http://github.com/TodoBackend/todo-backend-js-spec
試しにテストを実行してみる
$ cd path/to//todo-backend-js-spec
$open index.html
- 起動したブラウザのページのtest target rootに
http://localhost:8080
をセット - run testsをクリック
これでテストを実行できます。おそらく、最初の行にthe api root responds to a GET (i.e. the server is up and accessible, CORS headers are set up)
とエラーが出てると思います。サーバーを起動してないのだからエラー出て当然です。
ToDoBackendのサーバーを初期化する
$ cd path/to/ToDoBackend
$ mkdir ToDoServer
$ cd ToDoServer
$ kitura init
open ToDoServer.xcodeproj
- ビルドスキームをToDoServerに変更(デフォルトではToDoServer-Packageになっているはず)
- Xcode左上の停止ボタン(四角いやつ)の右
- ⌘-Rで実行
- 再度テストを実行する
おそらくまたthe api root responds to a GET (i.e. the server is up and accessible, CORS headers are set up)
とエラーが出てると思います。 Cross Origin Resource Sharing (CORS) が有効になっていないからです。
Cross Origin Resource Sharing (CORS) を有効化する
- CORSライブラリをPackage.swiftに追加する
- (注)チュートリアルページではdepenciesの方にConfigurationとかあり、エラーになった
// Package.swift let package = Package( name: "ToDoServer", dependencies: [ .package(url: "https://github.com/IBM-Swift/Kitura.git", .upToNextMinor(from: "2.0.0")), .package(url: "https://github.com/IBM-Swift/HeliumLogger.git", .upToNextMinor(from: "1.7.1")), .package(url: "https://github.com/IBM-Swift/CloudEnvironment.git", from: "6.0.0"), .package(url: "https://github.com/RuntimeTools/SwiftMetrics.git", from: "2.0.0"), .package(url: "https://github.com/IBM-Swift/Health.git", from: "0.0.0"), //ここ追加 .package(url: "https://github.com/IBM-Swift/Kitura-CORS", .upToNextMinor(from: "2.0.0")), ], targets: [ .target(name: "ToDoServer", dependencies: [ .target(name: "Application"), "Kitura" , "HeliumLogger"]), //ここにKituraCORS追加 .target(name: "Application", dependencies: [ "Kitura", "KituraCORS", "CloudEnvironment", "Health" , "SwiftMetrics", ]), .testTarget(name: "ApplicationTests" , dependencies: [.target(name: "Application"), "Kitura","HeliumLogger" ]) ] )
- packageをインストールするためにregenerateする
- Xcodeを閉じる
$ cd path/to/ToDoBackend/ToDoServer
$ swift package generate-xcodeproj
$ open TodoServer.xcodeproj
- CORSライブラリを使う
- Sources/Application/Application.swiftを開く
import KituraCORS
を追記- postInit()の中に下記のコードを追加
let options = Options(allowedOrigin: .all) let cors = CORS(options: options) router.all("/*", middleware: cors)
この状態で再度テストを行うと、the api root responds to a POST with the todo which was posted to it
に変わっているはずです。(注)もし変更なかったら、テスト用のページを一旦戻りrun testsしてみると変わるかと思います。このテスト結果はPostリクエストの処理を実装してないためです。
Postリクエストの処理を実装する
- Modelを生成する
- XcodeのProjectNavigator上のApplicationフォルダに右クリック
- New File...を選択する
- 名前をModels.swiftにする
- TargetsをApplicationだけにする(おそらくToDoServerPackageDescriptionにチェックがついている)。
- 私の環境だと最初はTargetsを選択する領域が出てなかったのですが、何かのボタンを押したら出たと記憶しています
- Create
- 下記のコードを追加
public struct ToDo : Codable, Equatable { public var id: Int? public var user: String? public var title: String? public var order: Int? public var completed: Bool? public var url: String? public static func ==(lhs: ToDo, rhs: ToDo) -> Bool { return (lhs.title == rhs.title) && (lhs.user == rhs.user) && (lhs.order == rhs.order) && (lhs.completed == rhs.completed) && (lhs.url == rhs.url) && (lhs.id == rhs.id) } }
ToDoアイテムを格納するArrayを作る(このチュートリアルではDBは使わない)
- Sources/Application/Application.swiftを開く
let cloudEnv = CloundEnv()
の下に下記のコードを追加するprivate var todoStore = [ToDo]() private var nextId :Int = 0 private let workerQueue = DispatchQueue(label: "worker")
App Class内に下記メソッドを追加
func execute(_ block: (() -> Void)) { workerQueue.sync { block() } }
/
へのpostリクエストに対応するhandlerを登録する- postInit()に下記コードを追加する
router.post("/", handler: storeHandler)
- App Classに下記のメソッドを追加する
func storeHandler(todo: ToDo, completion: (ToDo?, RequestError?) -> Void ) { var todo = todo if todo.completed == nil { todo.completed = false } todo.id = nextId todo.url = "http://localhost:8080/\(nextId)" nextId += 1 execute { todoStore.append(todo) } completion(todo, nil) }
DELETE, GET, PATCHの実装もする
基本は、postと同じ感じなので割愛
終わりに
今回は、Kituraのチュートリアルの一つToDoBackendを試してみました。次回は、この中で調査したものについて書きます。