Ktor で Locations を使う際、普通にForm DataとしてPOSTすると404エラーになってしまう。
GET parametersの項 を参照すると、サポート対象の機能のはずなのに。
ちなみに、 Issue #601 もあがっているが、半年以上放置されている。自分もコメントを追加しておいた。
ここでは残念な方法ではあるが、いくつか回避策があるので、その方法を記載しておく。
エラーになるパターン
このケースのように、Form Dataとしてパラメータを受け取ろうとすると、404エラーになってしまう。
@Location("/hoge")
data class HogeParamater(val param1, val param2)
routing {
post<HogeParamater> { param ->
// HogeParamaterを使った何らかの処理
}
}
試しに、以下のようにデフォルト値を設定するとエラーにはならないが、値はデフォルト値のままである。
@Location("/hoge")
data class HogeParamater(val param1: String = "default1", val param2: String = "default2")
routing {
post<HogeParamater> { param ->
// HogeParamaterを使った何らかの処理
}
}
回避方法1
以下のようにパラメータにデフォルト値を設定することで404エラーを回避し、var
で宣言することでパラメータへの再代入を許可した上でreceiveParameters
から値を取得して上書きする。
URLが変わらないので、この方法がまだしも一番ましかと判断し、自分はこの方法を選択した。
@Location("/hoge")
data class HogeParamater(var param1: String = "default1", var param2: String = "default2")
routing {
post<HogeParamater> { param ->
val receiveParameters = call.receiveParameters()
param.param1 = receiveParameters["param1"]!!
param.param2 = receiveParameters["param2"]!!
// HogeParamaterを使った何らかの処理
}
}
回避方法2
URL埋め込みパラメータにする。
これも動くのだが、URLが変わってしまうので非常に悲しい。
@Location("/hoge/{param1}/{param2}")
data class HogeParamater(val param1, val param2)
routing {
post<HogeParamater> { param ->
val receiveParameters = call.receiveParameters()
param.param1 = receiveParameters["param1"]!!
param.param2 = receiveParameters["param2"]!!
// HogeParamaterを使った何らかの処理
}
}
回避方法3
そもそもLocationsを使わず、Routingを利用する。
この方法も問題なく動くが、そもそもパラメータをtype safeに受け取るためにLocationsを導入したのであるから、非常に悲しい。
data class HogeParamater(val param1, val param2)
routing {
post("/hoge") {
val receiveParameters = call.receiveParameters()
val param1 = receiveParameters["param1"]!!
val param2 = receiveParameters["param2"]!!
val param = HogeParamater(param1, param2)
// HogeParamaterを使った何らかの処理
}
最後に
自分の知識不足の可能性も大いにあるが、Ktorはアプリケーション開発の関心事のRoutingやValidationがまだまだこなれてない感が強い。
今回レベルのバグが放置されるようだと、Starの数は多いものの実際使ってる人は少ないのでは?という気持ちになってしまう。
何にしても個人サービスとかならいいかもしれないが、プロダクションで使うのはもう少し様子見したいと思う。