はじめに
POSTメソッドもVapor4に対応させるべく書き換えていきます。さまざまな資料をひっくり返して試行錯誤を繰り返した末、なんとかエラーを出さずに処理を行うことができるようになりました。
なお、ここで示す方法が正しいとは限らないので、公式のドキュメントも併せて参照してくださいね。
POSTメソッドで変わるところ
routesメソッドの引数変更に対応する
routesメソッドの引数が変わったので、それに関係するところを修正します。修正と言ってもrouter
がapp
に変わるだけです。
パラメータの受け取り方が変わっています
先ほどと同じコードですが、パラメータの渡し方が変わっています。
Vapor3ではString.parameter
で渡していましたが、Vapor4では名前付きラベル(という呼称だったような気がする)で渡します。
この場合では:bookID
ですね。
このパラメータはリクエストに詰められたパラメータの中からラベルを指定して取り出すことができます。取り出すパラメータを明示的に示すことができ、大変わかりやすいです。
なお、nilならば空文字を返すという安直な対応をしていますが、ケースバイケースの対応をお願いします。
レスポンスを返してもらう
いよいよ本丸です。POSTした後のサーバからのレスポンスを返してもらいます。MongoDBに対して処理を行い、その結果に応じてレスポンスを返してみます。
Vapor3ではrouter.post
の戻り値をFuture<HTTPResponse>
としてコーディングしていました。MongoDBへの追加ができると自動的にObjectIDが割り当てられるため、割り当てられたかどうかで追加の成否を判定する方針です。
改めて見てみると、本当に割り当てられたIDが得られたかどうかで判定しているか怪しいですね。確か非同期処理のはずですが、非同期処理が終わる前にreturn
しているような気配があります。
DB上には望んだデータが保存されていたので処理上は問題ないですが、追加処理とステータスコードを返す処理がバラバラに動いているように見えます。何らかの原因で追加されなくてもOK(200)ステータスが返ってきそう。
とはいえ、Vapor4に対応させる予定なので修正はしないですけどね!
さてVapor4ですが、The非同期という書き方です。insertOne
で返された結果(insertOneResult
)をmap
にチェーンして処理します。
末尾のhopはなくても動きそうに見えますが、EventLoopから取り出すというイメージですかね。
DBへの処理なしでHTTPStatusをポンッと返したい
ステータスコードだけをポンっと返すにはどうするのか?
使い所としては、妙なデータやパラメータを与えられて処理できない時にその旨回答するケースなどですかね。
EventLoop内で新しくFutureを作ってmapするということです。これが正しいかどうかはともかく、理屈としては正しそうです。
当然ですが、app.postの戻り値はEventLoopFuture<HTTPStatus>
です。
小ネタ:ステータスコード418(私はティーポット)
20年以上前のエイプリルフールネタですね。諸々の議論の末、Unusedで生き残ったとのこと。
さすがGoogle。しっかりとノッています。
まとめ
本の情報を削除したり更新したりするメソッドも同様の対応でOKです。
それにしても手こずりました。特にEventLoopFutureで。非同期処理のことをもっと深く知っておくべきでした。
よくよく考えれば(考えなくても)、非同期処理が終わる前にreturnで値を返せば、非同期処理で得られる値が欲しくても得られないのは当然な話でしたね。