Ktor extension which generates OpenAPI document.
Maven dependency:
<dependency>
<groupId>io.github.imashtak</groupId>
<artifactId>ktordoc-openapi</artifactId>
<version>0.3.0</version>
</dependency>Gradle dependency:
implementation("io.github.imashtak:ktordoc-openapi:0.3.0")Use generateOpenAPI function to declare high level settings for OpenAPI document:
fun Application.configureOpenAPI() {
routing {
generateOpenAPI() {
info {
title("Example API")
version("1.0.0")
}
server {
url("http://127.0.0.1:8080")
}
}
}
}Then wrap endpoints with api function like this:
fun Application.configureRouting() {
routing {
api({
summary("hello world")
response("200") {
mediaType("application/json") {
schema(String::class)
}
}
}) {
get("/") {
call.respondText("\"Hello World!\"")
}
}
}
}Note: generateOpenAPI call MUST be placed after all routes definitions. Considering our example, Application module may be declared like this:
fun Application.module() {
configureRouting()
configureOpenAPI()
}So now, on app starting, the file openapi/documentation.yaml will be created with complete OpenAPI spec of defined routes. Note that routes which are not wrapped with api function will not be shown in spec.
It is easy to integrate with SwaggerUI or OpenAPI plugins:
fun Application.configureOpenAPI() {
routing {
generateOpenAPI(swaggerFile = "openapi.yaml") {}
swaggerUI(swaggerFile = "openapi.yaml")
}
}There is a simple rule - api function must wrap "leaf node" of routes "tree". In other words you have to place api in the following manner:
fun Application.configureRouting() {
routing {
route("/v1") {
api({}) {
get("/") {
call.respondText("Hello World!")
}
}
}
}
}Consider the following code:
fun Application.configureRouting() {
routing {
api({}) {
get("/some/{id}") {
call.respondText("Hello World!")
}
}
}
}Parameter id will automatically be added to OpenAPI specification as path parameter. Note that from OpenAPI point of view path parameters may be only required, but ktor can work with optional path parameters using syntax /some/{id?}. If made so, generated OpenAPI will show id parameter as required and there is nothing to do with that.
It is possible to add some docs to parameter:
fun Application.configureRouting() {
routing {
api({
parameter {
name("id")
description("description of `id` parameter")
}
}) {
get("/some/{id}") {
call.respondText("Hello World!")
}
}
}
}Other fields such as in, required and schema will be set automatically (if not set manually).
The same works for query parameters. Example uses Resources plugin:
@Resource("/some")
class Some(val label: String?)
fun Application.configureRouting() {
routing {
api({
parameter {
name("label")
description("description of `label` parameter")
}
}) {
get<Some> {
call.respondText("Hello World!")
}
}
}
}