はじめに
以下の書籍の10章でKtorのルーティングをしている際にかなり躓いたのでまとめます
KtorのType-safe routingがうまく行かない方がいれば参考になればと思います
問題
書籍のP258パスの共通化をKtorのType-safe routingで行いました
書籍ではLocation
を使っていたため、Resources
に書き換えて以下のコードにしました
Routing.kt
package com.example.plugins
import io.ktor.server.routing.*
import io.ktor.http.*
import io.ktor.resources.*
import kotlinx.serialization.Serializable
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.request.*
import io.ktor.server.resources.*
import io.ktor.server.resources.Resources
fun Application.configureRouting() {
install(Resources)
routing {
get<User.New> { param ->
val id = param.id
call.respondText("$id")
}
}
}
@Serializable
@Resource("/user")
class User() {
@Serializable
@Resource("{id}")
class New(val id: Long)
}
しかしアクセスすると以下のエラーが発生します
curl http://localhost:8080/user/1
/{id}, segment:1 -> SUCCESS; Parameters [id=[user]] @ /{id}
/{id}/(method:GET), segment:1 -> FAILURE "Not all segments matched" @ /{id}/(method:GET)
Matched routes:
No results
Route resolve result:
FAILURE "No matched subtrees found" @ /
ログを見る限り、/{id}
というルーティングはありますが、/user
はなさそうでした
どうすれば/user/{id}
のルーティングを用意できるのでしょうか
解決方法
まずは最終的なコードを載せます
Routing.kt
package com.example.plugins
import io.ktor.server.routing.*
import io.ktor.http.*
import io.ktor.resources.*
import kotlinx.serialization.Serializable
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.request.*
import io.ktor.server.resources.*
import io.ktor.server.resources.Resources
fun Application.configureRouting() {
install(Resources)
routing {
get<User.New> { param ->
val id = param.id
call.respondText("$id")
}
}
}
@Serializable
@Resource("/user")
class User() {
@Serializable
@Resource("{id}")
class New(val parent: User = User(), val id: Long)
}
ポイントは
class New(val parent: User = User(), val id: Long)
の行になります。ここでval parent: User = User()
をやっていますが、この箇所があることによって/user
がパスの先頭(親)になるようでした
おわりに
何度も公式のコードを見たり、調べたりしますがなかなか気づけなかったので多くの時間を使ってしまいました
参考