てくてくテック

気ままに開発のメモを書いていこうと思います。主にSwiftかと。

Kituraを使ってサーバーサイドSwiftを試してみた

はじめに

すごく久しぶりに投稿します。今後は、友人たちと投稿しようと思います。

今回は、Swiftを使ってサーバーサイドを書いてみたいと思い、IBM製フレームワークのKituraを使ってみた件について、toosaaがお話しします。

内容としては、Getting Startedを動かしてみるまでと、ちょっとした調査となります。

動作環境

  • macOS High Sierra ver 10.13.3
  • Xcode ver 9.2
  • Homebrew 1.5.2

Getting Started

Getting Startedの手順に従います。2017年2月3日現在、同じことを書いているだけです。

事前準備

Kitura コマンドラインのインストール

  • $ brew tap ibm-swift/kitura
  • $ brew tap ibm-swift/kitura

プロジェクトの初期化

  • $ HelloKitura
  • $ cd HelloKitura
  • $ kitura init
    • ここにあるように色々なファイルが作られます
      • .gitignoreとかもあります
      • この記事書いている時に、このページにCRUD projectやmodel generatorというのがあるのに気づきました。あとで読みます。

Hello, World!

  • $ open HelloKitura.xcodeproj
  • Sources/Application/Application.swiftpostInit()メソッドの中に下記のコードを挿入

注) 私の環境ではimport Kiture のとこにNo such module 'Kitura'とエラー出ましたが普通にビルドできます。

// Handle HTTP GET requests to /
router.get("/") {
    request, response, next in
    response.send("Hello, World!")
    next()
}
  • ビルドスキームをHelloKituraに変更(デフォルトではHelloKitura-Packageになっているはず)
    • Xcode左上の停止ボタン(四角いやつ)の右
  • ⌘-Rで実行
  • http://localhost:8080 にアクセス

これだけです。

調査

Hello, World!で書いたコードについて調べてみます。

routeの指定

routerはRouter Classのインスタンスで、getのオーバーロードをいくつか持ってます。そのメソッドの宣言を引っ張って来ると下記の通りです。参考

//RouterHTTPVerbs_generated.swift
public func get(_ path: String?=nil, handler: RouterHandler...) -> Router
public func get(_ path: String?=nil, handler: [RouterHandler]) -> Router
public func get(_ path: String?=nil, allowPartialMatch: Bool = true, middleware: RouterMiddleware...) -> Router 
public func get(_ path: String?=nil, allowPartialMatch: Bool = true, middleware: [RouterMiddleware]) -> Router

今回使っているのは、これらの一つですが、下記のメソッドもあります。チュートリアルで使われています。

//CodableRouter.swift
public func get<O: Codable>(_ route: String, handler: @escaping CodableArrayClosure<O>)
public func get<O: Codable>(_ route: String, handler: @escaping SimpleCodableClosure<O>)
public func get<Id: Identifier, O: Codable>(_ route: String, handler: @escaping IdentifierSimpleCodableClosure<Id, O>)
public func get<Q: QueryParams, O: Codable>(_ route: String, handler: @escaping (Q, @escaping CodableArrayResultClosure<O>) -> Void)

上のget()は、クロージャーを使っていますが、@escapingがついていない&返り値があるので同期処理なのだろうと思います。反対に下のは、非同期処理で使うのだろうと思います。あとCodableなのでjsonのシリアライズでシリアライズ。

どちらにせよ、第一引数の文字列がurlに関るはずです。名前がrouteとpathで違うのはわかりませんが。

http responseを返す

Hello, Worldではresponse.send("Hello, World!")でhttp responseを返していると予想できます。このresponseはRouterResponse classのインスタンスです。このclassのsend()は下記がとなっています。参考

public func send(_ str: String) -> RouterResponse
public func send(data: Data) -> RouterResponse
public func send(fileName: String) throws -> RouterResponse
public func send(json: [Any]) throws -> RouterResponse
public func send(json: [String: Any]) throws -> RouterResponse
public func send(status: HTTPStatusCode) -> RouterResponse
public func send<T : Encodable>(_ obj: T) throws -> RouterResponse
public func send<T : Encodable>(json: T) throws -> RouterResponse
public func send<T : Encodable>(jsonp: T, callbackParameter: String = "callback") throws -> RouterResponse

今回は一番最初のstringを返しています。静的なhtmlならsend(fileName: String), web apiならjsonのを使えば良さそうです。

next?

RouterHandlerの第三引数で、@escaping () -> Voidというクロージャーです。ドキュメントでは下記のように書かれています。ちょっと、コードを読んでみましたが、よくわかっていません(・_・;)

The closure to invoke to cause the router to inspect the path in the list of paths.

終わりに

今回は、KituraのGetting Startedと、その中で出てきたコードの簡単な調査を話しました。次回は、チュートリアルの内容に触れようと思います。