Skip to content

Commit dffef43

Browse files
committed
broaden the possible exceptions from HttpInterceptor.intercept()
1 parent 771ffd6 commit dffef43

6 files changed

Lines changed: 35 additions & 36 deletions

File tree

.github/workflows/pr.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,15 @@ jobs:
8787
with:
8888
name: tests-integration.zip
8989
path: diagnostics.zip
90-
90+
ios-tests:
91+
runs-on: macos-14
92+
steps:
93+
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
94+
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
95+
with:
96+
distribution: 'temurin'
97+
java-version: 17
98+
- run: xcodebuild -allowProvisioningUpdates -project tests/com.apollographql.iostest/com.apollographql.iostest.xcodeproj -configuration Debug -scheme com.apollographql.iostest -sdk iphoneos -destination name='iPhone 16' test -test-timeouts-enabled YES
9199
intellij-plugin:
92100
if: "!startsWith(github.head_ref, 'release-')"
93101
name: Build IntelliJ Plugin

libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/network/http/HttpInterceptor.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ interface HttpInterceptorChain {
1818
interface HttpInterceptor {
1919
/**
2020
* Intercepts the request and returns a response.
21-
* Implementation may throw [ApolloException] in case of error. Those errors are typically
22-
* caught by the network transport and subsequently exposed in `ApolloResponse.exception`
21+
* Implementation may throw in case of error. Those errors are typically
22+
* caught by the network transport and subsequently exposed in `ApolloResponse.exception`.
23+
* If the exception is not an instance of [ApolloException], it will be wrapped in an
24+
* instance of [ApolloNetworkException].
2325
*/
24-
@Throws(ApolloException::class, CancellationException::class)
26+
@Throws(Throwable::class)
2527
suspend fun intercept(request: HttpRequest, chain: HttpInterceptorChain): HttpResponse
2628

2729
// TODO: remove dispose

libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/network/http/HttpNetworkTransport.kt

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import com.apollographql.apollo.mpp.currentTimeMillis
2929
import com.apollographql.apollo.network.NetworkTransport
3030
import com.benasher44.uuid.Uuid
3131
import com.benasher44.uuid.uuid4
32+
import kotlinx.coroutines.CancellationException
3233
import kotlinx.coroutines.flow.Flow
3334
import kotlinx.coroutines.flow.catch
3435
import kotlinx.coroutines.flow.emitAll
@@ -62,20 +63,23 @@ private constructor(
6263
): Flow<ApolloResponse<D>> {
6364
return flow {
6465
val millisStart = currentTimeMillis()
65-
var apolloException: ApolloException? = null
66+
var throwable: Throwable? = null
6667
val httpResponse: HttpResponse? = try {
6768
DefaultHttpInterceptorChain(
6869
interceptors = interceptors + engineInterceptor,
6970
index = 0
7071
).proceed(httpRequest)
71-
} catch (e: ApolloException) {
72-
apolloException = e
72+
} catch (t: Throwable) {
73+
if (t is CancellationException) {
74+
throw t
75+
}
76+
throwable = t
7377
null
7478
}
7579

7680
val responses = when {
7781
httpResponse == null -> {
78-
flowOf(errorResponse(request.operation, apolloException!!))
82+
flowOf(errorResponse(request.operation, throwable!!))
7983
}
8084

8185
httpResponse.statusCode !in 200..299 && !httpResponse.isGraphQLResponse -> {
@@ -212,11 +216,11 @@ private constructor(
212216
if (jsonMerger == null) {
213217
jsonMerger = DeferredJsonMerger()
214218
}
215-
val merged = jsonMerger!!.merge(part)
216-
val deferredFragmentIds = jsonMerger!!.mergedFragmentIds
217-
val isLast = !jsonMerger!!.hasNext
219+
val merged = jsonMerger.merge(part)
220+
val deferredFragmentIds = jsonMerger.mergedFragmentIds
221+
val isLast = !jsonMerger.hasNext
218222

219-
if (jsonMerger!!.isEmptyPayload) {
223+
if (jsonMerger.isEmptyPayload) {
220224
null
221225
} else {
222226
@Suppress("DEPRECATION")

tests/com.apollographql.iostest/com.apollographql.iostestTests/com_apollographql_iostestTests.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@ struct com_apollographql_iostestTests {
77
final class AuthenticationInterceptor: Apollo_runtimeHttpInterceptor {
88

99
func intercept(request: HttpRequest, chain: Apollo_runtimeHttpInterceptorChain) async throws -> HttpResponse {
10-
throw DefaultApolloException(message: "interceptor error", cause: nil)
11-
//try await chain.proceed(request: request)
10+
throw NSError(domain: "interceptor error", code: 42, userInfo: ["foo": "bar"])
1211
}
1312

1413
func dispose() {
1514
// No op
1615
}
1716
}
1817

18+
19+
1920
@Test func example() async throws {
2021
try MainKt.testInterceptor(interceptor: AuthenticationInterceptor())
2122
}
22-
2323
}
2424

25-
extension DefaultApolloException: Swift.Error {}
Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import com.apollographql.apollo.ApolloClient
2-
import com.apollographql.apollo.api.http.HttpRequest
3-
import com.apollographql.apollo.api.http.HttpResponse
4-
import com.apollographql.apollo.exception.ApolloException
5-
import com.apollographql.apollo.exception.DefaultApolloException
62
import com.apollographql.apollo.network.http.HttpInterceptor
7-
import com.apollographql.apollo.network.http.HttpInterceptorChain
83
import com.apollographql.mockserver.MockServer
94
import com.apollographql.mockserver.enqueueError
105
import com.example.GetFooQuery
@@ -19,22 +14,13 @@ fun testInterceptor(interceptor: HttpInterceptor) {
1914
ApolloClient.Builder()
2015
.serverUrl(mockServer.url())
2116
.addHttpInterceptor(interceptor)
22-
.addHttpInterceptor(object : HttpInterceptor {
23-
override suspend fun intercept(
24-
request: HttpRequest,
25-
chain: HttpInterceptorChain,
26-
): HttpResponse {
27-
//throw DefaultApolloException("interceptor#1 error")
28-
return chain.proceed(request)
29-
}
30-
31-
})
3217
.build()
3318
.use { apolloClient ->
3419
apolloClient.query(GetFooQuery()).execute().apply {
35-
check(exception!!.message!!.contains("interceptor error"))
20+
println("exception: ${exception!!.cause!!.message}")
21+
check(exception!!.cause!!.message!!.contains("interceptor error"))
3622
}
3723
}
3824
}
3925
}
40-
}
26+
}

tests/shared-framework/src/commonTest/kotlin/test/MainTest.kt renamed to tests/shared-framework/src/jvm/kotlin/test/JvmTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ import com.apollographql.apollo.network.http.HttpInterceptorChain
88
import testInterceptor
99
import kotlin.test.Test
1010

11-
class MainTest {
11+
class JvmTest {
1212
@Test
13-
fun exceptionTest() {
13+
fun throwingInInterceptorIsExposedInResponse() {
1414
testInterceptor(object : HttpInterceptor {
1515
override suspend fun intercept(
1616
request: HttpRequest,
1717
chain: HttpInterceptorChain,
1818
): HttpResponse {
19-
throw DefaultApolloException("interceptor error")
19+
throw Exception("interceptor error")
2020
}
2121
})
2222
}

0 commit comments

Comments
 (0)