@@ -23,6 +23,8 @@ Extra Features:
2323
2424It is inspired by ktor Locations, but makes no use of it.
2525
26+ ## Examples
27+
2628Take a look at [ a few examples] ( https://github.com/papsign/Ktor-OpenAPI-Generator/wiki/A-few-examples )
2729
2830## Installation
@@ -68,363 +70,15 @@ dependencies {
6870}
6971```
7072
71- ## Examples
72-
73- Basic Example:
74-
75- ``` kotlin
76- apiRouting {
73+ ## Expose the OpenAPI.json and swager-ui
7774
78- // bare minimum, just like Ktor but strongly typed
79- get<StringParam , StringResponse > { params ->
80- respond(StringResponse (params.a))
81- }
82-
83- route(" inine" ).get<StringParam , StringResponse >(
84- info(" String Param Endpoint" , " This is a String Param Endpoint" ), // A Route module that describes an endpoint, it is optional
85- example = StringResponse (" Hi" )
86- ) { params ->
87- respond(StringResponse (params.a))
88- }
89-
90- route(" block" ) {
91- // use Unit if there are no parameters / body / response
92- post<Unit , StringUsable , StringUsable >(
93- info(" String Post Endpoint" , " This is a String Post Endpoint" ),
94- exampleRequest = StringUsable (" Ho" ),
95- exampleResponse = StringUsable (" Ho" )
96- ) { params, body ->
97- respond(body)
98- }
99- }
100- }
101-
102- // Path works like the @Location from locations, but for transparency we recommend only using it to extract the parameters
103- @Path(" string/{a}" )
104- data class StringParam (
105- @PathParam(" A simple String Param" ) val a : String ,
106- @QueryParam(" Optional String" ) val optional : String? // Nullable Types are optional
107- )
108-
109- // A response can be any class, but a description will be generated from the annotation
110- @Response(" A String Response" )
111- data class StringResponse (val str : String )
112-
113-
114- // DTOs can be requests and responses, annotations are optional
115- @Response(" A String Response" )
116- @Request(" A String Request" )
117- data class StringUsable (val str : String )
11875```
119-
120- Creates this ` openapi.json ` description:
121-
122- ``` json
123- {
124- "components" :{
125- "schemas" :{
126- "StringResponse" :{
127- "nullable" :false ,
128- "properties" :{
129- "str" :{
130- "nullable" :false ,
131- "type" :" string"
132- }
133- },
134- "required" :[
135- " str"
136- ],
137- "type" :" object"
138- },
139- "StringUsable" :{
140- "nullable" :false ,
141- "properties" :{
142- "str" :{
143- "nullable" :false ,
144- "type" :" string"
145- }
146- },
147- "required" :[
148- " str"
149- ],
150- "type" :" object"
151- }
152- }
153- },
154- "info" :{
155- "contact" :{
156- "email" :" support@test.com" ,
157- "name" :" Support"
158- },
159- "description" :" The Test API" ,
160- "title" :" Test API" ,
161- "version" :" 0.0.1"
162- },
163- "openapi" :" 3.0.0" ,
164- "paths" :{
165- "/string/{a}" :{
166- "get" :{
167- "parameters" :[
168- {
169- "deprecated" :false ,
170- "description" :" A simple String Param" ,
171- "explode" :false ,
172- "in" :" path" ,
173- "name" :" a" ,
174- "required" :true ,
175- "schema" :{
176- "nullable" :false ,
177- "type" :" string"
178- },
179- "style" :" simple"
180- },
181- {
182- "allowEmptyValue" :false ,
183- "deprecated" :false ,
184- "description" :" Optional String" ,
185- "explode" :false ,
186- "in" :" query" ,
187- "name" :" optional" ,
188- "required" :false ,
189- "schema" :{
190- "nullable" :false ,
191- "type" :" string"
192- },
193- "style" :" form"
194- }
195- ],
196- "responses" :{
197- "200" :{
198- "content" :{
199- "application/json" :{
200- "schema" :{
201- "$ref" :" #/components/schemas/StringResponse"
202- }
203- }
204- },
205- "description" :" A String Response"
206- }
207- }
208- }
209- },
210- "/inine/string/{a}" :{
211- "get" :{
212- "description" :" This is a String Param Endpoint" ,
213- "parameters" :[
214- {
215- "deprecated" :false ,
216- "description" :" A simple String Param" ,
217- "explode" :false ,
218- "in" :" path" ,
219- "name" :" a" ,
220- "required" :true ,
221- "schema" :{
222- "nullable" :false ,
223- "type" :" string"
224- },
225- "style" :" simple"
226- },
227- {
228- "allowEmptyValue" :false ,
229- "deprecated" :false ,
230- "description" :" Optional String" ,
231- "explode" :false ,
232- "in" :" query" ,
233- "name" :" optional" ,
234- "required" :false ,
235- "schema" :{
236- "nullable" :false ,
237- "type" :" string"
238- },
239- "style" :" form"
240- }
241- ],
242- "responses" :{
243- "200" :{
244- "content" :{
245- "application/json" :{
246- "example" :{
247- "str" :" Hi"
248- },
249- "schema" :{
250- "$ref" :" #/components/schemas/StringResponse"
251- }
252- }
253- },
254- "description" :" A String Response"
255- }
256- },
257- "summary" :" String Param Endpoint"
258- }
259- },
260- "/block" :{
261- "post" :{
262- "description" :" This is a String Post Endpoint" ,
263- "requestBody" :{
264- "content" :{
265- "application/json" :{
266- "example" :{
267- "str" :" Ho"
268- },
269- "schema" :{
270- "$ref" :" #/components/schemas/StringUsable"
271- }
272- }
273- },
274- "description" :" A String Request"
275- },
276- "responses" :{
277- "200" :{
278- "content" :{
279- "application/json" :{
280- "example" :{
281- "str" :" Ho"
282- },
283- "schema" :{
284- "$ref" :" #/components/schemas/StringUsable"
285- }
286- }
287- },
288- "description" :" A String Response"
289- }
290- },
291- "summary" :" String Post Endpoint"
292- }
293- }
294- },
295- "servers" :[
296- {
297- "description" :" Test server" ,
298- "url" :" http://localhost:8080/"
299- }
300- ]
301- }
302- ```
303-
304- Full Example:
305-
306- ``` kotlin
307- import com.papsign.ktor.openapigen.OpenAPIGen
308- import com.papsign.ktor.openapigen.annotations.Path
309- import com.papsign.ktor.openapigen.annotations.Request
310- import com.papsign.ktor.openapigen.annotations.Response
311- import com.papsign.ktor.openapigen.annotations.parameters.PathParam
312- import com.papsign.ktor.openapigen.annotations.parameters.QueryParam
313- import com.papsign.ktor.openapigen.openAPIGen
314- import com.papsign.ktor.openapigen.route.apiRouting
315- import com.papsign.ktor.openapigen.route.info
316- import com.papsign.ktor.openapigen.route.path.normal.get
317- import com.papsign.ktor.openapigen.route.path.normal.post
318- import com.papsign.ktor.openapigen.route.response.respond
319- import com.papsign.ktor.openapigen.route.route
320- import com.papsign.ktor.openapigen.schema.namer.DefaultSchemaNamer
321- import com.papsign.ktor.openapigen.schema.namer.SchemaNamer
322- import io.ktor.application.application
323- import io.ktor.application.call
324- import io.ktor.application.install
325- import io.ktor.features.ContentNegotiation
326- import io.ktor.jackson.jackson
327- import io.ktor.response.respond
328- import io.ktor.response.respondRedirect
329- import io.ktor.routing.get
330- import io.ktor.routing.routing
331- import io.ktor.server.engine.embeddedServer
332- import io.ktor.server.netty.Netty
333- import kotlin.reflect.KType
334-
335- object Minimal {
336-
337- @JvmStatic
338- fun main (args : Array <String >) {
339- embeddedServer(Netty , 8080 , " localhost" ) {
340- // define basic OpenAPI info
341- install(OpenAPIGen ) {
342- // basic info
343- info {
344- version = " 0.0.1"
345- title = " Test API"
346- description = " The Test API"
347- contact {
348- name = " Support"
349- email = " support@test.com"
350- }
351- }
352- // describe the server, add as many as you want
353- server(" http://localhost:8080/" ) {
354- description = " Test server"
355- }
356- // optional
357- replaceModule(DefaultSchemaNamer , object : SchemaNamer {
358- val regex = Regex (" [A-Za-z0-9_.]+" )
359- override fun get (type : KType ): String {
360- return type.toString().replace(regex) { it.value.split(" ." ).last() }.replace(Regex (" >|<|, " ), " _" )
361- }
362- })
363- }
364-
365- install(ContentNegotiation ) {
366- jackson()
367- }
368-
369- // normal Ktor routing
370- routing {
371- get(" /openapi.json" ) {
372- call.respond(application.openAPIGen.api.serialize())
373- }
374-
375- get(" /" ) {
376- call.respondRedirect(" /swagger-ui/index.html?url=/openapi.json" , true )
377- }
378- }
379-
380- // Described routing
381- apiRouting {
382-
383- // bare minimum, just like Ktor but strongly typed
384- get<StringParam , StringResponse > { params ->
385- respond(StringResponse (params.a))
386- }
387-
388- route(" inine" ).get<StringParam , StringResponse >(
389- info(" String Param Endpoint" , " This is a String Param Endpoint" ), // A Route module that describes an endpoint, it is optional
390- example = StringResponse (" Hi" )
391- ) { params ->
392- respond(StringResponse (params.a))
393- }
394-
395- route(" block" ) {
396- // use Unit if there are no parameters / body / response
397- post<Unit , StringUsable , StringUsable >(
398- info(" String Post Endpoint" , " This is a String Post Endpoint" ),
399- exampleRequest = StringUsable (" Ho" ),
400- exampleResponse = StringUsable (" Ho" )
401- ) { params, body ->
402- respond(body)
403- }
404- }
405- }
406- }.start(true )
407-
76+ application.routing {
77+ get("/openapi.json") {
78+ call.respond(application.openAPIGen.api.serialize())
79+ }
80+ get("/") {
81+ call.respondRedirect("/swagger-ui/index.html?url=/openapi.json", true)
40882 }
409-
410- // Path works like the @Location from locations, but for transparency we recommend only using it to extract the parameters
411- @Path(" string/{a}" )
412- data class StringParam (
413- @PathParam(" A simple String Param" ) val a : String ,
414- @QueryParam(" Optional String" ) val optional : String? // Nullable Types are optional
415- )
416-
417- // A response can be any class, but a description will be generated from the annotation
418- @Response(" A String Response" )
419- data class StringResponse (val str : String )
420-
421- // DTOs can be requests and responses, annotations are optional
422- @Response(" A String Response" )
423- @Request(" A String Request" )
424- data class StringUsable (val str : String )
42583}
42684```
427-
428- For an advanced example with most of the features, see the tests.
429-
430-
0 commit comments