### Basic Route Documentation Example Source: https://smiley4.github.io/ktor-openapi-tools/latest/openapi/documenting_routes/basic_route_documentation This example shows how to document a GET request for retrieving all users, including query parameters and response body type. ```APIDOC ## GET users ### Description Retrieves all users ### Method GET ### Endpoint /users #### Query Parameters - **search** (String) - Optional - Search term for filtering users ### Response #### Success Response (200) - **body** (List) - A list of user objects ``` -------------------------------- ### Define Global Examples in Ktor OpenAPI Source: https://smiley4.github.io/ktor-openapi-tools/latest/openapi/working_with_examples/global_examples Configure global examples within the `examples` block during `OpenApi` plugin installation. Each example needs a unique identifier for referencing. ```kotlin install(OpenApi) { examples { example("success-user") { value = User( id = "user-123", name = "John Doe", email = "john@example.com", role = "user" ) summary = "Regular user" description = "Example of a standard user account" } example("admin-user") { value = User( id = "admin-1", name = "Admin User", email = "admin@example.com", role = "admin" ) summary = "Administrative user" description = "Example of an admin user with elevated privileges" } example("error-not-found") { value = ErrorResponse( code = "NOT_FOUND", message = "The requested resource was not found" ) summary = "Not found error" } } } ``` -------------------------------- ### Setup Ktor Application with OpenAPI Plugin Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/openapi-examples Sets up the Ktor application with the OpenAPI plugin, including configuration for shared examples and a custom encoder. This is the main entry point for the examples. ```kotlin package io.github.smiley4.ktoropenapi.examples import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.config.descriptors.KTypeDescriptor import io.github.smiley4.ktoropenapi.get import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktorswaggerui.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respondText import io.ktor.server.routing.route import io.ktor.server.routing.routing import kotlin.reflect.typeOf fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install and customize the OpenApi plugin install(OpenApi) { examples { // specify two shared examples example("Shared A") { description = "first shared example" value = MyExampleClass( someValue = "shared a" ) } example("Shared B") { description = "second shared example" value = MyExampleClass( someValue = "shared b" ) } // encoder used in "custom-encoder" example encoder { type, example -> // encode just the wrapped value for CustomEncoderData class if (type is KTypeDescriptor && type.type == typeOf()) (example as CustomEncoderData).number // return the example unmodified to fall back to default encoder else example } } } routing { // add the routes for the OpenAPI spec, Swagger UI and ReDoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") } get("basic", { request { body { // specify two example values example("Example 1") { description = "A first example value" value = MyExampleClass( someValue = "example 1" ) } example("Example 2") { description = "A second example value" value = MyExampleClass( someValue = "example 2" ) } } } }) { call.respondText("...") } get("reference-shared", { request { body { // reference two shared examples specified in the plugin config (and placed in the component section) exampleRef("Example 1", "Shared A") exampleRef("Example 2", "Shared B") } } }) { call.respondText("...") } get("custom-encoder", { request { body { // The type is CustomEncoderData, but it's actually encoded as a plain number // See configuration for encoder example("Example 1") { value = CustomEncoderData(123) } } } }) { call.respondText("...") } } } private data class MyExampleClass( val someValue: String ) private data class CustomEncoderData( val number: Int ) ``` -------------------------------- ### Install and Configure OpenAPI Plugin Source: https://smiley4.github.io/ktor-openapi-tools/latest/openapi?q= Install the OpenAPI plugin and configure basic API information like title and version. This setup is essential before defining routes. ```kotlin install(OpenApi) { info { title = "My API" version = "1.0.0" } } routing { get("users/{id}", { ... }) } ``` -------------------------------- ### Ktor Application Setup with OpenAPI Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/petstore?q= Sets up a Ktor server with the OpenAPI plugin, defining API information, examples, and routing for Swagger UI and ReDoc. ```kotlin package io.github.smiley4.ktoropenapi.examples import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.delete import io.github.smiley4.ktoropenapi.get import io.github.smiley4.ktoropenapi.post import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktorredoc.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.ktor.http.HttpStatusCode import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respond import io.ktor.server.routing.route import io.ktor.server.routing.routing fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } /** * Uses the OpenAPI example "petstore simple" to demonstrate ktor with swagger-ui * https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v2.0/json/petstore-simple.json */ private fun Application.myModule() { data class Pet( val id: Long, val name: String, val tag: String ) data class NewPet( val name: String, val tag: String ) data class ErrorModel( val message: String ) install(OpenApi) { info { title = "Swagger Petstore" version = "1.0.0" description = "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification" termsOfService = "http://swagger.io/terms/" contact { name = "Swagger API Team" } license { name = "MIT" } } examples { example("Unexpected Error") { value = ErrorModel("Unexpected Error") } } } routing { // add the routes for OpenAPI spec, Swagger UI and ReDoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") { hideLoading = true } } route("/pets") { get({ operationId = "findPets" description = "Returns all pets from the system that the user has access to" request { queryParameter>("tags") { description = "tags to filter by" required = false example("dog") { value = "default" } } queryParameter("limit") { description = "maximum number of results to return" required = false example("default") { value = 100 } } } response { code(HttpStatusCode.OK) { body> { description = "the list of available pets" example("Pet List") { value = listOf( Pet( id = 123, name = "Big Bird", tag = "bird" ), Pet( id = 456, name = "Charlie", tag = "dog" ) ) } } } } }) } } } ``` -------------------------------- ### Ktor Application Setup with OpenAPI and Webhooks Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/webhooks?q= Sets up a Ktor application with OpenAPI documentation, Swagger UI, Redoc, a standard POST route for registration, and a webhook for concert alerts. This is the main entry point for the example. ```kotlin package io.github.smiley4.ktoropenapi.examples import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktoropenapi.post import io.github.smiley4.ktoropenapi.webhook import io.github.smiley4.ktorswaggerui.swaggerUI import io.ktor.http.ContentType import io.ktor.http.HttpStatusCode import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respond import io.ktor.server.routing.route import io.ktor.server.routing.routing fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install the "OpenApi"-Plugin install(OpenApi) routing { // add the routes for the api-spec, swagger-ui and redoc route("api.json") { openApi() } route("swagger") { swaggerUI("/api.json") } route("redoc") { redoc("/api.json") } // a "normal" documented route to register for notifications post("registerForAlert", { description = "Register an URL to be called when new concerts are scheduled." request { body { description = "The URL to be notified about approaching concerts." } } }) { call.respond(HttpStatusCode.NotImplemented, Unit) } // documentation of the webhook to notify webhook(HttpMethod.Post, "concertAlert") { description = "Notify the registered URL with details of an upcoming concert" request { body { mediaTypes(ContentType.Text.Plain) required = true } } } } } ``` -------------------------------- ### Setup Basic Authentication and OpenAPI Security Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/authentication Installs the Authentication plugin and configures a basic authentication scheme. It also sets up the OpenAPI plugin with a default security scheme and an unauthorized response. ```kotlin package io.github.smiley4.ktoropenapi.examples import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.config.AuthScheme import io.github.smiley4.ktoropenapi.config.AuthType import io.github.smiley4.ktoropenapi.get import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktordoc.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.auth.Authentication import io.ktor.server.auth.UserIdPrincipal import io.ktor.server.auth.authenticate import io.ktor.server.auth.basic import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respondText import io.ktor.server.routing.route import io.ktor.server.routing.routing fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install "Authentication" Plugin and setup e.g. Basic-Auth // username = "user", password = "pass" install(Authentication) { basic { realm = "Access to the API" validate { credentials -> if (credentials.name == "user" && credentials.password == "pass") { UserIdPrincipal(credentials.name) } else { null } } } } // Install and configure the OpenAPI plugin install(OpenApi) { schemas { } security { // configure a basic-auth security scheme securityScheme("MySecurityScheme") { type = AuthType.HTTP scheme = AuthScheme.BASIC } // if no other security scheme is specified for a route, the one with this name is used instead defaultSecuritySchemeNames("MySecurityScheme") // if no other response is documented for "401 Unauthorized", this information is used instead defaultUnauthorizedResponse { description = "Username or password is invalid" body() } } } routing { // add the routes for the api spec, swagger-ui and redoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") } authenticate { // route is in an "authenticate" block -> default security scheme will be used (if not specified otherwise) get("protected", { // response for "401 Unauthorized" is automatically added if configured in the plugin config and not specified otherwise }) { call.respondText("Hello World!") } get("protected2", { // response for "401 Unauthorized" is automatically added if configured in the plugin config and not specified otherwise }) { call.respondText("Hello World!") } } // route is not in an "authenticate" block but "protected" flag is set (e.g. because is it protected by an external reverse-proxy // -> specified or default security scheme is used and default "401 Unauthorized" is added if not specified otherwise get("externally-protected", { // manually specify that this route requires authentication protected = true }) { call.respondText("Hello World!") } // route is not in an "authenticate" block and "protected" flag is not set // -> security schemes will be ignored and not default "401 Unauthorized" response is added get("unprotected", { securitySchemeNames("MySecurityScheme") }) { call.respondText("Hello World!") } } } class AuthRequired(val message: String) ``` -------------------------------- ### Ktor Application Setup with OpenAPI Routes Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/customized-schema-generator Sets up a Ktor application with OpenAPI, Swagger UI, and ReDoc routes. Includes a sample documented GET endpoint. ```kotlin fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install and configure the OpenApi plugin install(OpenApi) { schemas { // replace default schema-generator with configurable pre-defined generator, or ... generator = SchemaGenerator.kotlinx { nullables = RequiredHandling.NON_REQUIRED optionals = RequiredHandling.REQUIRED title = TitleType.SIMPLE explicitNullTypes = false } // ... replace default schema-generator with completely custom generator generator = { type -> type .analyzeTypeUsingKotlinxSerialization() .generateSwaggerSchema { nullables = RequiredHandling.NON_REQUIRED optionals = RequiredHandling.REQUIRED } .withTitle(TitleType.SIMPLE) .compileReferencingRoot( explicitNullTypes = false ) } } } routing { // add the routes for the OpenAPI spec, Swagger UI and ReDoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") } // a documented route get("hello", { // information about the request response { // information about a "200 OK" response code(HttpStatusCode.OK) { // body of the response body() } } }) { call.respond(HttpStatusCode.NotImplemented, "...") } } } @Serializable private class MyResponseBody( val name: String, ) ``` -------------------------------- ### Install and Configure OpenAPI Plugin Source: https://smiley4.github.io/ktor-openapi-tools/latest/openapi Install the OpenAPI plugin and configure basic API information like title and version. This setup is essential for enabling OpenAPI generation. ```kotlin install(OpenApi) { info { title = "My API" version = "1.0.0" } } routing { get("users/{id}", { description = "Get user by ID" response { code(HttpStatusCode.OK) { body() } } }) { // Handler implementation } } ``` -------------------------------- ### Ktor Application Setup with OpenAPI Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/petstore Sets up the Ktor application with the OpenAPI plugin, defining API information, examples, and routing for Swagger UI and ReDoc. This is the main entry point for the application. ```kotlin package io.github.smiley4.ktoropenapi.examples import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.delete import io.github.smiley4.ktoropenapi.get import io.github.smiley4.ktoropenapi.post import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktredoc.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.ktor.http.HttpStatusCode import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respond import io.ktor.server.routing.route import io.ktor.server.routing.routing fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } /** * Uses the OpenAPI example "petstore simple" to demonstrate ktor with swagger-ui * https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v2.0/json/petstore-simple.json */ private fun Application.myModule() { data class Pet( val id: Long, val name: String, val tag: String ) data class NewPet( val name: String, val tag: String ) data class ErrorModel( val message: String ) install(OpenApi) { info { title = "Swagger Petstore" version = "1.0.0" description = "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification" termsOfService = "http://swagger.io/terms/" contact { name = "Swagger API Team" } license { name = "MIT" } } examples { example("Unexpected Error") { value = ErrorModel("Unexpected Error") } } } routing { // add the routes for OpenAPI spec, Swagger UI and ReDoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") { hideLoading = true } } route("/pets") { get({ operationId = "findPets" description = "Returns all pets from the system that the user has access to" request { queryParameter>("tags") { description = "tags to filter by" required = false example("dog") { value = "default" } } queryParameter("limit") { description = "maximum number of results to return" required = false example("default") { value = 100 } } } response { code(HttpStatusCode.OK) { body { description = "the list of available pets" example("Pet List") { value = listOf( Pet( id = 123, name = "Big Bird", tag = "bird" ), Pet( id = 456, name = "Charlie", tag = "dog" ) ) } } ``` -------------------------------- ### Basic Ktor Application Setup with OpenAPI Plugin Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/basics Sets up a basic Ktor application, installs the OpenAPI plugin, and configures essential API information like title, description, external docs, and servers. It also defines routes for the OpenAPI JSON spec, Swagger UI, and Redoc. ```kotlin package io.github.smiley4.ktoropenapi.examples import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.config.ExampleEncoder import io.github.smiley4.ktoropenapi.config.OutputFormat import io.github.smiley4.ktoropenapi.config.SchemaGenerator import io.github.smiley4.ktoropenapi.config.descriptors.anyOf import io.github.smiley4.ktoropenapi.config.descriptors.array import io.github.smiley4.ktoropenapi.config.descriptors.ref import io.github.smiley4.ktoropenapi.config.descriptors.type import io.github.smiley4.ktoropenapi.get import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktorswaggerui.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.github.smiley4.schemakenerator.reflection.analyzer.TypeCategoryAnalyzer.Companion.DEFAULT_PRIMITIVE_TYPES import io.github.smiley4.schemakenerator.reflection.data.EnumConstType import io.github.smiley4.schemakenerator.swagger.data.TitleType import io.ktor.http.HttpStatusCode import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respondText import io.ktor.server.routing.route import io.ktor.server.routing.routing import io.swagger.v3.oas.models.examples.Example import io.swagger.v3.oas.models.media.Schema import kotlinx.serialization.json.JsonNamingStrategy import kotlin.reflect.typeOf fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install and configure the "OpenApi" Plugin install(OpenApi) { outputFormat = OutputFormat.JSON // configure basic information about the api info { title = "Example API" description = "An example api to showcase basic swagger-ui functionality." } // provide a reference to an external documentation externalDocs { url = "https://github.com/SMILEY4/ktor-swagger-ui/wiki" description = "Sample external documentation" } // configure the servers from where the api is being served server { url = "http://localhost:8080" description = "Development Server" } server { url = "https://www.example.com" description = "Production Server" } examples { encoder(ExampleEncoder.jackson()) } } routing { // Create a route for the openapi spec file. // This route will not be included in the spec. route("api.json") { openApi() } // Create a route for the Swagger UI using the openapi spec at "/api.json". // This route will not be included in the spec. route("swagger") { swaggerUI("/api.json") } // Create a route for redoc using the OpenAPI spec at "/api.json". // This route will not be included in the spec. route("redoc") { redoc("/api.json") } // a documented route get("hello", { // description of the route description = "A Hello-World route" // information about the request request { // information about the query parameter "name" of type "string" queryParameter("name") { description = "the name to greet" } body() { exampleRef("Standard User", "standard-user") } } // information about possible responses response { // information about a "200 OK" response code(HttpStatusCode.OK) { // a description of the response description = "successful request - always returns 'Hello World!'" } } }) { call.respondText("Hello ${call.request.queryParameters["name"]}") } } } ``` -------------------------------- ### Setting up Ktor Application with OpenAPI Routes Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/customized-schema-generator?q= Basic setup for a Ktor application, including installing the OpenApi plugin and defining routes for OpenAPI specification, Swagger UI, and ReDoc. This serves as the entry point for the application and its API documentation. ```kotlin fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install and configure the OpenApi plugin install(OpenApi) { schemas { // replace default schema-generator with configurable pre-defined generator, or ... generator = SchemaGenerator.kotlinx { nullables = RequiredHandling.NON_REQUIRED optionals = RequiredHandling.REQUIRED title = TitleType.SIMPLE explicitNullTypes = false } // ... replace default schema-generator with completely custom generator generator = { type -> type .analyzeTypeUsingKotlinxSerialization() .generateSwaggerSchema { nullables = RequiredHandling.NON_REQUIRED optionals = RequiredHandling.REQUIRED } .withTitle(TitleType.SIMPLE) .compileReferencingRoot( explicitNullTypes = false ) } } } routing { // add the routes for the OpenAPI spec, Swagger UI and ReDoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") } // a documented route get("hello", { // information about the request response { // information about a "200 OK" response code(HttpStatusCode.OK) { // body of the response body() } } }) { call.respond(HttpStatusCode.NotImplemented, "...") } } } @Serializable private class MyResponseBody( val name: String, ) ``` -------------------------------- ### Document a Resource Route with Parameters Source: https://smiley4.github.io/ktor-openapi-tools/latest/openapi/advanced_topics/typesafe_routing_support Document a resource route using the imported `get` function. This example demonstrates documenting path parameters, descriptions, tags, and responses for a user retrieval route. ```kotlin import io.github.smiley4.ktoropenapi.resources.get @Serializable @Resource("users") class Users @Serializable @Resource("{id}") class User(val parent: Users, val id: String) get({ description = "Retrieve a user by ID" tags = listOf("users") response { code(HttpStatusCode.OK) { description = "User found" body() } code(HttpStatusCode.NotFound) { description = "User not found" } } }) { // handler implementation } ``` -------------------------------- ### Setup Basic Authentication and OpenAPI Configuration Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/authentication?q= Installs the Authentication plugin with Basic Auth and configures the OpenAPI plugin to use a basic auth security scheme. It also sets up default security schemes and unauthorized responses. ```kotlin package io.github.smiley4.ktoropenapi.examples import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.config.AuthScheme import io.github.smiley4.ktoropenapi.config.AuthType import io.github.smiley4.ktoropenapi.get import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktorswaggerui.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.auth.Authentication import io.ktor.server.auth.UserIdPrincipal import io.ktor.server.auth.authenticate import io.ktor.server.auth.basic import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respondText import io.ktor.server.routing.route import io.ktor.server.routing.routing fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install "Authentication" Plugin and setup e.g. Basic-Auth // username = "user", password = "pass" install(Authentication) { basic { realm = "Access to the API" validate { credentials -> if (credentials.name == "user" && credentials.password == "pass") { UserIdPrincipal(credentials.name) } else { null } } } } // Install and configure the OpenAPI plugin install(OpenApi) { schemas { } security { // configure a basic-auth security scheme securityScheme("MySecurityScheme") { type = AuthType.HTTP scheme = AuthScheme.BASIC } // if no other security scheme is specified for a route, the one with this name is used instead defaultSecuritySchemeNames("MySecurityScheme") // if no other response is documented for "401 Unauthorized", this information is used instead defaultUnauthorizedResponse { description = "Username or password is invalid" body() } } } routing { // add the routes for the api spec, swagger-ui and redoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") } authenticate { // route is in an "authenticate" block -> default security scheme will be used (if not specified otherwise) get("protected", { // response for "401 Unauthorized" is automatically added if configured in the plugin config and not specified otherwise }) { call.respondText("Hello World!") } get("protected2", { // response for "401 Unauthorized" is automatically added if configured in the plugin config and not specified otherwise }) { call.respondText("Hello World!") } } // route is not in an "authenticate" block but "protected" flag is set (e.g. because is it protected by an external reverse-proxy // -> specified or default security scheme is used and default "401 Unauthorized" is added if not specified otherwise get("externally-protected", { // manually specify that this route requires authentication protected = true }) { call.respondText("Hello World!") } // route is not in an "authenticate" block and "protected" flag is not set // -> security schemes will be ignored and not default "401 Unauthorized" response is added get("unprotected", { securitySchemeNames("MySecurityScheme") }) { call.respondText("Hello World!") } } } class AuthRequired(val message: String) ``` -------------------------------- ### Configuring Request Parameter Examples Source: https://smiley4.github.io/ktor-openapi-tools/latest/dokka/ktor-openapi/ktor-openapi/io.github.smiley4.ktoropenapi.config/-request-parameter-config/example.html Demonstrates how to set example values for request parameters. This can be done by providing an `ExampleDescriptor` or a named `Example`. ```APIDOC ## Function Overloads for Example Configuration This section describes the available functions for configuring example values for request parameters. ### `example(example: ExampleDescriptor)` This overload allows you to provide an `ExampleDescriptor` directly to configure the example. ### `example(name: String, example: Example)` This overload allows you to provide a named `Example` to configure the example. ### `inline fun example(name: String, example: ValueExampleDescriptorConfig.() -> Unit)` This inline function provides a more concise way to configure examples using a lambda receiver. It allows defining examples with a specific type `T` and configuring them within the `ValueExampleDescriptorConfig` context. An example value for this parameter. ``` -------------------------------- ### Setup Ktor OpenAPI Plugin with Schema Configuration Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/schemas?q= Installs and configures the OpenApi plugin, including custom schema definitions and generation overrides. This setup is necessary before defining API routes that utilize these schemas. ```kotlin package io.github.smiley4.ktoropenapi.examples import com.fasterxml.jackson.annotation.JsonSubTypes import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.config.SchemaGenerator import io.github.smiley4.ktoropenapi.config.descriptors.anyOf import io.github.smiley4.ktoropenapi.config.descriptors.array import io.github.smiley4.ktoropenapi.config.descriptors.ref import io.github.smiley4.ktoropenapi.get import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktorswaggerui.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respondText import io.ktor.server.routing.route import io.ktor.server.routing.routing import io.swagger.v3.oas.models.media.Schema import java.time.LocalDateTime fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install and customize the OpenApi Plugin install(OpenApi) { schemas { // add a swagger schema to the component section of the api spec with the id "swagger-schema" schema("swagger-schema", Schema().also { it.type = "number" it.title = "Custom Type" }) // add a type to the component section of the api spec with the id "type-schema" schema("type-schema") // customized schema generation generator = SchemaGenerator.reflection { // overwrite default schema generation with one specific for LocalDateTime that correctly handles "type" and "format" overwrite(SchemaGenerator.TypeOverwrites.LocalDateTime()) } } } routing { // add the routes for the api spec, swagger-ui and redoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") } get("basic", { request { // directly specify the schema type body() } }) { call.respondText("...") } get("global-swagger-schema", { request { // reference and use the schema from the component section with the id "swagger-schema" body(ref("swagger-schema")) } }) { call.respondText("...") } get("global-type-schema", { request { // reference and use the schema from the component section with the id "type-schema" body(ref("type-schema")) } }) { call.respondText("...") } get("array-schema", { request { // an array of items with the referenced schema with the id "type-schema" body( array( ref("type-schema") ) ) } }) { call.respondText("...") } get("anyof-schema", { request { // either the referenced schema with id "type-schema" or "swagger-schema" body( anyOf( ref("type-schema"), ref("swagger-schema") ) ) } }) { call.respondText("...") } get("type-overwrite", { request { // schema is not generated the normal way but the overwriting schema from the config is used instead body() } }) { call.respondText("...") } get("jackson-subtypes", { request { // jackson subtypes are detected automatically body() } }) { call.respondText("...") } } } private data class MySchemaClass( ``` -------------------------------- ### Ktor Application Setup with OpenAPI Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/request-response?q= Sets up a Ktor application with ContentNegotiation using Jackson for JSON serialization and installs the OpenApi plugin. It also configures routes for Swagger UI, OpenAPI spec, and ReDoc. ```kotlin package io.github.smiley4.ktoropenapi.examples import com.fasterxml.jackson.core.util.DefaultIndenter import com.fasterxml.jackson.core.util.DefaultPrettyPrinter import com.fasterxml.jackson.databind.SerializationFeature import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.post import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktordoc.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.ktor.http.HttpStatusCode import io.ktor.serialization.jackson.jackson import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.plugins.contentnegotiation.ContentNegotiation import io.ktor.server.request.receive import io.ktor.server.response.respond import io.ktor.server.routing.route import io.ktor.server.routing.routing fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install the OpenApi plugin and use the default configuration install(OpenApi) install(ContentNegotiation) { jackson { configure(SerializationFeature.INDENT_OUTPUT, true) setDefaultPrettyPrinter(DefaultPrettyPrinter().apply { indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance) indentObjectsWith(DefaultIndenter(" ", "\n")) }) } } routing { // add the routes for OpenAPI spec, Swagger UI and ReDoc route("swagger") { swaggerUI("/api.json") } route("api.json") { openApi() } route("redoc") { redoc("/api.json") } // a documented route post("calculate", { // information about the request request { // specify the schema of the request body and some additional information body { description = "the requested operation and values to perform the operation on" required = true } } // information the possible responses response { // document the "200 OK" response code(HttpStatusCode.OK) { description = "Calculation was performed successfully." // specify the schema of the response body and some additional information body { description = "the result of an operation together with the original request" } } // document the "422 Unprocessable Entity" response code(HttpStatusCode.UnprocessableEntity) { description = "The requested calculation could not be performed, e.g. due to division by zero." } } }) { call.receive().let { calculation -> when (calculation.operation) { OperationType.ADD -> { call.respond( HttpStatusCode.OK, CalculationResult( calculation = calculation, result = calculation.a + calculation.b ) ) } OperationType.SUB -> { call.respond( HttpStatusCode.OK, CalculationResult( calculation = calculation, result = calculation.a - calculation.b ) ) } OperationType.MUL -> { call.respond( HttpStatusCode.OK, CalculationResult( calculation = calculation, result = calculation.a * calculation.b ) ) } OperationType.DIV -> { if (calculation.b == 0f) { ``` -------------------------------- ### Basic Ktor Application Setup with OpenAPI Plugin Source: https://smiley4.github.io/ktor-openapi-tools/latest/examples/basics?q= Sets up a Ktor application with the OpenAPI plugin, configuring basic API information, external documentation links, server details, and example encoding. It also defines routes for the OpenAPI JSON spec, Swagger UI, and Redoc. ```kotlin package io.github.smiley4.ktoropenapi.examples import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.config.ExampleEncoder import io.github.smiley4.ktoropenapi.config.OutputFormat import io.github.smiley4.ktoropenapi.config.SchemaGenerator import io.github.smiley4.ktoropenapi.config.descriptors.anyOf import io.github.smiley4.ktoropenapi.config.descriptors.array import io.github.smiley4.ktoropenapi.config.descriptors.ref import io.github.smiley4.ktoropenapi.config.descriptors.type import io.github.smiley4.ktoropenapi.get import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.ktordoc.redoc import io.github.smiley4.ktorswaggerui.swaggerUI import io.github.smiley4.schemakenerator.reflection.analyzer.TypeCategoryAnalyzer.Companion.DEFAULT_PRIMITIVE_TYPES import io.github.smiley4.schemakenerator.reflection.data.EnumConstType import io.github.smiley4.schemakenerator.swagger.data.TitleType import io.ktor.http.HttpStatusCode import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.response.respondText import io.ktor.server.routing.route import io.ktor.server.routing.routing import io.swagger.v3.oas.models.examples.Example import io.swagger.v3.oas.models.media.Schema import kotlinx.serialization.json.JsonNamingStrategy import kotlin.reflect.typeOf fun main() { embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true) } private fun Application.myModule() { // Install and configure the "OpenApi" Plugin install(OpenApi) { outputFormat = OutputFormat.JSON // configure basic information about the api info { title = "Example API" description = "An example api to showcase basic swagger-ui functionality." } // provide a reference to an external documentation externalDocs { url = "https://github.com/SMILEY4/ktor-swagger-ui/wiki" description = "Sample external documentation" } // configure the servers from where the api is being served server { url = "http://localhost:8080" description = "Development Server" } server { url = "https://www.example.com" description = "Production Server" } examples { encoder(ExampleEncoder.jackson()) } } routing { // Create a route for the openapi spec file. // This route will not be included in the spec. route("api.json") { openApi() } // Create a route for the Swagger UI using the openapi spec at "/api.json". // This route will not be included in the spec. route("swagger") { swaggerUI("/api.json") } // Create a route for redoc using the OpenAPI spec at "/api.json". // This route will not be included in the spec. route("redoc") { redoc("/api.json") } // a documented route get("hello", { // description of the route description = "A Hello-World route" // information about the request request { // information about the query parameter "name" of type "string" queryParameter("name") { description = "the name to greet" } body() { exampleRef("Standard User", "standard-user") } } // information about possible responses response { // information about a "200 OK" response code(HttpStatusCode.OK) { // a description of the response description = "successful request - always returns 'Hello World!'" } } }) { call.respondText("Hello ${call.request.queryParameters["name"]}") } } } ``` -------------------------------- ### Documenting Basic Route Information Source: https://smiley4.github.io/ktor-openapi-tools/latest/openapi/documenting_routes/basic_route_documentation This example demonstrates how to set operationId, summary, and description for a GET request to retrieve a user by ID. ```APIDOC ## GET users/{id} ### Description Retrieves detailed information for a specific user ### Method GET ### Endpoint /users/{id} ### Operation ID getUserById ### Summary Get user by ID ``` -------------------------------- ### Parameter Configuration Example Source: https://smiley4.github.io/ktor-openapi-tools/latest/openapi/documenting_routes/request_documentation?q= An example showing common configuration options for query parameters, including description, required status, deprecation, and examples. ```APIDOC queryParameter("search") { description = "Search query" required = false deprecated = false example("Example 1") { value = "john" } } ```