はじめに
どうもどうも。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/hello
とhttp://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サーバに向けて進めていきます。