Foso / Ktorfit

HTTP client generator / KSP plugin for Kotlin Multiplatform (Android, iOS, Js, Jvm, Native, WasmJs)) using KSP and Ktor clients inspired by Retrofit https://foso.github.io/Ktorfit
https://foso.github.io/Ktorfit
Apache License 2.0
1.61k stars 43 forks source link

Getting error when using @FormUrlEncoded #11

Closed Tlaster closed 2 years ago

Tlaster commented 2 years ago

Describe the bug When using @FormUrlEncoded, ktor will throw an error io.ktor.http.UnsafeHeaderException: Header(s) [Content-Type] are controlled by the engine and cannot be set explicitly, I think it's a limitation from ktor since there's already an issue about it. But I haven't got a solution yet.

To Reproduce Steps to reproduce the behavior: Make an api interface with @FormUrlEncoded

Expected behavior We can make @FormUrlEncoded request

Software used

Android Studio Electric Eel | 2022.1.1 Canary 2
Build #AI-213.7172.25.2211.8571212, built on May 11, 2022
Runtime version: 11.0.13+0-b1751.21-8125866 amd64
Manjaro
Foso commented 2 years ago

Hi @Tlaster , which Ktor version are you using?

Tlaster commented 2 years ago

I'm using Version 2.0.1. And I also notice that when trying the workload in the repo, I can reproduce the error by adding @Headers(value = ["Content-Type: application/json"]) to JsonPlaceHolderApi.getPosts(). (I run it by ./gradlew :workload:runDebugExecutableLinuxX64)

gazanfarov commented 2 years ago

Just got the same error when using @FormUrlEncoded annotation

2022-06-01 11:44:14.088 3743-3815/ua.blink E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-6
    Process: ua.blink, PID: 3743
    io.ktor.http.UnsafeHeaderException: Header(s) [Content-Type] are controlled by the engine and cannot be set explicitly
        at io.ktor.client.engine.HttpClientEngineKt.validateHeaders(HttpClientEngine.kt:158)
        at io.ktor.client.engine.HttpClientEngineKt.access$validateHeaders(HttpClientEngine.kt:1)
        at io.ktor.client.engine.HttpClientEngine$install$1.invokeSuspend(HttpClientEngine.kt:65)
        at io.ktor.client.engine.HttpClientEngine$install$1.invoke(HttpClientEngine.kt)
        at io.ktor.client.engine.HttpClientEngine$install$1.invoke(HttpClientEngine.kt)
        at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
        at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
        at io.ktor.util.pipeline.SuspendFunctionGun.proceedWith(SuspendFunctionGun.kt:91)
        at io.ktor.client.plugins.logging.Logging$setupRequestLogging$1.invokeSuspend(Logging.kt:74)
        at io.ktor.client.plugins.logging.Logging$setupRequestLogging$1.invoke(Logging.kt)
        at io.ktor.client.plugins.logging.Logging$setupRequestLogging$1.invoke(Logging.kt)
        at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
        at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
        at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:101)
        at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
        at io.ktor.client.plugins.HttpSend$DefaultSender.execute(HttpSend.kt:135)
        at io.ktor.client.plugins.auth.Auth$Plugin$install$2.invokeSuspend(Auth.kt:44)
        at io.ktor.client.plugins.auth.Auth$Plugin$install$2.invoke(Auth.kt)
        at io.ktor.client.plugins.auth.Auth$Plugin$install$2.invoke(Auth.kt)
        at io.ktor.client.plugins.HttpSend$InterceptedSender.execute(HttpSend.kt:113)
        at io.ktor.client.plugins.HttpRedirect$Plugin$install$1.invokeSuspend(HttpRedirect.kt:61)
        at io.ktor.client.plugins.HttpRedirect$Plugin$install$1.invoke(HttpRedirect.kt)
        at io.ktor.client.plugins.HttpRedirect$Plugin$install$1.invoke(HttpRedirect.kt)
        at io.ktor.client.plugins.HttpSend$InterceptedSender.execute(HttpSend.kt:113)
        at io.ktor.client.plugins.HttpCallValidator$Companion$install$3.invokeSuspend(HttpCallValidator.kt:149)
        at io.ktor.client.plugins.HttpCallValidator$Companion$install$3.invoke(HttpCallValidator.kt)
        at io.ktor.client.plugins.HttpCallValidator$Companion$install$3.invoke(HttpCallValidator.kt)
        at io.ktor.client.plugins.HttpSend$InterceptedSender.execute(HttpSend.kt:113)
        at io.ktor.client.plugins.HttpSend$Plugin$install$1.invokeSuspend(HttpSend.kt:101)
        at io.ktor.client.plugins.HttpSend$Plugin$install$1.invoke(HttpSend.kt)
        at io.ktor.client.plugins.HttpSend$Plugin$install$1.invoke(HttpSend.kt)
        at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
        at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
        at io.ktor.util.pipeline.SuspendFunctionGun.proceedWith(SuspendFunctionGun.kt:91)
        at io.ktor.client.plugins.HttpCallValidator$Companion$install$1.invokeSuspend(HttpCallValidator.kt:125)
        at io.ktor.client.plugins.HttpCallValidator$Companion$install$1.invoke(HttpCallValidator.kt)
        at io.ktor.client.plugins.HttpCallValidator$Companion$install$1.invoke(HttpCallValidator.kt)
        at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
        at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
        at io.ktor.client.plugins.HttpRequestLifecycle$Plugin$install$1.invokeSuspend(HttpRequestLifecycle.kt:35)
        at io.ktor.client.plugins.HttpRequestLifecycle$Plugin$install$1.invoke(HttpRequestLifecycle.kt)
        at io.ktor.client.plugins.HttpRequestLifecycle$Plugin$install$1.invoke(HttpRequestLifecycle.kt)
        at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
        at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
        at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:101)
        at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
gazanfarov commented 2 years ago

@Tlaster have you been able to overcome this issue yet?

Tlaster commented 2 years ago

@Tlaster have you been able to overcome this issue yet?

No, our team end up creating a new one that just generates ktor call without any runtime: https://github.com/qdsfdhvh/ktor-fit

Foso commented 2 years ago

Hi @Tlaster , @gazanfarov i released a new version ( v1.0.0-beta07). I removed the Content-Type Header, so the error is not fix for now. I still dont understand why Ktor doesnt allow this header

gazanfarov commented 2 years ago

@Foso just noticed new commit and here you are. God speed! 🤓 Going to check it today, thank you!

Update: everything works now.