Ktor API (Kotlin) 的 Swagger API 文档中未显示标头

发布于 2025-01-14 15:36:15 字数 3194 浏览 2 评论 0原文

我正在使用 papsign/Ktor-OpenAPI-Generator 为 Ktor 应用程序生成 Swagger API 文档。我有一个 POST 端点,其中包含请求中的标头。完整代码如下:

fun main(args: Array<String>): Unit =
    io.ktor.server.netty.EngineMain.main(args)

@Suppress("unused")
fun Application.module() {
    
    install(OpenAPIGen) {
        info {
            version = "1.0.0"
            title = "Accelerated Earn"
            description = "Accelerated earn service provides extra earn."
            contact {
                name = "John Doe"
                email = "[email protected]"
            }
        }

        // describe the servers, add as many as you want
        server("/") {
            description = "This server"
        }

        replaceModule(DefaultSchemaNamer, object: SchemaNamer {
            val regex = Regex("[A-Za-z0-9_.]+")
            override fun get(type: KType): String {
                return type.toString().replace(regex) { it.value.split(".").last() }.replace(Regex(">|<|, "), "_")
            }
        })
    }
    
    // Configuring jackson serialization
    install(ContentNegotiation) {
        jackson {
            dateFormat = DateFormat.getDateTimeInstance()
        }
    }

    // Configuring swagger routes
    routing {
        get("/openapi.json") {
            call.respond(application.openAPIGen.api.serialize())
        }

        get("/") {
            call.respondRedirect("/swagger-ui/index.html?url=/openapi.json", true)
        }
    }
    
    demoFunction()
}

// Defining the DEMO tag
enum class Tags(override val description: String) : APITag {
    DEMO("This is a demo endpoint")
}

// Request is of type DemoClass, response is Boolean
fun Application.demoFunction() {
    apiRouting {
        tag(Tags.DEMO) {
            route("/demo") {
                post<Unit, Boolean, DemoClass>(
                    status(HttpStatusCode.OK),
                    info(
                        "Demo endpoint",
                        "This is a demo API"
                    ),
                    exampleResponse = true,
                    exampleRequest = DemoClass(name = "john doe", xyz = "some header")
                ) { _, request ->
                    respond(true)
                }
            }
        }
    }
}

@Request("Request")
data class DemoClass(
    @HeaderParam("Sample header")
    val xyz: String,
    @PathParam("Name")
    val name: String
)

在 DemoClass 中,我使用 @HeaderParam 注释将“xyz”属性表示为标头,并使用 @PathParam 注释将“name”表示为请求的参数。我预计“xyz”将在文档中显示为标头,但它显示为请求正文的一部分,并且没有提及有关标头的内容(如下图所示)
xyz 是在请求正文中

xyz 在架构中显示为请求正文的一部分

没有提及标题

因此,同时制作请求时,我必须将标头放入请求正文中,而不是将其作为请求中的标头传递。有可能解决这个问题吗?我该怎么做?

I'm using the papsign/Ktor-OpenAPI-Generator to generate Swagger API documentation for a Ktor application. I have a POST endpoint which contains headers in the request. Here is the entire code:

fun main(args: Array<String>): Unit =
    io.ktor.server.netty.EngineMain.main(args)

@Suppress("unused")
fun Application.module() {
    
    install(OpenAPIGen) {
        info {
            version = "1.0.0"
            title = "Accelerated Earn"
            description = "Accelerated earn service provides extra earn."
            contact {
                name = "John Doe"
                email = "[email protected]"
            }
        }

        // describe the servers, add as many as you want
        server("/") {
            description = "This server"
        }

        replaceModule(DefaultSchemaNamer, object: SchemaNamer {
            val regex = Regex("[A-Za-z0-9_.]+")
            override fun get(type: KType): String {
                return type.toString().replace(regex) { it.value.split(".").last() }.replace(Regex(">|<|, "), "_")
            }
        })
    }
    
    // Configuring jackson serialization
    install(ContentNegotiation) {
        jackson {
            dateFormat = DateFormat.getDateTimeInstance()
        }
    }

    // Configuring swagger routes
    routing {
        get("/openapi.json") {
            call.respond(application.openAPIGen.api.serialize())
        }

        get("/") {
            call.respondRedirect("/swagger-ui/index.html?url=/openapi.json", true)
        }
    }
    
    demoFunction()
}

// Defining the DEMO tag
enum class Tags(override val description: String) : APITag {
    DEMO("This is a demo endpoint")
}

// Request is of type DemoClass, response is Boolean
fun Application.demoFunction() {
    apiRouting {
        tag(Tags.DEMO) {
            route("/demo") {
                post<Unit, Boolean, DemoClass>(
                    status(HttpStatusCode.OK),
                    info(
                        "Demo endpoint",
                        "This is a demo API"
                    ),
                    exampleResponse = true,
                    exampleRequest = DemoClass(name = "john doe", xyz = "some header")
                ) { _, request ->
                    respond(true)
                }
            }
        }
    }
}

@Request("Request")
data class DemoClass(
    @HeaderParam("Sample header")
    val xyz: String,
    @PathParam("Name")
    val name: String
)

In DemoClass, I have used @HeaderParam annotation to denote "xyz" property as a header, and used @PathParam annotation to denote "name" as a parameter of the request. I expected that "xyz" would be shown as a header in the documentation but it is being shown as a part of the request body, and nothing about headers is mentioned (as shown in the below figures)
xyz is in the request body

xyz is shown as a part of the request body in the schema

No mention of headers

Because of this, while making a request, I have to put the header inside the request body instead of passing it as a header in the request. Is it possible to fix this? How do I do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

↙温凉少女 2025-01-21 15:36:15

发现错误了。 post函数的第一个参数是标题的类。这是更新后的代码:-

fun Application.demoFunction() {
    apiRouting {
        tag(Tags.DEMO) {
            route("/demo") {
                post<Headers, Boolean, DemoClass>(
                    status(HttpStatusCode.OK),
                    info(
                        "Demo endpoint",
                        "This is a demo API"
                    ),
                    exampleResponse = true,
                    exampleRequest = DemoClass(name = "john doe")
                ) { header, request ->
                    respond(true)
                }
            }
        }
    }
}

@Request("Request")
data class DemoClass(
    @PathParam("Name")
    val name: String
)

data class Headers(
    @HeaderParam("Sample Header")
    val xyz: String
)

Found the error. The first parameter of post function is the class of header. Here is the updated code :-

fun Application.demoFunction() {
    apiRouting {
        tag(Tags.DEMO) {
            route("/demo") {
                post<Headers, Boolean, DemoClass>(
                    status(HttpStatusCode.OK),
                    info(
                        "Demo endpoint",
                        "This is a demo API"
                    ),
                    exampleResponse = true,
                    exampleRequest = DemoClass(name = "john doe")
                ) { header, request ->
                    respond(true)
                }
            }
        }
    }
}

@Request("Request")
data class DemoClass(
    @PathParam("Name")
    val name: String
)

data class Headers(
    @HeaderParam("Sample Header")
    val xyz: String
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文