Ktor Version and Engine Used (client or server and name)
1.3.2, ktor-client-android
Describe the bug
The redirect is not working for 302 status code if the request method was POST (I assume for every not GET method)
To Reproduce
Steps to reproduce the behavior:
private val androidClient by lazy {
HttpClient(Android.config {
connectTimeout = 60_000
socketTimeout = 40_000
}
) {
install(HttpCookies) {
storage = AcceptAllCookiesStorage()
}
}
}
androidClient.post("http://www.mocky.io/v2/5e95a5f12f00005b410252ca")
Expected behavior
Should get a response:
{
"text": "Hello world"
}
Actual result
io.ktor.client.features.RedirectResponseException: Unhandled redirect:
W/System.err: io.ktor.client.features.RedirectResponseException: Unhandled redirect: http://www.mocky.io/v2/5e95a5f12f00005b410252ca. Status: 302 Found
2020-04-14 17:51:32.736 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.client.features.DefaultResponseValidationKt$addDefaultResponseValidation$1$1.invokeSuspend(DefaultResponseValidation.kt:34)
2020-04-14 17:51:32.736 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.client.features.DefaultResponseValidationKt$addDefaultResponseValidation$1$1.invoke(Unknown Source:10)
2020-04-14 17:51:32.736 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.client.features.HttpCallValidator.validateResponse(HttpCallValidator.kt:37)
2020-04-14 17:51:32.736 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.client.features.HttpCallValidator$Companion$install$2.invokeSuspend(HttpCallValidator.kt:99)
2020-04-14 17:51:32.737 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.client.features.HttpCallValidator$Companion$install$2.invoke(Unknown Source:14)
2020-04-14 17:51:32.737 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:318)
2020-04-14 17:51:32.737 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.proceed(PipelineContext.kt:163)
2020-04-14 17:51:32.737 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.execute(PipelineContext.kt:183)
2020-04-14 17:51:32.738 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:27)
2020-04-14 17:51:32.738 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.client.call.HttpClientCall.receive(HttpClientCall.kt:75)
2020-04-14 17:51:32.738 8777-8777/com.testapp.android.ktorbug W/System.err: at com.testapp.android.ktorbug.testappViewModel.executeAndroidRequest(testappViewModel.kt:396)
2020-04-14 17:51:32.738 8777-8777/com.testapp.android.ktorbug W/System.err: at com.testapp.android.ktorbug.testappViewModel$executeAndroidRequest$1.invokeSuspend(Unknown Source:12)
2020-04-14 17:51:32.739 8777-8777/com.testapp.android.ktorbug W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
2020-04-14 17:51:32.739 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:238)
2020-04-14 17:51:32.739 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:194)
2020-04-14 17:51:32.739 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
2020-04-14 17:51:32.740 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(PipelineContext.kt:144)
2020-04-14 17:51:32.740 8777-8777/com.testapp.android.ktorbug W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
2020-04-14 17:51:32.740 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:238)
2020-04-14 17:51:32.740 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:194)
2020-04-14 17:51:32.740 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
2020-04-14 17:51:32.740 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(PipelineContext.kt:144)
2020-04-14 17:51:32.741 8777-8777/com.testapp.android.ktorbug W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
2020-04-14 17:51:32.741 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:238)
2020-04-14 17:51:32.741 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:194)
2020-04-14 17:51:32.741 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
2020-04-14 17:51:32.741 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(PipelineContext.kt:144)
2020-04-14 17:51:32.742 8777-8777/com.testapp.android.ktorbug W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
2020-04-14 17:51:32.742 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:238)
2020-04-14 17:51:32.742 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:194)
2020-04-14 17:51:32.742 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
2020-04-14 17:51:32.742 8777-8777/com.testapp.android.ktorbug W/System.err: at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(PipelineContext.kt:144)
2020-04-14 17:51:32.743 8777-8777/com.testapp.android.ktorbug W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
2020-04-14 17:51:32.743 8777-8777/com.testapp.android.ktorbug W/System.err: at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
2020-04-14 17:51:32.743 8777-8777/com.testapp.android.ktorbug W/System.err: at android.os.Handler.handleCallback(Handler.java:873)
2020-04-14 17:51:32.743 8777-8777/com.testapp.android.ktorbug W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
2020-04-14 17:51:32.743 8777-8777/com.testapp.android.ktorbug W/System.err: at android.os.Looper.loop(Looper.java:193)
2020-04-14 17:51:32.743 8777-8777/com.testapp.android.ktorbug W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6723)
2020-04-14 17:51:32.744 8777-8777/com.testapp.android.ktorbug W/System.err: at java.lang.reflect.Method.invoke(Native Method)
2020-04-14 17:51:32.744 8777-8777/com.testapp.android.ktorbug W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
2020-04-14 17:51:32.744 8777-8777/com.testapp.android.ktorbug W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Screenshots
If applicable, add screenshots to help explain your problem.
Hi @gabin8,
Yes, that's true. This problem was already mentioned in https://github.com/ktorio/ktor/issues/1623. We don't support the POST method in a redirect.
@dmitrievanthony Can you offer any workaround for this? Especially in case when I don't have control over server. Also it would be nice to make such redirect handling optional or even build-in. Because from what I see - the browsers, postman and other network clients handle such redirects and don't throw an exception
Well, @gabin8, as far as I understand in your case the POST after the redirect should become a GET method. This case is a bit simpler and you can implement it manually specifying the following redirect feature configuration:
val androidClient = HttpClient(Android) {
engine {
connectTimeout = 60_000
socketTimeout = 40_000
}
install(HttpRedirect) {
checkHttpMethod = false
}
}
val res = androidClient.post<String>("http://www.mocky.io/v2/5e95a5f12f00005b410252ca")
This workaround works well, so let me close the issue. In case of any additional questions feel free to reopen it.
Most helpful comment
Well, @gabin8, as far as I understand in your case the POST after the redirect should become a GET method. This case is a bit simpler and you can implement it manually specifying the following redirect feature configuration:
This workaround works well, so let me close the issue. In case of any additional questions feel free to reopen it.