-
Notifications
You must be signed in to change notification settings - Fork 309
Description
Perceived Problem
We have an api that implements certain stuff "outside" of graphql and might at any time return a non-graphql response back to our client, e.g. 401 Unauthorized or 403 Forbidden. In some of these responses we get a regular json body back with some details on why it went wrong.
While that body might not be useful for end users we do need access to it in our error handling and reporting to be able to more closely pin down what has happened.
The issue is that graphql-request will not provide any version of the response body if it couldn't parse the body as a graphql response.
Ideas / Proposed Solution(s)
My proposal is to include the original response in the ClientError. I have patched this locally (can be provided if interesting) and found it to be working fine.
Below is an extract of our response middleware, the response in this case holds some message, in json-format, as to why the kill switch was triggered.
if (res instanceof ClientError && res.originalResponse !== undefined) {
// This could have been res.response.headers['Kill-Switch'], but headers is not typed properly
// ↓
const hasKillSwitch = res.originalResponse.headers.get("Kill-Switch");
if (hasKillSwitch) {
const reason = await extractKillSwitchReason(res.originalResponse);
throw new KillSwitchError(reason);
}
}The ClientError would look something like this:
export class ClientError extends Error {
public response: GraphQLResponse
public request: GraphQLRequestContext
+ public originalResponse?: Response
- constructor(response: GraphQLResponse, request: GraphQLRequestContext) {
+ constructor(response: GraphQLResponse, request: GraphQLRequestContext, originalResponse?: Response) {
const message = `${ClientError.extractMessage(response)}: ${
JSON.stringify({
response,
request,
})
}`
super(message)
Object.setPrototypeOf(this, ClientError.prototype)
this.response = response
this.request = request
+ this.originalResponse = originalResponse
// this is needed as Safari doesn't support .captureStackTrace
if (typeof Error.captureStackTrace === `function`) {
Error.captureStackTrace(this, ClientError)
}
}
private static extractMessage(response: GraphQLResponse): string {
return response.errors?.[0]?.message ?? `GraphQL Error (Code: ${String(response.status)})`
}
}I would be happy to align on this and provide a PR if this kind of feature would be interesting.