-
Notifications
You must be signed in to change notification settings - Fork 645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there a way of reading the Request and Response body
more than once?
#5007
Comments
Hi! You can use class MyInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
val responseStr = response.body?.source()?.peek()?.readUtf8()
println("Intercepted response: $responseStr")
return response
}
} To use it with Apollo Kotlin: val apolloClient = ApolloClient.Builder()
.serverUrl("https://...")
.okHttpClient(
OkHttpClient.Builder()
.addInterceptor(MyInterceptor())
.build()
)
.build() Let us know if that works for you! |
As an additional note, @marandaneto Is there anything else you need besides the operation document and the errors? If you only need that, you can use val interceptor = object: ApolloInterceptor {
override fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>> {
return chain.proceed(request).onEach {response ->
println("GraphQL document: ${request.operation.document()}")
println("Errors: ${response.errors}")
}
}
} |
@BoD Oh indeed, missed that, thanks. For the request, I believe it's also not a problem if I just: For the request, I can just do |
@martinbonnin The problem with Edit:
From https://github.com/apollographql/apollo-kotlin-tutorial/tree/main/compose/final |
You can catch that: val interceptor = object : ApolloInterceptor {
override fun <D : Operation.Data> intercept(request: ApolloRequest<D>, chain: ApolloInterceptorChain): Flow<ApolloResponse<D>> {
return chain.proceed(request)
.catch {
println("Oh no, network error: $it")
throw it
}.onEach { response ->
println("GraphQL document: ${request.operation.document()}")
println("GraphQL errors: ${response.errors}")
}
}
} Edit: in order to read the error body, you'll need exposeHttpErrorBody. So it's definitely more involved but it can save the buffering of the full HTTP response in the non-error case Edit2: also v4 is changing this to avoid throwing when exceptions happen (#4711) |
Thanks @martinbonnin and @BoD , let me try this out. |
Alright, looks like this would do: val apolloClient = ApolloClient.Builder()
.serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
.webSocketServerUrl("wss://apollo-fullstack-tutorial.herokuapp.com/graphql")
.okHttpClient(
OkHttpClient.Builder()
.addInterceptor(AuthorizationInterceptor())
.build()
)
.webSocketReopenWhen { throwable, attempt ->
Log.d("Apollo", "WebSocket got disconnected, reopening after a delay", throwable)
delay(attempt * 1000)
true
}
.httpExposeErrorBody(true)
// add sentry interceptors
.sentryTracing()
.build() class TestApolloInterceptor : ApolloInterceptor {
override fun <D : Operation.Data> intercept(
request: ApolloRequest<D>,
chain: ApolloInterceptorChain
): Flow<ApolloResponse<D>> {
return chain.proceed(request)
.catch {
val body = (it as? ApolloHttpException)?.body
// I have to use the peek to read but not to consume the bytes
println("Body: ${body?.peek()?.readUtf8()}")
throw it
}
.onEach { response ->
println("GraphQL document: ${request.operation.document()}")
println("Errors: ${response.errors}")
}
}
} @BoD @martinbonnin a last question, would be possible to access the raw body of the I will close the issue for now since I can also parse the Thanks for the great work & support. |
At the end of the day, I'd say it all depends your requirements. If you need access to the raw request/response bytes, then
|
Question
When reading the Request and Response bodies more than once, it throws
IllegalStateException
(closed).The reason is most likely because of MultipartReader.
I've tried using a
HttpInterceptor
,ApolloInterceptor
fromapollo3
, andInterceptor
fromokhttp3
.Usually reading
request/request.data
, orrequest/request.body
, returning aBufferedSource
.If the Sentry SDK reads the Request and Response bodies once, the final App won't be able to and this is a blocker.
The problem is that error monitoring tools such as Sentry.io would be able to leverage GraphQL errors if we are able to read the request and response bodies from the
apollo-kotlin
lib in order to give more context to those errors.A bit more context getsentry/sentry#33723
This feature will be opt-in by default due to PII concerns.
Our backend service has data scrubbing capabilities as well.
Is there any workaround to make that work with the Apollo Kotlin library? Thanks a bunch.
The text was updated successfully, but these errors were encountered: