Intergate Swagger UI Hosting as Ktor Feature
See original GitHub issueIt would be really nice if Ktor could support hosting a Swagger UI that is generated from your routes
configuration.
For example, the following could be used to generate a Swagger UI.
data class PetModel(val id: Int?, val name: String)
data class PetsModel(val pets: MutableList<PetModel>)
val data = PetsModel(mutableListOf(PetModel(1, "max"), PetModel(2, "moritz")))
fun newId() = ((data.pets.map { it.id ?: 0 }.max()) ?: 0) + 1
@Group("pet operations")
@Location("/pets/{id}")
class pet(val id: Int)
@Group("pet operations")
@Location("/pets")
class pets
@Group("debug")
@Location("/request/info")
class requestInfo
@Group("debug")
@Location("/request/withHeader")
class withHeader
class Header(val optionalHeader: String?, val mandatoryHeader: Int)
@Group("debug")
@Location("/request/withQueryParameter")
class withQueryParameter
class QueryParameter(val optionalParameter: String?, val mandatoryParameter: Int)
fun main(args: Array<String>) {
val server = embeddedServer(Netty, getInteger("server.port", 8080)) {
install(DefaultHeaders)
install(Compression)
install(CallLogging)
install(ContentNegotiation) {
gson {
setPrettyPrinting()
}
}
install(Locations)
install(SwaggerSupport) {
forwardRoot = true
swagger.info = Information(
version = "0.1",
title = "sample api implemented in ktor",
description = "This is a sample which combines [ktor](https://github.com/Kotlin/ktor) with [swaggerUi](https://swagger.io/). You find the sources on [github](https://github.com/nielsfalk/ktor-swagger)",
contact = Contact(
name = "Niels Falk",
url = "https://nielsfalk.de"
)
)
}
routing {
get<pets>("all".responds(ok<PetsModel>())) {
call.respond(data)
}
post<pets, PetModel>("create".responds(ok<PetModel>())) { _, entity ->
// http201 would be better but there is no way to do this see org.jetbrains.ktor.gson.GsonSupport.renderJsonContent
call.respond(entity.copy(id = newId()).apply {
data.pets.add(this)
})
}
get<pet>("find".responds(ok<PetModel>(), notFound())) { params ->
data.pets.find { it.id == params.id }
?.let {
call.respond(it)
}
}
put<pet, PetModel>("update".responds(ok<PetModel>(), notFound())) { params, entity ->
if (data.pets.removeIf { it.id == params.id && it.id == entity.id }) {
data.pets.add(entity)
call.respond(entity)
}
}
delete<pet>("delete".responds(ok<Unit>(), notFound())) { params ->
if (data.pets.removeIf { it.id == params.id }) {
call.respond(Unit)
}
}
get<requestInfo>(
responds(ok<Unit>()),
respondRequestDetails()
)
get<withQueryParameter>(
responds(ok<Unit>())
.parameter<QueryParameter>(),
respondRequestDetails()
)
get<withHeader>(
responds(ok<Unit>())
.header<Header>(),
respondRequestDetails()
)
}
}
server.start(wait = true)
}
fun respondRequestDetails(): suspend PipelineContext<Unit, ApplicationCall>.(Any) -> Unit {
return {
call.respond(
mapOf(
"parameter" to call.parameters,
"header" to call.request.headers
).format()
)
}
}
private fun Map<String, StringValues>.format() =
mapValues {
it.value.toMap()
.flatMap { (key, value) -> value.map { key to it } }
.map { (key, value) -> "$key: $value" }
.joinToString(separator = ",\n")
}
.map { (key, value) -> "$key:\n$value" }
.joinToString(separator = "\n\n")
This is the swagger UI generated from the above.
I spent today overhauling @nielsfalk’s project ktor-swagger to use the newest version of Ktor and also use Gradle to build the application PR here.
I think this project has quite a bit of potential and could satisfy a need in the community by allowing for a fast way to create documentation for API’s written using Ktor.
If the Ktor team would like to adopt this project as a feature, I’m happy to try to make the port from the external project it is today into this repository.
If the interest does not exist to adopt a new feature, I totally understand. The concern that I have with publishing this myself (or with @nielsfalk assistance) is the issue of incompatible breaking changes in Ktor (as Ktor is pre-1.0).
I open the floor to the developers of this project. I’d love to see this integrated as a fully supported feature, but I understand if this is outside the scope of this project.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:206
- Comments:20 (6 by maintainers)
Top GitHub Comments
@orangefiredragon It’s currently released here: https://github.com/nielsfalk/ktor-swagger
I’d love to integrate it officially.
Currently the project is 90% developed for my own use case at my company. The API is also pretty fluid currently as I’m still figuring out where we are missing things/need new functionality.
But in its current state it’s very functional.
This missing feature is the only thing keeping my company from adopting Ktor. Until then we’re using Spring and SpringFox.
Huge props to @JLLeitschuh for the work he did. I’d love to see it (or a similar implementation) merged into Ktor itself.
I looked around online for a public roadmap but couldn’t find one; it’d be nice to at least know if the Ktor/Kotlin/JetBrains team has a plan for this. Even just a “more/less than 6 months” estimate would be great.