Skip to content

Instantly share code, notes, and snippets.

@Szer
Created July 20, 2021 18:32
Show Gist options
  • Save Szer/ed82e957e7d7fe95ce103cdcd7313f5f to your computer and use it in GitHub Desktop.
Save Szer/ed82e957e7d7fe95ce103cdcd7313f5f to your computer and use it in GitHub Desktop.
custom_jackson
object CustomDeserToTheRescue :
ApplicationFeature<ApplicationCallPipeline, Unit, CustomDeserToTheRescue> {
override val key: AttributeKey<CustomDeserToTheRescue> = AttributeKey("CustomDeserToTheRescue")
override fun install(
pipeline: ApplicationCallPipeline,
configure: Unit.() -> Unit
): CustomDeserToTheRescue {
pipeline.receivePipeline.intercept(ApplicationReceivePipeline.Transform) { receive ->
// skip if already transformed
if (subject.value !is ByteReadChannel) return@intercept
// skip if a byte channel has been requested so there is nothing to negotiate
if (subject.typeInfo.jvmErasure == ByteReadChannel::class) return@intercept
val requestContentType = try {
call.request.contentType().withoutParameters()
} catch (parseFailure: BadContentTypeFormatException) {
throw BadRequestException(
"Illegal Content-Type header format: ${call.request.headers[HttpHeaders.ContentType]}",
parseFailure
)
}
val type = receive.typeInfo
val value = receive.value as? ByteReadChannel ?: throw UnsupportedMediaTypeException(requestContentType)
val converted = withContext(Dispatchers.IO) {
val reader = value.toInputStream().reader(call.request.contentCharset() ?: Charsets.UTF_8)
Jackson.mapper.readValue(reader, type.jvmErasure.javaObjectType)
}
proceedWith(ApplicationReceiveRequest(receive.typeInfo, converted, reusableValue = true))
}
return this
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment