VaporアプリケーションでAPIを作る(GET編)

はじめに

どうもどうも。API初心者です。失礼します(拝み手)。
他者が公開しているAPIを使うことはあっても、APIを公開する側に回るとは思いもしなかったです。

サーバサイドからMongoDBへアクセスするサーバサイドアプリケーションを作ってみました。が、サーバサイドアプリケーションの構築経験がほぼ無い状態で足元がグラグラの状態です。
このまま進めばグダる未来が現実のものとなるので、そうならないように足回りを固めようと思います。

セキュリティ関係のことはここでは触れませんので、ご注意を。あくまでも一時的かつローカルで試すことを目的に据えています。

まずはスッピンで動かす

何もしない状態でXCodeでRunすると、http://localhost:8080でアプリケーションが動くようになります。実行すると、このような感じ。

Routeを追加する

もともと生成されているroutes.swiftにRouteを追加してみます。
これで、It works!以外を表示させてみます。

router.get("hello") { req in
    return "Hello, world!"
}
router.get("hello/test") { req in
    return "Hello, test!"
}

XCodeでRunからのhttp://localhost:8080/hellohttp://localhost:8080/hello/test
の結果です。

Oops!

router.get("hello","test") { req in
    return "Hello, test!"
}

パラメータを渡してみる

まずはベーシックに文字列型から

ツーと言えばカー、山といえば川のような定型のやり取りだけでは物足りないです。パラメータを渡してみましょう。さっきのrouteを修正します。

router.get("hello",String.parameter) { req -> String in
    let param = try req.parameters.next(String.self)
    return "Hello, \(param)!"
}

先ほどtestと入れたところに任意の文字列を入れてみます。試しにparameterを入れてみます。

日本語もいけますね。

型を変えてもいけますよ

StringではなくIntに変えてみます。

router.get("hello",Int.parameter) { req -> String in
    let param = try req.parameters.next(Int.self)
    return "Hello, \(param)!"
}

ただし、このケースでhttp://localhost:8080/hello/abcなど数字以外が入ったときはエラーになります。

The parameter was not convertible to an Int

型には気をつけたほうがいいかもしれない

利用する人がお行儀良いかどうかは不確定です。いろんな人が居ます。
ですので、ひとまず文字列で受け取り、コード内で処理したほうがいいかもしれません。

router.get("hello",String.parameter) { req -> String in
    let param = try req.parameters.next(String.self)
    // 数字を受け取るつもりだったなら、ここでパースする。
    return "Hello, \(param)!"
}

データを取り回す構造体を作る案もありますが、心配ならばパースするなどの対策を入れておくのがいいかもしれません。

注意

同じルートで型だけ変えてみるオーバロードのようなものはできないです。例えば、このような形はうまくいきません。

router.get("hello",String.parameter) { req -> String in
    let param = try req.parameters.next(String.self)
    return "Hello, \(param)!"
}
router.get("hello",Int.parameter) { req -> String in
    let param = try req.parameters.next(Int.self)
    return "Hello, \(param)!"
}

このようにしてしまうと、常に2つ目のrouteに入ってしまいます。そして、2つ目のrouteに入るにも関わらず、Vapor側では入力されているパラメータをStringとみなしているようです。推測ですが、コード上IntだとしているのにVapor側はStringと認識しているということになり、型が違うというエラーが発生してしまいます。

Invalid parameter type: int != string

素直にrouteを変えるか、一律文字列で受け取ってコード側で何とかするのが良さそうです。

まとめ

今日はGETだけでここまでにします。次はAPIっぽくデータのPOSTを試してみます。徐々にDBサーバに向けて進めていきます。