Swift製のWebフレームワークが早くも乱立していますが、GitHubで1000スター以上獲得している中から、一番deployが手軽そうなVaporに手を出してみます。

Swiftenvと最新版のSwiftをインストール

$ swift --version
Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81)
Target: x86_64-apple-darwin15.0.0

$ brew install kylef/formulae/swiftenv
$ echo 'if which swiftenv > /dev/null; then eval "$(swiftenv init -)"; fi' >> ~/.bash_profile
$ source ~/.bash_profile 

$ swiftenv install swift-DEVELOPMENT-SNAPSHOT-2016-02-25-a

$ swift --version
Apple Swift version 3.0-dev (LLVM b361b0fc05, Clang 11493b0f62, Swift fc261045a5)
Target: x86_64-apple-macosx10.9

$ swiftenv version
DEVELOPMENT-SNAPSHOT-2016-02-25-a

Xcodeで使うSwiftの設定

Xcode 7.3を使っていれば、メニューのXcode -> Toolchainsから切り替えられます。

プロジェクト作成

  1. OS X -> Application -> Command Line ToolからHelloVaporプロジェクトを作成
  2. Import Paths$(SRCROOT)/.build/debug$(SRCROOT)/.build/releaseを設定(コード補完のため)
  3. プロジェクトのディレクトリで$ swift build --initを実行
  4. 作成されたファイルをXcodeに追加する(SourcesのみAdd to targetsを設定)
  5. HelloVaporディレクトリとmain.swiftを削除
  6. Xcode上で実行
Hello, world!
Program ended with exit code: 0

コンソールに上記のメッセージが表示されればOKです。

Vaporを導入

Package.swiftを変更します。

import PackageDescription

let package = Package(
    name: "HelloVapor",
    dependencies: [
        .Package(url: "https://github.com/qutheory/vapor.git", majorVersion: 0),
    ]
)

このままswift buildを実行すると、ld: framework not found XCTest for architecture x86_64で失敗するので、build.shというシェルスクリプトを作って対応します。

#!/bin/sh

echo "Downloading dependencies..."
swift build &>/dev/null
echo "Fixing SPM bug..."
rm -rf Packages/Vapor-0.2.6/Tests/ &>/dev/null
echo "Building..."
swift build
echo "Running..."
.build/debug/HelloVapor
$ ./build.sh 
Downloading dependencies...
Fixing SPM bug...
Building...
Compiling Swift Module 'HelloVapor' (1 sources)
Linking HelloVapor
Running...
Hello, world!

Server.swiftを追加します。

import Vapor

struct Server {
    let app = Application()
    
    init() {
        app.get("welcome") { request in
            return "Hello"
        }
    }

    func start() {
        app.start(port: 8080)
    }
}

main.swiftを書き換えます。

let server = Server()
server.start()

再度build.shを実行して、http://localhost:8080/welcomeにアクセスすれば、Helloと表示されるはずです。

自動テスト

Tests/HelloVapor/ServerTests.swiftを作成します。

import XCTest
@testable import HelloVapor
@testable import Vapor

class ServerTests: XCTestCase {

    override func setUp() {
        super.setUp()
    }
    
    override func tearDown() {
        super.tearDown()
    }

    func testStart() {
        let server = Server()
        server.app.bootRoutes()

        let request = Request(
            method: .Get,
            path: "welcome",
            address: nil,
            headers: ["host": "example.com"],
            body: []
        )
        
        do {
            let result = server.app.router.route(request)!
            var bytes = try result(request: request).data
            
            let utf8 = NSData(bytes: &bytes , length: bytes.count)
            let string = String(data: utf8, encoding: NSUTF8StringEncoding)
            XCTAssert(string == "<html><meta charset=\"UTF-8\"><body>Hello</body></html>")
        } catch {
            XCTFail()
        }
    }
}

build.shを実行してすぐ止めてswift testを実行します。(build.shを書き換えた方がよさそうですが割愛します)

Test Suite 'ServerTests' passed at 2016-02-28 00:26:39.491.
   Executed 1 test, with 0 failures (0 unexpected) in 0.004 (0.004) seconds

これで一応形は整いました。 次からは簡単なWebサービスに必要そうな機能の実装方法を調べていきたいと思います。

ソースコード

https://github.com/tnantoka/swift-a-week/tree/gh-pages/works/HelloVapor

参考