Skip to content

Commit a127f8a

Browse files
authored
Add KDoc for ApolloInterceptor (#6295)
1 parent 13c81ff commit a127f8a

File tree

2 files changed

+115
-3
lines changed

2 files changed

+115
-3
lines changed

libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/interceptor/ApolloInterceptor.kt

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,48 @@ import com.apollographql.apollo.api.Operation
55
import com.apollographql.apollo.api.ApolloResponse
66
import kotlinx.coroutines.flow.Flow
77

8+
/**
9+
* An [ApolloInterceptor] intercepts requests at the GraphQL layer.
10+
*
11+
* [ApolloInterceptor]s may modify the request and or the response:
12+
*
13+
* ```kotlin
14+
* // Add a header to each request and extensions to each response.
15+
* val newRequest = request.newBuilder()
16+
* .addHttpHeader("foo1", "bar1")
17+
* .build()
18+
*
19+
* return chain.proceed(newRequest).map {
20+
* it.newBuilder()
21+
* .extensions(mapOf("foo2" to "bar2"))
22+
* .build()
23+
* }
24+
* ```
25+
*
26+
* @see [com.apollographql.apollo.api.ExecutionContext]
27+
* @see [com.apollographql.apollo.network.http.HttpInterceptor]
28+
*/
29+
interface ApolloInterceptor {
30+
/**
31+
* Intercepts the given [request]. Call `chain.proceed()` to continue with the next interceptor or emit items
32+
* directly to bypass the chain.
33+
*
34+
* Exceptions thrown from [intercept] are not caught and are propagated to the call site. Use `ApolloResponse.Builder.exception()`
35+
* to return an exception response if you don't want your [com.apollographql.apollo.ApolloCall] to throw.
36+
*
37+
* @see ApolloResponse.Builder
38+
*/
39+
fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>>
40+
}
41+
42+
/**
43+
* An [ApolloInterceptorChain] is a list of interceptors called in order. Each interceptor wraps the subsequent ones
44+
* and can delegate to them by calling [proceed] or emit items directly.
45+
*/
846
interface ApolloInterceptorChain {
947
fun <D : Operation.Data> proceed(request: ApolloRequest<D>): Flow<ApolloResponse<D>>
1048
}
1149

12-
interface ApolloInterceptor {
13-
fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>>
14-
}
1550

1651
internal class DefaultInterceptorChain(
1752
private val interceptors: List<ApolloInterceptor>,
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import com.apollographql.apollo.ApolloClient
2+
import com.apollographql.apollo.api.ApolloRequest
3+
import com.apollographql.apollo.api.ApolloResponse
4+
import com.apollographql.apollo.api.Operation
5+
import com.apollographql.apollo.exception.DefaultApolloException
6+
import com.apollographql.apollo.interceptor.ApolloInterceptor
7+
import com.apollographql.apollo.interceptor.ApolloInterceptorChain
8+
import kotlinx.coroutines.flow.Flow
9+
import kotlinx.coroutines.flow.flow
10+
import kotlinx.coroutines.flow.map
11+
import kotlinx.coroutines.runBlocking
12+
import okio.use
13+
import test.FooQuery
14+
import kotlin.test.Test
15+
import kotlin.test.assertEquals
16+
import kotlin.test.assertFailsWith
17+
import kotlin.test.assertIs
18+
19+
class InterceptorsErrorTest {
20+
@Test
21+
fun interceptorsMayThrow() {
22+
ApolloClient.Builder()
23+
.serverUrl("unused")
24+
.addInterceptor(object : ApolloInterceptor {
25+
override fun <D : Operation.Data> intercept(
26+
request: ApolloRequest<D>,
27+
chain: ApolloInterceptorChain,
28+
): Flow<ApolloResponse<D>> {
29+
throw IllegalStateException("woops")
30+
}
31+
})
32+
.build()
33+
.use { apolloClient ->
34+
35+
runBlocking {
36+
val exception = assertFailsWith<IllegalStateException> {
37+
apolloClient.query(FooQuery())
38+
.execute()
39+
}
40+
41+
assertEquals("woops", exception.message)
42+
}
43+
}
44+
}
45+
46+
@Test
47+
fun interceptorsMayReturnExceptionResponse() {
48+
ApolloClient.Builder()
49+
.serverUrl("unused")
50+
.addInterceptor(object : ApolloInterceptor {
51+
override fun <D : Operation.Data> intercept(
52+
request: ApolloRequest<D>,
53+
chain: ApolloInterceptorChain,
54+
): Flow<ApolloResponse<D>> {
55+
return flow {
56+
emit(
57+
ApolloResponse.Builder(request.operation, request.requestUuid)
58+
.exception(DefaultApolloException("oh no", IllegalStateException("woops")))
59+
.build()
60+
)
61+
}
62+
}
63+
})
64+
.build()
65+
.use { apolloClient ->
66+
runBlocking {
67+
apolloClient.query(FooQuery())
68+
.execute()
69+
.apply {
70+
assertIs<DefaultApolloException>(exception)
71+
assertIs<IllegalStateException>(exception!!.cause)
72+
assertEquals("woops", exception!!.cause!!.message)
73+
}
74+
}
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)