https://kotlinlang.org logo
#ktor
Title
# ktor
j

jozefdransfield

01/06/2021, 11:09 AM
I have an issue where a request is generating an exception io.ktor.utils.io.charsets.MalformedInputException: Input length = 1, In the request handler i am doing call.receiveParameters() which i think is where the issue is coming from. However my issue is how can i capture the raw request as this is happening in the wild and i want to capture the body in a log so i can investigate?
r

Rustam Siniukov

01/06/2021, 1:15 PM
hi, what version of Ktor do you use?
j

jozefdransfield

01/06/2021, 2:04 PM
1.5
r

Rustam Siniukov

01/06/2021, 2:39 PM
do you have the stacktrace?
j

jozefdransfield

01/06/2021, 3:57 PM
io.ktor.utils.io.charsets.MalformedInputException: Input length = 1     at io.ktor.utils.io.charsets.CharsetJVMKt.throwExceptionWrapped(CharsetJVM.kt:323)     at io.ktor.utils.io.charsets.CharsetJVMKt.decodeImplSlow(CharsetJVM.kt:289)     at io.ktor.utils.io.charsets.CharsetJVMKt.decodeExactBytes(CharsetJVM.kt:254)     at io.ktor.utils.io.core.StringsKt.readTextExactBytes(Strings.kt:297)     at io.ktor.utils.io.core.StringsKt.readTextExactBytes$default(Strings.kt:296)     at io.ktor.utils.io.core.AbstractInput.readText(AbstractInput.kt:470)     at io.ktor.utils.io.core.AbstractInput.readText$default(AbstractInput.kt:467)     at io.ktor.http.cio.CIOMultipartDataBase.partToData(CIOMultipartData.kt:77)     at io.ktor.http.cio.CIOMultipartDataBase$partToData$1.invokeSuspend(CIOMultipartData.kt)     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)     at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)     at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)     at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)     at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)     at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)     at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)     at io.ktor.server.netty.EventLoopGroupProxy$Companion$create$factory$1$1.run(NettyApplicationEngine.kt:227)     at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)     at java.base/java.lang.Thread.run(Thread.java:832)
r

Rustam Siniukov

01/06/2021, 5:08 PM
Looking at the stacktrace, most likely someone sends not valid request that can’t be transformed to the string. In that case, the only thing you can do is to receive body as
ByteArray
and try to parse it to
Parameters
manually. If it fails you can log it (and maybe create an issue in Ktor if there is an error in transformation).
j

jozefdransfield

01/07/2021, 9:20 AM
so as it stands if the call.recieveParameters() throws an error i have already consumed the channel, so i would always need to receive it as a byte array, is there a helper function for me to attempt to turn that into a parameters?
r

Rustam Siniukov

01/07/2021, 12:58 PM
You can use
DoubleReceive
feature to first try to receive
Parameters
and then
ByteArray
if it fails
x-form-urlencoded
(i believe you use this content type) is just a string of
key=value
tuples separated with
&
and url encoded. So just convert byte array to string and then url decode it. If it succeeds, please file an issue to ktor
j

jozefdransfield

01/07/2021, 1:52 PM
it seems to be throwing this now:
io.ktor.features.RequestReceiveAlreadyFailedException: Request body consumption was failed     at io.ktor.features.DoubleReceive$Feature$install$1.invokeSuspend(DoubleReceive.kt:62)     at io.ktor.features.DoubleReceive$Feature$install$1.invoke(DoubleReceive.kt)     at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:243)     at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:113)     at io.ktor.util.pipeline.SuspendFunctionGun.execute(SuspendFunctionGun.kt:133)     at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:79)     at io.ktor.request.ApplicationReceiveFunctionsKt.receive(ApplicationReceiveFunctions.kt:116)     at privasea.Privasea$$special$$inlined$with$lambda$2$3.invokeSuspend(Privasea.kt:316)     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)     at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:191)     at io.ktor.util.pipeline.SuspendFunctionGun.access$resumeRootWith(SuspendFunctionGun.kt:15)     at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:86)     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)     at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:191)     at io.ktor.util.pipeline.SuspendFunctionGun.access$resumeRootWith(SuspendFunctionGun.kt:15)     at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:86)     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)     at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)     at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)     at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)     at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)     at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)     at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)     at io.ktor.server.netty.EventLoopGroupProxy$Companion$create$factory$1$1.run(NettyApplicationEngine.kt:227)     at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)     at java.base/java.lang.Thread.run(Thread.java:832) Caused by: io.ktor.utils.io.charsets.MalformedInputException: Input length = 1     at io.ktor.utils.io.charsets.CharsetJVMKt.throwExceptionWrapped(CharsetJVM.kt:323)     at io.ktor.utils.io.charsets.CharsetJVMKt.decodeImplSlow(CharsetJVM.kt:289)     at io.ktor.utils.io.charsets.CharsetJVMKt.decodeExactBytes(CharsetJVM.kt:254)     at io.ktor.utils.io.core.StringsKt.readTextExactBytes(Strings.kt:297)     at io.ktor.utils.io.core.StringsKt.readTextExactBytes$default(Strings.kt:296)     at io.ktor.utils.io.core.AbstractInput.readText(AbstractInput.kt:470)     at io.ktor.utils.io.core.AbstractInput.readText$default(AbstractInput.kt:467)     at io.ktor.http.cio.CIOMultipartDataBase.partToData(CIOMultipartData.kt:77)     at io.ktor.http.cio.CIOMultipartDataBase$partToData$1.invokeSuspend(CIOMultipartData.kt)     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)     ... 9 more
r

Rustam Siniukov

01/07/2021, 2:05 PM
Oh, ok, sorry for misleading you. Yes, if original consumption failed,
DoubleReceive
feature will not help.
j

jozefdransfield

01/07/2021, 3:14 PM
is there an alternative to log the request?
r

Rustam Siniukov

01/07/2021, 3:30 PM
As a bit hacky workaround, you can try to first read
ByteArray
and save it locally, then try to read
Parameters
. If
Parameters
fails, you already have the saved data. Do you find it ok as temp solution to try to understand what is wrong with the request?
j

jozefdransfield

01/08/2021, 10:54 AM
excellent i can now see the request many thanks!
👍 1
140 Views