👋
Ktorを紹介するとともに、2024/4現在の注意点も紹介
前提とするバージョン
io.ktor:ktor-server-core-jvm:2.3.9
io.ktor:ktor-server-netty-jvm:2.3.9
IntelliJ IDEA 2024.1
Ktorの特徴
- クエリパラメーターなどを、@Resourceという機能を使って、タイプセーフなルーティングで実装できる
- ルーティングとプラグインと組み合わせやすく、ネストが深い特定のルーティングだけに認証機能などのプラグインを適用するといったことが自然にできる
- swaggerドキュメントの自動生成ができる 割と目玉機能
- 設定ファイルとして使いやすいHOCON(Human-Optimized Config Object Notation)を使った設定ができる
タイプセーフルーティング(@Resource)などの実装例
実装例です。ポイントは、以下の通りです。
- リソースの定義(URLの定義)する箇所には、リソースの定義(URLの定義)だけを書く。
- リソースハンドラー(Spring Frameworkっぽいネーミングですが)のファイルには、リソースに対するハンドラーを書く。
- 基本的に全部、全部タイプセーフな@Resourceという機能を使って実装する
// Routing.kt
// ルーティングのプラグインを適用する
fun Application.configureRouting() {
install(Resources)
routing {
pingRoute()
route("v1") {
authenticatedRoute()
}
}
}
// AuthenticatedRoute.kt
// リソースハンドラーを並べる
fun Route.authenticatedRoute() {
companiesResourceHandler()
hoge1ResourceHandler()
hoge2ResourceHandler()
hoge3ResourceHandler()
}
// CompaniesResource.kt
// URLの定義を書きます
class CompaniesResource {
@Resource("companies")
class Index(
val q: String? = null,
)
@Resource("companies/{id}")
class Id(
val id: Int,
)
}
/**
CompaniesResourceHandler.kt
ここでは~Resourceに対するハンドラーを書きます
以下、routingのメソッドは使わない
io.ktor.server.routing.get
io.ktor.server.routing.post
io.ktor.server.routing.put
io.ktor.server.routing.delete
以下、resourcesパッケージのメソッドを使う
io.ktor.server.resources.get
io.ktor.server.resources.post
io.ktor.server.resources.put
io.ktor.server.resources.delete
*/
fun Route.companiesResourceHandler() {
val companiesController by inject<companiesController>() // DI with ktor-koin
get<CompaniesResource.Index> { params ->
val responseBody = companiesController.index(call.principal(), params)
call.respond(status = HttpStatusCode.OK, message = responseBody)
}
post<CompaniesResource.Id> { params ->
val createBody = call.receive<CompaniesCreateBody>()
val responseBody = companiesController.create(call.principal(), createBody)
call.respond(status = HttpStatusCode.OK, message = responseBody)
}
}
// schema.kt
// リクエストボディを書きます
data class CompaniesCreateBody(
val name: String,
)
swaggerドキュメントの自動生成での不具合や注意点
生成されるswaggerドキュメントのopenapiのバージョンが新しくなった
IntelliJ IDEA2024.1でswaggerドキュメントの最初の1行目のopenapiのバージョンの箇所が変わりました。
- openapi: "3.0.3"
+ openapi: "3.1.0"
しかし、3.1.0は、OpenAPIGeneratorがまだ不具合を起こす(arrayで且つ同じ型が連続して定義されると正しい型にならない)ため、自動生成された後、手でopenapi: "3.0.3"
へ戻す等の対応を今はするようにしています。
Nullableにしていないプリミティブ型がrequiredにならない
2024/1頃に、IntelliJ IDEA2024.1で修正される予定とのことでしたが、まだ修正されていません。
enumのフィールド毎にenumの定義を生成してしまい、重複する
以下のようにdata classを定義した場合、
data class ExampleClass(
val enum1: ExampleEnum,
val enum2: ExampleEnum,
val enum3: ExampleEnum,
)
enum class ExampleEnum {
A, B, C
}
以下のように重複して生成されます
ExampleClass:
type: "object"
properties:
enum1:
type: "string"
enum:
- "A"
- "B"
- "C"
enum2:
type: "string"
enum:
- "A"
- "B"
- "C"
enum3:
type: "string"
enum:
- "A"
- "B"
- "C"
required:
- "enum1"
- "enum2"
- "enum3"
issue報告 https://youtrack.jetbrains.com/issue/IDEA-344875/OpenAPI-generator-enum-definitions-are-duplicated
isはじまりのBooleanのフィールドがスキップされる
代わりに、flgという名前のフィールドを使うと、正しく生成されます。
Discussion