feat: reintroduce swagger compatability (#426)

This commit is contained in:
Pavel Kulikov
2023-03-14 20:43:06 +00:00
committed by GitHub
parent 9b93c887a2
commit 54d12de67a
14 changed files with 116 additions and 1 deletions

View File

@ -4,6 +4,8 @@
### Added ### Added
- Add support for swagger documentation
### Changed ### Changed
### Remove ### Remove

View File

@ -18,7 +18,7 @@ import kotlinx.html.unsafe
/** /**
* Provides an out-of-the-box route to view docs using ReDoc on the specified [path]. * Provides an out-of-the-box route to view docs using ReDoc on the specified [path].
* @param pageTitle Webpage title you wish to be displayed on your docs * @param pageTitle Webpage title you wish to be displayed on your docs
* @param route path to docs resource * @param path path to docs resource
* @param specUrl url to point ReDoc to the OpenAPI json document * @param specUrl url to point ReDoc to the OpenAPI json document
*/ */
fun Route.redoc(pageTitle: String = "Docs", path: String = "/docs", specUrl: String = "/openapi.json") { fun Route.redoc(pageTitle: String = "Docs", path: String = "/docs", specUrl: String = "/openapi.json") {

View File

@ -0,0 +1,91 @@
package io.bkbn.kompendium.core.routes
import io.ktor.server.application.call
import io.ktor.server.html.respondHtml
import io.ktor.server.routing.Route
import io.ktor.server.routing.get
import io.ktor.server.routing.route
import kotlinx.html.body
import kotlinx.html.div
import kotlinx.html.head
import kotlinx.html.id
import kotlinx.html.link
import kotlinx.html.meta
import kotlinx.html.script
import kotlinx.html.title
import kotlinx.html.unsafe
/**
* Provides an out-of-the-box route to view docs using Swagger
* @see <a href="https://swagger.io/specification/">Swagger OpenApi Specification</a>
* for the latest supported open api version.
* @param pageTitle Webpage title you wish to be displayed on your docs
* @param path path to docs resource
* @param specUrl url to point Swagger to the OpenAPI json document
* @param swaggerVersion version of swagger-ui distribution
*/
fun Route.swagger(
pageTitle: String = "Docs",
path: String = "/swagger-ui",
specUrl: String = "/openapi.json",
swaggerVersion: String? = null
) {
val swaggerVersionSuffix = if (swaggerVersion == null) "" else "@$swaggerVersion"
route(path) {
get {
call.respondHtml {
head {
title {
+pageTitle
}
meta {
charset = "utf-8"
}
meta {
name = "viewport"
content = "width=device-width, initial-scale=1"
}
link {
href = "https://unpkg.com/swagger-ui-dist$swaggerVersionSuffix/swagger-ui.css"
rel = "stylesheet"
}
}
body {
div {
id = "swagger-ui"
}
script {
src = "https://unpkg.com/swagger-ui-dist$swaggerVersionSuffix/swagger-ui-standalone-preset.js"
}
script {
src = "https://unpkg.com/swagger-ui-dist$swaggerVersionSuffix/swagger-ui-bundle.js"
}
unsafe {
+"""
<script>
window.onload = function () {
// Build a system
const ui = SwaggerUIBundle({
url: "$specUrl",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout",
})
window.ui = ui
}
</script>
""".trimIndent()
}
}
}
}
}
}

View File

@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.SerializationFeature
import io.bkbn.kompendium.core.fixtures.TestSpecs.defaultSpec import io.bkbn.kompendium.core.fixtures.TestSpecs.defaultSpec
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.KotlinXSchemaConfigurator import io.bkbn.kompendium.json.schema.KotlinXSchemaConfigurator
import io.bkbn.kompendium.json.schema.definition.JsonSchema import io.bkbn.kompendium.json.schema.definition.JsonSchema
import io.bkbn.kompendium.oas.OpenApiSpec import io.bkbn.kompendium.oas.OpenApiSpec
@ -130,6 +131,7 @@ object TestHelpers {
} }
application(applicationSetup) application(applicationSetup)
routing { routing {
swagger()
redoc() redoc()
routeUnderTest() routeUnderTest()
} }

View File

@ -4,6 +4,7 @@ import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.component.Components import io.bkbn.kompendium.oas.component.Components
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
@ -68,6 +69,7 @@ private fun Application.mainModule() {
) )
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
authenticate("basic") { authenticate("basic") {
route("/{id}") { route("/{id}") {

View File

@ -4,6 +4,7 @@ import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.KotlinXSchemaConfigurator import io.bkbn.kompendium.json.schema.KotlinXSchemaConfigurator
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
@ -49,6 +50,7 @@ private fun Application.mainModule() {
schemaConfigurator = KotlinXSchemaConfigurator() schemaConfigurator = KotlinXSchemaConfigurator()
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
route("/{id}") { route("/{id}") {
idDocumentation() idDocumentation()

View File

@ -4,6 +4,7 @@ import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule
@ -51,6 +52,7 @@ private fun Application.mainModule() {
) )
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
route("/{id}") { route("/{id}") {

View File

@ -5,6 +5,7 @@ import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.enrichment.TypeEnrichment import io.bkbn.kompendium.enrichment.TypeEnrichment
import io.bkbn.kompendium.json.schema.KotlinXSchemaConfigurator import io.bkbn.kompendium.json.schema.KotlinXSchemaConfigurator
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
@ -50,6 +51,7 @@ private fun Application.mainModule() {
schemaConfigurator = KotlinXSchemaConfigurator() schemaConfigurator = KotlinXSchemaConfigurator()
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
enrichedDocumentation() enrichedDocumentation()
post { post {

View File

@ -4,6 +4,7 @@ import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule
@ -50,6 +51,7 @@ private fun Application.mainModule() {
} }
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
route("/{id}") { route("/{id}") {

View File

@ -6,6 +6,7 @@ import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.SchemaConfigurator import io.bkbn.kompendium.json.schema.SchemaConfigurator
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
@ -48,6 +49,7 @@ private fun Application.mainModule() {
schemaConfigurator = GsonSchemaConfigurator() schemaConfigurator = GsonSchemaConfigurator()
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
route("/{id}") { route("/{id}") {

View File

@ -5,6 +5,7 @@ import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.component.Components import io.bkbn.kompendium.oas.component.Components
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
@ -80,6 +81,7 @@ private fun Application.mainModule() {
} }
routing { routing {
authenticate("basic") { authenticate("basic") {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
route("/{id}") { route("/{id}") {
locationDocumentation() locationDocumentation()

View File

@ -8,6 +8,7 @@ import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.SchemaConfigurator import io.bkbn.kompendium.json.schema.SchemaConfigurator
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
@ -51,6 +52,7 @@ private fun Application.mainModule() {
schemaConfigurator = JacksonSchemaConfigurator() schemaConfigurator = JacksonSchemaConfigurator()
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
route("/{id}") { route("/{id}") {

View File

@ -3,6 +3,7 @@ package io.bkbn.kompendium.playground
import io.bkbn.kompendium.core.metadata.GetInfo import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.locations.NotarizedLocations import io.bkbn.kompendium.locations.NotarizedLocations
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
@ -72,6 +73,7 @@ private fun Application.mainModule() {
) )
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
get<Listing> { listing -> get<Listing> { listing ->
call.respondText("Listing ${listing.name}, page ${listing.page}") call.respondText("Listing ${listing.name}, page ${listing.page}")

View File

@ -3,6 +3,7 @@ package io.bkbn.kompendium.playground
import io.bkbn.kompendium.core.metadata.GetInfo import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.core.routes.swagger
import io.bkbn.kompendium.json.schema.definition.TypeDefinition import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.payload.Parameter import io.bkbn.kompendium.oas.payload.Parameter
import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule
@ -73,6 +74,7 @@ private fun Application.mainModule() {
) )
} }
routing { routing {
swagger(pageTitle = "Simple API Docs")
redoc(pageTitle = "Simple API Docs") redoc(pageTitle = "Simple API Docs")
get<ListingResource> { listing -> get<ListingResource> { listing ->
call.respondText("Listing ${listing.name}, page ${listing.page}") call.respondText("Listing ${listing.name}, page ${listing.page}")