diff --git a/okhttp/src/main/kotlin/okhttp3/internal/http/CallServerInterceptor.kt b/okhttp/src/main/kotlin/okhttp3/internal/http/CallServerInterceptor.kt index 32c21282da01..60161e921c85 100644 --- a/okhttp/src/main/kotlin/okhttp3/internal/http/CallServerInterceptor.kt +++ b/okhttp/src/main/kotlin/okhttp3/internal/http/CallServerInterceptor.kt @@ -148,16 +148,18 @@ class CallServerInterceptor(private val forWebSocket: Boolean) : Interceptor { } } - private fun shouldIgnoreAndWaitForRealResponse(code: Int): Boolean = when { - // Server sent a 100-continue even though we did not request one. Try again to read the - // actual response status. - code == 100 -> true + companion object { + fun shouldIgnoreAndWaitForRealResponse(code: Int): Boolean = when { + // Server sent a 100-continue even though we did not request one. Try again to read the + // actual response status. + code == 100 -> true - // Handle Processing (102) & Early Hints (103) and any new codes without failing - // 100 and 101 are the exceptions with different meanings - // But Early Hints not currently exposed - code in (102 until 200) -> true + // Handle Processing (102) & Early Hints (103) and any new codes without failing + // 100 and 101 are the exceptions with different meanings + // But Early Hints not currently exposed + code in (102 until 200) -> true - else -> false + else -> false + } } } diff --git a/okhttp/src/main/kotlin/okhttp3/internal/http2/Http2Stream.kt b/okhttp/src/main/kotlin/okhttp3/internal/http2/Http2Stream.kt index e8a6d7499d10..f625d02a7c03 100644 --- a/okhttp/src/main/kotlin/okhttp3/internal/http2/Http2Stream.kt +++ b/okhttp/src/main/kotlin/okhttp3/internal/http2/Http2Stream.kt @@ -18,6 +18,8 @@ package okhttp3.internal.http2 import okhttp3.Headers import okhttp3.internal.EMPTY_HEADERS import okhttp3.internal.assertThreadDoesntHoldLock +import okhttp3.internal.http.CallServerInterceptor +import okhttp3.internal.http.CallServerInterceptor.Companion.shouldIgnoreAndWaitForRealResponse import okhttp3.internal.notifyAll import okhttp3.internal.toHeaderList import okhttp3.internal.wait @@ -258,12 +260,12 @@ class Http2Stream internal constructor( if (this.errorCode != null) { return false } - if (source.finished && sink.finished) { - return false - } this.errorCode = errorCode this.errorException = errorException notifyAll() + if (source.finished && sink.finished) { + return false + } } connection.removeStream(id) return true @@ -283,7 +285,10 @@ class Http2Stream internal constructor( val open: Boolean synchronized(this) { if (!hasResponseHeaders || !inFinished) { - hasResponseHeaders = true + val status = headers[Header.RESPONSE_STATUS_UTF8]?.toIntOrNull() + if (status == null || !shouldIgnoreAndWaitForRealResponse(status)) { + hasResponseHeaders = true + } headersQueue += headers } else { this.source.trailers = headers diff --git a/okhttp/src/test/java/okhttp3/InformationalResponseCodeTest.kt b/okhttp/src/test/java/okhttp3/InformationalResponseCodeTest.kt index 46bcd26d86d1..f0a55007591f 100644 --- a/okhttp/src/test/java/okhttp3/InformationalResponseCodeTest.kt +++ b/okhttp/src/test/java/okhttp3/InformationalResponseCodeTest.kt @@ -30,19 +30,22 @@ class InformationalResponseCodeTest { recordFrames = true } - private var client = clientTestRule.newClient() + private var client = clientTestRule.newClientBuilder() + .followRedirects(false) + .build() @Test fun test103() { // Pretend we are curl so cloudflare will send a 103 val request = Request.Builder() - .url("https://tradingstrategy.ai") - .header("user-agent", "curl/7.85.0") + .url("https://theornateoracle.com/cart.php?action=add&product_id=456") + .header("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36") .build() val response = client.newCall(request).execute() - assertThat(response.code).isEqualTo(200) + assertThat(response.code).isEqualTo(302) assertThat(response.protocol).isEqualTo(Protocol.HTTP_2) response.close()