From 8c8a5562c74c7e2e467df5bf69f50a40b927e3fa Mon Sep 17 00:00:00 2001 From: Pavel Samokha Date: Mon, 8 Jun 2020 17:32:49 +0300 Subject: [PATCH] Preserve generic type info when parse body --- .../com/papsign/ktor/openapigen/content/type/BodyParser.kt | 3 ++- .../openapigen/content/type/binary/BinaryContentTypeParser.kt | 4 ++-- .../ktor/openapigen/content/type/ktor/KtorContentProvider.kt | 2 +- .../type/multipart/MultipartFormDataContentProvider.kt | 4 ++-- .../kotlin/com/papsign/ktor/openapigen/route/OpenAPIRoute.kt | 3 ++- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/papsign/ktor/openapigen/content/type/BodyParser.kt b/src/main/kotlin/com/papsign/ktor/openapigen/content/type/BodyParser.kt index 7e1b52f48..a5b307a96 100644 --- a/src/main/kotlin/com/papsign/ktor/openapigen/content/type/BodyParser.kt +++ b/src/main/kotlin/com/papsign/ktor/openapigen/content/type/BodyParser.kt @@ -4,8 +4,9 @@ import io.ktor.application.ApplicationCall import io.ktor.http.ContentType import io.ktor.util.pipeline.PipelineContext import kotlin.reflect.KClass +import kotlin.reflect.KType interface BodyParser: ContentTypeProvider { fun getParseableContentTypes(clazz: KClass): List - suspend fun parseBody(clazz: KClass, request: PipelineContext): T + suspend fun parseBody(clazz: KType, request: PipelineContext): T } \ No newline at end of file diff --git a/src/main/kotlin/com/papsign/ktor/openapigen/content/type/binary/BinaryContentTypeParser.kt b/src/main/kotlin/com/papsign/ktor/openapigen/content/type/binary/BinaryContentTypeParser.kt index 6bed8fe42..3e11e7dcb 100644 --- a/src/main/kotlin/com/papsign/ktor/openapigen/content/type/binary/BinaryContentTypeParser.kt +++ b/src/main/kotlin/com/papsign/ktor/openapigen/content/type/binary/BinaryContentTypeParser.kt @@ -50,8 +50,8 @@ object BinaryContentTypeParser: BodyParser, ResponseSerializer, OpenAPIGenModule } @Suppress("UNCHECKED_CAST") - override suspend fun parseBody(clazz: KClass, request: PipelineContext): T { - return clazz.getAcceptableConstructor().call( request.context.receiveStream()) + override suspend fun parseBody(clazz: KType, request: PipelineContext): T { + return (clazz.classifier as KClass).getAcceptableConstructor().call( request.context.receiveStream()) } override fun getMediaType(type: KType, apiGen: OpenAPIGen, provider: ModuleProvider<*>, example: T?, usage: ContentTypeProvider.Usage): Map>? { diff --git a/src/main/kotlin/com/papsign/ktor/openapigen/content/type/ktor/KtorContentProvider.kt b/src/main/kotlin/com/papsign/ktor/openapigen/content/type/ktor/KtorContentProvider.kt index 618e731af..452cffe94 100644 --- a/src/main/kotlin/com/papsign/ktor/openapigen/content/type/ktor/KtorContentProvider.kt +++ b/src/main/kotlin/com/papsign/ktor/openapigen/content/type/ktor/KtorContentProvider.kt @@ -68,7 +68,7 @@ object KtorContentProvider : ContentTypeProvider, BodyParser, ResponseSerializer return contentTypes!!.toList() } - override suspend fun parseBody(clazz: KClass, request: PipelineContext): T { + override suspend fun parseBody(clazz: KType, request: PipelineContext): T { return request.call.receive(clazz) } diff --git a/src/main/kotlin/com/papsign/ktor/openapigen/content/type/multipart/MultipartFormDataContentProvider.kt b/src/main/kotlin/com/papsign/ktor/openapigen/content/type/multipart/MultipartFormDataContentProvider.kt index 33a7a684d..94359549e 100644 --- a/src/main/kotlin/com/papsign/ktor/openapigen/content/type/multipart/MultipartFormDataContentProvider.kt +++ b/src/main/kotlin/com/papsign/ktor/openapigen/content/type/multipart/MultipartFormDataContentProvider.kt @@ -68,7 +68,7 @@ object MultipartFormDataContentProvider : BodyParser, OpenAPIGenModuleExtension private val typeContentTypes = HashMap>() - override suspend fun parseBody(clazz: KClass, request: PipelineContext): T { + override suspend fun parseBody(clazz: KType, request: PipelineContext): T { val objectMap = HashMap() request.context.receiveMultipart().forEachPart { val name = it.name @@ -86,7 +86,7 @@ object MultipartFormDataContentProvider : BodyParser, OpenAPIGenModuleExtension } } } - val ctor = clazz.primaryConstructor!! + val ctor = (clazz.classifier as KClass).primaryConstructor!! return ctor.callBy(ctor.parameters.associateWith { val raw = objectMap[it.openAPIName] if ((raw == null || (raw !is InputStream && streamTypes.contains(it.type))) && it.type.isMarkedNullable) { diff --git a/src/main/kotlin/com/papsign/ktor/openapigen/route/OpenAPIRoute.kt b/src/main/kotlin/com/papsign/ktor/openapigen/route/OpenAPIRoute.kt index 527d56d3b..c7c8f9129 100644 --- a/src/main/kotlin/com/papsign/ktor/openapigen/route/OpenAPIRoute.kt +++ b/src/main/kotlin/com/papsign/ktor/openapigen/route/OpenAPIRoute.kt @@ -23,6 +23,7 @@ import io.ktor.routing.application import io.ktor.routing.contentType import io.ktor.util.pipeline.PipelineContext import kotlin.reflect.KClass +import kotlin.reflect.typeOf abstract class OpenAPIRoute>(val ktorRoute: Route, val provider: CachingModuleProvider) { private val log = classLogger() @@ -58,7 +59,7 @@ abstract class OpenAPIRoute>(val ktorRoute: Route, val provi getContentTypesMap(B::class).forEach { (contentType, parsers) -> contentType(contentType) { handle { - val receive: B = parsers.getBodyParser(call.request.contentType()).parseBody(B::class, this) + val receive: B = parsers.getBodyParser(call.request.contentType()).parseBody(typeOf(), this) val params: P = if (Unit is P) Unit else parameterHandler.parse(call.parameters, call.request.headers) pass(this, responder, PHandler.handle(params), BHandler.handle(receive)) }