kotlinswagger-uihttp4k

How to expose swagger UI with http4k?


I'm building a microservice with the http4k framework using their Contract APIs. I can easily expose the swagger API description JSON on eg. /swagger.json with

fun app(): HttpHandler = "/" bind contract {
    renderer = OpenApi3(ApiInfo("GoOut Locations API", "1.0"), Jackson)
    descriptionPath = "/swagger.json"
    routes += ...
}

Is there an easy way to expose the swagger UI so that 1) I can specify the path it will be available on. (eg. /swagger-ui) 2) The UI will be preconfigured to fetch the description JSON from the descriptionPath specified above.

An ideal API would look something like

fun app(): HttpHandler = "/" bind contract {
    renderer = OpenApi3(ApiInfo("GoOut Locations API", "1.0"), Jackson)
    descriptionPath = "/swagger.json"
    uiPath = "/swagger-ui"
    routes += ...
}

Solution

  • As of http4k 4.28.1.0, there is now a way to do this. See the following code taken from this documentation page:

    package guide.howto.create_a_swagger_ui
    
    import org.http4k.contract.contract
    import org.http4k.contract.meta
    import org.http4k.contract.openapi.ApiInfo
    import org.http4k.contract.openapi.v3.OpenApi3
    import org.http4k.contract.ui.swaggerUi
    import org.http4k.core.Body
    import org.http4k.core.ContentType
    import org.http4k.core.Method.GET
    import org.http4k.core.Request
    import org.http4k.core.Response
    import org.http4k.core.Status.Companion.OK
    import org.http4k.core.Uri
    import org.http4k.core.with
    import org.http4k.lens.string
    import org.http4k.routing.routes
    import org.http4k.server.SunHttp
    import org.http4k.server.asServer
    
    fun main() {
        val greetingLens = Body.string(ContentType.TEXT_PLAIN).toLens()
    
        // Define a single http route for our contract
        val helloHandler = "/v1/hello" meta {
            operationId = "v1Hello"
            summary = "Say Hello"
            returning(OK, greetingLens to "Sample Greeting")
        } bindContract GET to { _: Request ->
            Response(OK).with(greetingLens of "HI!")
        }
    
        // Define a contract, and render an OpenApi 3 spec at "/spec"
        val v1Api = contract {
            routes += helloHandler
            renderer = OpenApi3(
                ApiInfo("Hello Server - Developer UI", "99.3.4")
            )
            descriptionPath = "spec"
        }
    
        // Build a Swagger UI based on the OpenApi spec defined at "/spec"
        val ui = swaggerUi(
            Uri.of("spec"),
            title = "Hello Server",
            displayOperationId = true
        )
    
        // Combine our api, spec, and ui; then start a server
        // The Swagger UI is available on the root "/" path
        routes(v1Api, ui)
            .asServer(SunHttp(8080))
            .start()
            .block()
    }