question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Intergate Swagger UI Hosting as Ktor Feature

See original GitHub issue

It 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.

screen shot 2018-06-26 at 10 11 29 pm

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:closed
  • Created 5 years ago
  • Reactions:206
  • Comments:20 (6 by maintainers)

github_iconTop GitHub Comments

44reactions
JLLeitschuhcommented, Aug 12, 2018

@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.

20reactions
noahbetzen-wkcommented, Apr 23, 2019

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Intergate Swagger UI Hosting as Ktor Feature : KTOR-774
I spent today overhauling @Niels Falk 's project ktor-swagger to use the newest version of Ktor and also use Gradle to build the...
Read more >
Swagger UI - Ktor
Swagger UI ​​ Ktor allows you to generate and serve Swagger UI for your project based on the existing OpenAPI specification. With Swagger...
Read more >
Tweets with replies by Simon Vergauwen ... - Twitter
Published 7 December 2022 Intergate Swagger UI Hosting as Ktor Feature (KTOR-774) New plugins API for client (KTOR-5161) Rate-Limit Support on Server ...
Read more >
Using OpenAPI and Swagger UI - Quarkus
Another option, that is a feature provided by SmallRye and not part of the specification, is to use configuration to add this global...
Read more >
Free Developer Stuff
Choose a free template, or start from scratch, and add the features you need. ... UI components, designed to integrate beautifully with Tailwind...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found