Skip to content

Commit 97619f7

Browse files
committed
complete first draft of new basic openapi documentation
1 parent f2e4286 commit 97619f7

22 files changed

+1551
-708
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Documenting SSE Routes
2+
3+
Server-Sent Events (SSE) routes can be documented for discoverability in the OpenAPI specification. While SSE functionality works normally in Ktor, documentation is achieved by wrapping SSE routes in a documented parent route.
4+
5+
??? warning "Limited OpenAPI Support"
6+
7+
**Important:** OpenAPI has limited support for Server-Sent Events. The specification does not officially define SSE endpoints, so not all documentation features work as expected or may not render correctly in documentation UIs.
8+
9+
SSE documentation is primarily for discoverability and basic information. Advanced SSE features (event types, reconnection behavior, stream format) are not well-represented in OpenAPI.
10+
11+
12+
## Describing SSE-Routes
13+
14+
SSE routes are documented by wrapping them in a parent route with documentation:
15+
16+
```kotlin
17+
import io.ktor.server.sse.sse
18+
19+
route({
20+
description = "Server-sent events stream for real-time updates"
21+
tags = listOf("events", "sse")
22+
}) {
23+
sse("/events") {
24+
// SSE implementation
25+
send(ServerSentEvent(data = "Hello"))
26+
}
27+
}
28+
```
29+
30+
All standard route documentation options are (theoretically) available. See [Basic Route Documentation]() for complete documentation options.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Documenting Webhooks
2+
3+
Webhooks are HTTP callbacks that your API sends to external systems. While webhooks are not part of your server's request handling, they can be documented in the OpenAPI specification to help API consumers understand what data your API will send to their endpoints.
4+
5+
??? warning "Documentation Only"
6+
7+
**Important:** Webhook documentation is purely informational. It does not create callable Ktor routes and has no impact on your application's routing or request handling.
8+
9+
Webhooks appear only in the generated OpenAPI specification under the `webhooks` section. They document HTTP requests your API makes to external systems, not requests it receives.
10+
11+
## Describing Webhooks
12+
13+
Webhooks are documented using the webhook function:
14+
15+
```kotlin
16+
routing {
17+
route("webhooks") {
18+
webhook(HttpMethod.Post, "concertAlert") {
19+
description = "Notify the registered URL with details of an upcoming concert"
20+
request {
21+
body<String> {
22+
mediaTypes(ContentType.Text.Plain)
23+
required = true
24+
}
25+
}
26+
}
27+
}
28+
}
29+
```
30+
31+
Parameters:
32+
33+
- httpMethod: HTTP method for the webhook (typically HttpMethod.Post)
34+
- eventName: Unique identifier for the webhook event (e.g., "newOrder", "userCreated")
35+
36+
All standard route documentation options are available. See [Basic Route Documentation]() for complete documentation options.
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Multiple API Specifications
2+
3+
The OpenAPI plugin supports generating multiple independent specifications from a single application. This enables API versioning, separation of internal and external APIs, or organizing endpoints by product or team.
4+
5+
Each specification has a unique identifier, its own configuration, and contains only the routes assigned to it. Specifications are generated and served independently.
6+
7+
## Configuring Specifications
8+
9+
Each specification can have its own configuration that extends or overrides the base plugin configuration.
10+
11+
All configuration options available in the base plugin config are available for individual specifications:
12+
13+
```kotlin
14+
install(OpenApi) {
15+
// Base configuration for all specifications
16+
info {
17+
title = "My API"
18+
}
19+
20+
// Define specification "v1"
21+
spec("v1") {
22+
info {
23+
version = "1.0.0"
24+
}
25+
}
26+
27+
// Define specification "v2"
28+
spec("v2") {
29+
info {
30+
version = "2.0.0"
31+
}
32+
}
33+
}
34+
```
35+
36+
Each specification is identified by a unique string (e.g., "v1", "v2", "internal").
37+
38+
## Assigning Routes to Specifications
39+
40+
Routes must be assigned to specifications to appear in them. Assignment can be done explicitly in route documentation or automatically via an assigner function.
41+
42+
### Assignment at Route Documentation
43+
44+
The `specName` property assigns a route to a specific specification:
45+
46+
```kotlin
47+
get("users", {
48+
specName = "v1"
49+
description = "Get users (v1)"
50+
}) { }
51+
```
52+
53+
Routes can be easily assigned in groups by adding the `specName` at a parent route:
54+
55+
```kotlin
56+
route("v1", {
57+
specName = "v1" // All child routes assigned to v1
58+
}) {
59+
get("users") { }
60+
get("products") { }
61+
get("orders") { }
62+
}
63+
```
64+
65+
All routes within this block are automatically assigned to the "v1" specification through inheritance.
66+
67+
### Assignment via Assigner Function
68+
69+
Routes can be automatically assigned based on their properties using an assigner function:
70+
71+
```kotlin
72+
install(OpenApi) {
73+
specAssigner = { url, tags ->
74+
when (url.firstOrNull()) {
75+
"v1" -> "v1"
76+
"v2" -> "v2"
77+
"internal" -> "internal"
78+
else -> OpenApiPluginConfig.DEFAULT_SPEC_ID
79+
}
80+
}
81+
}
82+
```
83+
84+
The function receives:
85+
86+
- `url`: URL path as a list of segments (e.g., `["api", "v1", "users"]` for `/api/v1/users`)
87+
- `tags`: Tags assigned to the route
88+
89+
The function returns the specification identifier to assign the route to.
90+
91+
### Unassigned Routes
92+
93+
Routes without an assignment are assigned to the default specification with the identifier `OpenApiPluginConfig.DEFAULT_SPEC_ID`. The default specification only exists if any routes are assigned to it.
94+
95+
## Serving Multiple Specifications
96+
97+
Each specification is served independently via HTTP routes.
98+
99+
```kotlin
100+
routing {
101+
// v1 specification
102+
route("v1/api.json") {
103+
openApi("v1")
104+
}
105+
106+
// v2 specification
107+
route("v2/api.json") {
108+
openApi("v2")
109+
}
110+
111+
// Internal specification
112+
route("internal/api.json") {
113+
openApi("internal")
114+
}
115+
}
116+
```
117+
118+
More information on how to handle multiple specifications in UIs:
119+
120+
- with [Swagger UI]()
121+
- with [ReDoc]()
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Type-Safe Routing Support
2+
3+
The OpenAPI plugin supports Ktor's type-safe routing via the Resources plugin. Resource classes can be used to define routes, and the plugin can automatically extract parameter information from resource class properties.
4+
5+
## Setup
6+
7+
Type-safe routing support requires additional configuration:
8+
9+
### Installed Resources Plugin
10+
11+
The Ktor Resources plugin must be installed separately:
12+
13+
```kotlin
14+
dependencies {
15+
implementation("io.ktor:ktor-server-resources:$ktor_version")
16+
}
17+
```
18+
19+
```kotlin
20+
install(Resources)
21+
install(OpenApi)
22+
```
23+
24+
### Configure Schema Generator
25+
26+
Type-safe routing requires the kotlinx.serialization schema generator:
27+
28+
```kotlin
29+
install(OpenApi) {
30+
schemas {
31+
generator = SchemaGenerator.kotlinx()
32+
}
33+
}
34+
```
35+
36+
### Enable Auto-Documentation (Optional)
37+
38+
The `autoDocumentResourcesRoutes` option automatically extracts parameter information from resource classes:
39+
40+
```kotlin
41+
install(OpenApi) {
42+
autoDocumentResourcesRoutes = true
43+
}
44+
```
45+
46+
When enabled, the plugin automatically documents:
47+
48+
- Path parameters from resource class properties
49+
- Query parameters from resource class properties
50+
- Parameter types, nullability, and default values
51+
52+
This reduces the need for manual parameter documentation in resource routes.
53+
54+
## Documenting Resource Routes
55+
56+
### Import Documented Resource Functions
57+
58+
Use documented resource route functions from `io.github.smiley4.ktoropenapi.resources`:
59+
60+
```kotlin
61+
import io.github.smiley4.ktoropenapi.resources.get
62+
import io.github.smiley4.ktoropenapi.resources.post
63+
import io.github.smiley4.ktoropenapi.resources.put
64+
import io.github.smiley4.ktoropenapi.resources.delete
65+
```
66+
67+
### Document Resource Routes
68+
69+
The documentation block works the same as with standard routes:
70+
71+
```kotlin
72+
import io.github.smiley4.ktoropenapi.resources.get
73+
74+
@Serializable
75+
@Resource("users")
76+
class Users
77+
78+
@Serializable
79+
@Resource("{id}")
80+
class User(val parent: Users, val id: String)
81+
82+
83+
get<User>({
84+
description = "Retrieve a user by ID"
85+
tags = listOf("users")
86+
87+
response {
88+
code(HttpStatusCode.OK) {
89+
description = "User found"
90+
body<UserResponse>()
91+
}
92+
code(HttpStatusCode.NotFound) {
93+
description = "User not found"
94+
}
95+
}
96+
}) {
97+
val user = call.parameters["id"]
98+
// Handler implementation
99+
}
100+
```

docs/openapi/core_concepts/how_it_works.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ httpMethod("path", {
4848

4949
Type information from the documentation DSL is automatically converted to OpenAPI schemas. Schemas can be defined locally (
5050
inline with usage) or globally (in the plugin configuration).
51-
The plugin uses [schema-kenerator](https://github.com/SMILEY4/schema-kenerator) to generate its schemas from kotlin classes and supports
51+
The plugin uses [schema-kenerator](https://github.com/SMILEY4/schema-kenerator) to generate its schemas from kotlin classes and supports.
5252
multiple schema generation strategies:
5353

5454
- Reflection-based (default): Analyzes Kotlin types using reflection

0 commit comments

Comments
 (0)