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 += ...
}
After a bit of searching I achieved this with combination of Web Jars and http4k's static routing.
The potential viewer of the docs must simply visit /docs
path where he gets redirected to /docs/index.html?url=<path to Api description>
where
index.html
is a static Swagger UI entrypoint served from a web jar.url
query param tells the swagger UI where to fetch the OpenApi description from.From the DX perspective we have a simple http4k application:
// path the OpenApi description will be exposed on
private const val API_DESCRIPTION_PATH = "/swagger.json"
fun app(): HttpHandler {
val api = contract {
renderer = OpenApi3(ApiInfo("Your API summary", "1.0"), Jackson)
descriptionPath = API_DESCRIPTION_PATH
// the actual API routes
routes += ...
}
return routes(
// the docs routes are not considered part of the API so we define them outside of the contract
swaggerUi(API_DESCRIPTION_PATH),
api
)
}
The swaggerUi
handler implementation follows
/**
* Exposes Swagger UI with /docs path as its entry point.
* @param descriptionPath absolute path to API description JSON. The UI will be configured to fetch it after load.
*/
fun swaggerUi(descriptionPath: String): RoutingHttpHandler = routes(
"docs" bind Method.GET to {
Response(Status.FOUND).header("Location", "/docs/index.html?url=$descriptionPath")
},
// For some reason the static handler does not work without "/" path prefix.
"/docs" bind static(Classpath("META-INF/resources/webjars/swagger-ui/3.25.2"))
)
We also have to include the swagger-ui webjar as our dependency. Here's a Gradle directive:
implementation 'org.webjars:swagger-ui:3.25.2'
See the webjars website for Maven (and more) directives.
Note that the swaggerUi
handler assumes its bound to the /
root path of the whole service. However, that can be easily fixed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With