Skip to content

Commit

Permalink
fix: Treat malformed HTTP responses as connection errors (#63)
Browse files Browse the repository at this point in the history
By default, OkHTTP would throw an IOException when an illegal HTTP response is returned, which is an unexpected exception. This PR replaces that exception with java.net.ConnectException, which we catch and wrap with a PoWeb `ServerConnectionException`, which provides more useful information.

Before:

```
java.io.IOException: unexpected end of stream on http://127.0.0.1:13276/...
        at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:202)
        (...)
     Caused by: java.io.EOFException: \n not found: limit=0 content=…
        at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.kt:348)
        (...)
```

[Now](https://console.firebase.google.com/u/0/project/relaynet-gateway-android/testlab/histories/bh.fce322cdd2254629/matrices/6474453305210171425/executions/bs.a50e5565a3e74f36/testcases/5/test-cases), using relaycorp/relaynet-gateway-android@731ab77:

```
tech.relaycorp.poweb.ServerConnectionException: Failed to connect to http://127.0.0.1:13276/v1/parcels
(...)
Caused by: java.net.ConnectException: Failed to connect to /127.0.0.1:13276
(...)
Caused by: java.net.ConnectException: failed to connect to /127.0.0.1 (port 13276) from /127.0.0.1 (port 43068) after 10000ms: (...)
Caused by: android.system.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)

```
  • Loading branch information
gnarea authored Sep 30, 2020
1 parent 39ec031 commit ded7c40
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/main/kotlin/tech/relaycorp/poweb/PoWebClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import kotlinx.coroutines.channels.ClosedReceiveChannelException
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.flow
import okhttp3.OkHttpClient
import tech.relaycorp.poweb.handshake.Challenge
import tech.relaycorp.poweb.handshake.InvalidChallengeException
import tech.relaycorp.poweb.handshake.Response
Expand Down Expand Up @@ -55,7 +56,14 @@ public class PoWebClient internal constructor(
internal val hostName: String,
internal val port: Int,
internal val useTls: Boolean,
ktorEngine: HttpClientEngine = OkHttp.create {}
ktorEngine: HttpClientEngine = OkHttp.create {
// By default, OkHTTP would throw an IOException when an illegal HTTP response is returned.
// Enabling retryOnConnectionFailure would treat that as a connection failure and try again,
// throwing a java.net.ConnectException if it still fails -- And ConnectException is a
// more reliable exception to handle when something like this goes wrong. See:
// https://github.com/relaycorp/relaynet-poweb-jvm/issues/61
preconfigured = OkHttpClient.Builder().retryOnConnectionFailure(true).build()
}
) : Closeable {
internal var ktorClient = HttpClient(ktorEngine) {
install(WebSockets)
Expand Down

0 comments on commit ded7c40

Please sign in to comment.