apollo-link-rest
apollo-link-rest copied to clipboard
Response status based on the response document
So I have a case where my API server will give a status code 400 and internal error code 1501 on the response document meaning "invalid ID", ie.:
{
"code": 1501,
"id": "00jph2tpvxfrv8smz98rkee0ekd8oob1",
"message": "Could not load catalog",
"details": "Invalid resource id",
"previous": null,
"@note.1": "Hey! It looks like you found an error. If you have any questions about this error, feel free to contact support with the above error id."
}
As far as the web client is concerned, this is effectively a 404 and should be treated as such. But there is currently no convenient way of achieving this behavior in RestLink;
- the
responseTransformeris applied after thestatusreading and also only handles the response body customFetchtakes an extraordinary amount of jerry-rigging to get working both client-side and server-side getting this behavior(in fact I haven't managed).
So tl;dr, it would be nice to be able to either:
- Inform
RestLinkof an alternative status code interpretation based on the response document - Take over
statuscode handling entirely(as in, be allowed to inject an alternative implementation of this section: https://github.com/apollographql/apollo-link-rest/blob/5960abb3cae90bf1302654d39f6635d9f30df4cc/src/restLink.ts#L1011-L1044) - Or some other good idea someone might have to solve this quandary!
Hope this issue isn't too freeform 😅
+1, great dive into this @klarstrup! Running into the same problem but in the other direction: a REST interface I can't modify returns 400's with a "message: (stringified JSON)" in the body, that indicates validation errors on a POST call from a mutation, etc. As it stands, I see no way to tell rest-link that's a GraphQL error rather than a network error. Have tried intercepting the response and mangling it with apollo-link-error, as well as rewriting that link itself.
I did put a hacky workaround in place using an apollo-link similar to apollo-link-error. Yours might look something like this:
const errorLink = new ApolloLink((operation, forward) => {
return new Observable(observer => {
let sub: ZenObservable.Subscription;
try {
sub = forward!(operation).subscribe({
next: result => {
if (result.code === 1501) {
observer.error(new Error('This is actually an error'));
} else {
observer.next(result)
}
},
error: networkError => {
observer.error(networkError)
}
},
complete: () => {
observer.complete();
},
});
} catch (e) {
observer.error(e);
}
return () => {
if (sub) sub.unsubscribe();
};
});
});
It would be really great if we could provide a custom determineError() or similar method to link-rest. It does seem to me like the assumptions made in link-rest differ from those in the vanilla link-http.
I think by its nature, rest-link can't be as opinionated as the http-link. As the docs point out, in most use cases for link-rest, we can't change the backend. Thus, the response shapes and behavior won't fit any prescribed pattern, and there should be flexibility to decide whether a response is a GraphQL error, a network error, or no error at all.
If there's bandwidth to work with me on this, I can take on a PR.
Related: https://github.com/apollographql/apollo-link/issues/855