Skip to content

Commit

Permalink
Merge pull request #59 from vansickle/preserve-generic-type-info
Browse files Browse the repository at this point in the history
Preserve generic type info when parse body
  • Loading branch information
Wicpar authored Jun 8, 2020
2 parents 729aef7 + 8c8a556 commit 6593fde
Show file tree
Hide file tree
Showing 5 changed files with 9 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 <T: Any> getParseableContentTypes(clazz: KClass<T>): List<ContentType>
suspend fun <T: Any> parseBody(clazz: KClass<T>, request: PipelineContext<Unit, ApplicationCall>): T
suspend fun <T: Any> parseBody(clazz: KType, request: PipelineContext<Unit, ApplicationCall>): T
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ object BinaryContentTypeParser: BodyParser, ResponseSerializer, OpenAPIGenModule
}

@Suppress("UNCHECKED_CAST")
override suspend fun <T : Any> parseBody(clazz: KClass<T>, request: PipelineContext<Unit, ApplicationCall>): T {
return clazz.getAcceptableConstructor().call( request.context.receiveStream())
override suspend fun <T : Any> parseBody(clazz: KType, request: PipelineContext<Unit, ApplicationCall>): T {
return (clazz.classifier as KClass<T>).getAcceptableConstructor().call( request.context.receiveStream())
}

override fun <T> getMediaType(type: KType, apiGen: OpenAPIGen, provider: ModuleProvider<*>, example: T?, usage: ContentTypeProvider.Usage): Map<ContentType, MediaTypeModel<T>>? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ object KtorContentProvider : ContentTypeProvider, BodyParser, ResponseSerializer
return contentTypes!!.toList()
}

override suspend fun <T: Any> parseBody(clazz: KClass<T>, request: PipelineContext<Unit, ApplicationCall>): T {
override suspend fun <T: Any> parseBody(clazz: KType, request: PipelineContext<Unit, ApplicationCall>): T {
return request.call.receive(clazz)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ object MultipartFormDataContentProvider : BodyParser, OpenAPIGenModuleExtension
private val typeContentTypes = HashMap<KType, Map<String, MediaTypeEncodingModel>>()


override suspend fun <T : Any> parseBody(clazz: KClass<T>, request: PipelineContext<Unit, ApplicationCall>): T {
override suspend fun <T : Any> parseBody(clazz: KType, request: PipelineContext<Unit, ApplicationCall>): T {
val objectMap = HashMap<String, Any>()
request.context.receiveMultipart().forEachPart {
val name = it.name
Expand All @@ -86,7 +86,7 @@ object MultipartFormDataContentProvider : BodyParser, OpenAPIGenModuleExtension
}
}
}
val ctor = clazz.primaryConstructor!!
val ctor = (clazz.classifier as KClass<T>).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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T : OpenAPIRoute<T>>(val ktorRoute: Route, val provider: CachingModuleProvider) {
private val log = classLogger()
Expand Down Expand Up @@ -58,7 +59,7 @@ abstract class OpenAPIRoute<T : OpenAPIRoute<T>>(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<B>(), 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))
}
Expand Down

0 comments on commit 6593fde

Please sign in to comment.