Okhttp: Failing to close response in interceptor results in "Check failed"

Created on 21 Jan 2020  路  4Comments  路  Source: square/okhttp

I wrote an Interceptor that redirects to HTTPS based on information from the response, but on the second request the Transmitter throws an exception:

Exception in thread "main" java.lang.IllegalStateException: Check failed.
    at okhttp3.internal.connection.Transmitter.prepareToConnect(Transmitter.kt:125)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:62)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
    at HttpsUpgradeInterceptor.intercept(HttpsUpgradeInterceptor.kt:13)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:194)
    at okhttp3.RealCall.execute(RealCall.kt:67)
    at HttpsUpgradeInterceptorKt.main(HttpsUpgradeInterceptor.kt:26)
    at HttpsUpgradeInterceptorKt.main(HttpsUpgradeInterceptor.kt)

Code:
https://gist.github.com/octylFractal/713bf759781b2997bfc693ab4b1d2a5c

I'm not 100% sure if doing another request in an application interceptor is supported, but the error message isn't clear. Edit: read the interceptors page again, and this is advertised as supported, so this is definitely a bug

bug

All 4 comments

I'm not 100% but I seem to remember if you aren't cleanly closing the first request in the interceptor you can get similar errors. Try closing it.

But thanks for the reproduction otherwise.

Yeah, try this:

    override fun intercept(chain: Interceptor.Chain): Response {
        val response = chain.proceed(chain.request())
        val url = chain.request().url
        if (!url.isHttps && response.code == 501 && response.message == "HTTPS Required") {
            println("Upgrading $url to HTTPS and trying again after 501")
            response.close() // ADD THIS!
            return chain.proceed(chain.request().newBuilder()
                .url(url.newBuilder().scheme("https").build())
                .build())
        }
        return response
    }

Yes, that works perfectly, thank you. It might be nice to improve the exception message so it's clear what hasn't been done.

Was this page helpful?
0 / 5 - 0 ratings