-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use KotlinPoet %T for call.receive (#288)
Fixes an issue where invalid code generated when request body is an list of models.
- Loading branch information
1 parent
259d4de
commit 6b73349
Showing
4 changed files
with
168 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
openapi: 3.0.1 | ||
info: | ||
title: Library Catalog API | ||
description: An API to manage books in the library catalog. | ||
version: 1.0.0 | ||
paths: | ||
/books/batch: | ||
post: | ||
summary: Add a batch of books to the catalog | ||
description: Submit a batch of books to be added to the library catalog. | ||
operationId: addBooksBatch | ||
requestBody: | ||
description: A list of books to be added to the catalog. | ||
required: true | ||
content: | ||
application/json: | ||
schema: | ||
type: array | ||
items: | ||
$ref: '#/components/schemas/Book' | ||
responses: | ||
'201': | ||
description: Books successfully added to the catalog | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/BooksResponse' | ||
components: | ||
schemas: | ||
Book: | ||
type: object | ||
properties: | ||
title: | ||
type: string | ||
description: The title of the book. | ||
example: "The Great Gatsby" | ||
author: | ||
type: string | ||
description: The author of the book. | ||
example: "F. Scott Fitzgerald" | ||
isbn: | ||
type: string | ||
description: The ISBN number of the book. | ||
example: "978-0743273565" | ||
required: | ||
- title | ||
- author | ||
- isbn | ||
BooksResponse: | ||
type: object | ||
properties: | ||
message: | ||
type: string | ||
example: "Books added successfully!" | ||
bookIds: | ||
type: array | ||
items: | ||
type: string | ||
example: ["book_123456", "book_789012"] |
106 changes: 106 additions & 0 deletions
106
src/test/resources/examples/requestBodyAsArray/controllers/ktor/Controllers.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package examples.requestBodyAsArray.controllers | ||
|
||
import examples.requestBodyAsArray.models.Book | ||
import examples.requestBodyAsArray.models.BooksResponse | ||
import io.ktor.http.Headers | ||
import io.ktor.http.HttpStatusCode | ||
import io.ktor.http.Parameters | ||
import io.ktor.server.application.ApplicationCall | ||
import io.ktor.server.application.call | ||
import io.ktor.server.plugins.BadRequestException | ||
import io.ktor.server.plugins.ParameterConversionException | ||
import io.ktor.server.request.receive | ||
import io.ktor.server.response.respond | ||
import io.ktor.server.routing.Route | ||
import io.ktor.server.routing.post | ||
import io.ktor.util.converters.DefaultConversionService | ||
import io.ktor.util.reflect.typeInfo | ||
import kotlin.Any | ||
import kotlin.String | ||
import kotlin.Suppress | ||
import kotlin.collections.List | ||
|
||
public interface BooksBatchController { | ||
/** | ||
* Add a batch of books to the catalog | ||
* Submit a batch of books to be added to the library catalog. | ||
* | ||
* Route is expected to respond with [examples.requestBodyAsArray.models.BooksResponse]. | ||
* Use [examples.requestBodyAsArray.controllers.TypedApplicationCall.respondTyped] to send the | ||
* response. | ||
* | ||
* @param requestBody A list of books to be added to the catalog. | ||
* @param call Decorated ApplicationCall with additional typed respond methods | ||
*/ | ||
public suspend fun addBooksBatch( | ||
requestBody: List<Book>, | ||
call: TypedApplicationCall<BooksResponse>, | ||
) | ||
|
||
public companion object { | ||
/** | ||
* Mounts all routes for the BooksBatch resource | ||
* | ||
* - POST /books/batch Add a batch of books to the catalog | ||
*/ | ||
public fun Route.booksBatchRoutes(controller: BooksBatchController) { | ||
post("/books/batch") { | ||
val requestBody = call.receive<List<Book>>() | ||
controller.addBooksBatch(requestBody, TypedApplicationCall(call)) | ||
} | ||
} | ||
|
||
/** | ||
* Gets parameter value associated with this name or null if the name is not present. | ||
* Converting to type R using DefaultConversionService. | ||
* | ||
* Throws: | ||
* ParameterConversionException - when conversion from String to R fails | ||
*/ | ||
private inline fun <reified R : Any> Parameters.getTyped(name: String): R? { | ||
val values = getAll(name) ?: return null | ||
val typeInfo = typeInfo<R>() | ||
return try { | ||
@Suppress("UNCHECKED_CAST") | ||
DefaultConversionService.fromValues(values, typeInfo) as R | ||
} catch (cause: Exception) { | ||
throw ParameterConversionException( | ||
name, | ||
typeInfo.type.simpleName | ||
?: typeInfo.type.toString(), | ||
cause, | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Gets first value from the list of values associated with a name. | ||
* | ||
* Throws: | ||
* BadRequestException - when the name is not present | ||
*/ | ||
private fun Headers.getOrFail(name: String): String = this[name] ?: throw | ||
BadRequestException("Header " + name + " is required") | ||
} | ||
} | ||
|
||
/** | ||
* Decorator for Ktor's ApplicationCall that provides type safe variants of the [respond] functions. | ||
* | ||
* It can be used as a drop-in replacement for [io.ktor.server.application.ApplicationCall]. | ||
* | ||
* @param R The type of the response body | ||
*/ | ||
public class TypedApplicationCall<R : Any>( | ||
private val applicationCall: ApplicationCall, | ||
) : ApplicationCall by applicationCall { | ||
@Suppress("unused") | ||
public suspend inline fun <reified T : R> respondTyped(message: T) { | ||
respond(message) | ||
} | ||
|
||
@Suppress("unused") | ||
public suspend inline fun <reified T : R> respondTyped(status: HttpStatusCode, message: T) { | ||
respond(status, message) | ||
} | ||
} |