How to handle HTTP error with combination of valid graphql response
Question
Hi,
We found an interesting situation where I'm not sure if it is a missing feature in the Apollo Kotlin client or if we just haven't found the answer.
Our backend currently has a feature where it returns HTTP status codes (401, 429, 500, etc.) along with a valid GraphQL response. This does not seem to be an issue for the iOS client, React client, etc., but for the Kotlin client, it appears to be problematic. When the response is not 2XX, an ApolloHttpException is thrown, and there is no data in response.data nor errors in response.errors. I was able to overcome this issue by changing the status code of the HTTP response in an OkHttp interceptor so that the body is still parsed.
According to the documentation for GraphQL routers, this is a valid response. For example, here: Apollo GraphQL Router Customizations
fn supergraph_service(service) {
// Define a closure to process our request
let f = |request| {
// Something goes wrong during request processing...
throw #{
status: 403,
body: #{
errors: [#{
message: `I have raised a 403`,
extensions: #{
code: "ACCESS_DENIED"
}
}]
}
};
};
// Map our request using our closure
service.map_request(f);
}
However, it seems that the Kotlin client doesn't allow processing such requests, and without some "hacks," you cannot access the GraphQL body response when an HTTP code outside the 2XX range is received. How can this problem be solved without "hacks"?
Thank you.
Hi 👋 You've just bumped into a loophole of GraphQL, congrats! The HTTP transport is not specified at the moment (a draft is here though) and it's hard to align implementations.
I'll look into what it takes to let some errors pass through but this might take a while to settle on this. In the short term, your solution is good 👍
Out of curiosity, when the error code is not 2XX, do you have data != null? Or just errors != null
both data and errors are null
Sorry, I meant in your backend response.
Does your server return != 2XX together with some data? The GraphQL over HTTP spec seems to go towards not allowing this (although I'll need to reread that several times since it also looks like it depends the content-type)
I see, it will return only error and according they understanding of graphql specification which should be active from 1.1.2025 they will return just errors with no data at all. As shown in example:
body: #{
errors: [#{
message: `I have raised a 403`,
extensions: #{
code: "ACCESS_DENIED"
}
}]
}
they will return just errors with no data at all
Gotcha 👍 Yep, that makes sense.
In #6170 we add support for the application/graphql-response+json content-type, which allows non-200 status codes, if your server can support that.
This is not released yet, in the meantime it can be tried out with the snapshots.
Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Kotlin usage and allow us to serve you better.