Apollo-ios: handleErrorOrRetry does not work when errors are returned in GraphQL response body

Created on 11 Jul 2019  路  11Comments  路  Source: apollographql/apollo-ios

@designatednerd I want to first thank you for getting out the latest HTTPNeworkTransport Delegates.

I just am not sure if the below function works

  func networkTransport(_ networkTransport: HTTPNetworkTransport,
                        receivedError error: Error,
                        for request: URLRequest,
                        response: URLResponse?,
                        retryHandler: @escaping (_ shouldRetry: Bool) -> Void)

According to graphQL

Notice that HTTP status codes are not relevant when using GraphQL! A GraphQL server will always respond with code 200 (unless an internal server occured, then it might be code 500). Any further information needs to be parsed from the JSON payload of the response.

Here is a screenshot from my GraphQL server with an invalid token error, returns a 401 in the errors array, but because it returns a 200, it doesn't seem to call the above function, and is actually considered a success.

Screenshot 2019-07-11 at 1 02 27 PM

I'm not sure if this is a limitation on your work, or from the existing work on how errors are handled by apollo-ios:

public func send<Operation>(operation: Operation, completionHandler: @escaping (_ response: GraphQLResponse<Operation>?, _ error: Error?) -> Void) -> Cancellable

Any insight would be appreciated.

Thanks

bug

Most helpful comment

@nexig Yes, you should use the HTTPNetworkTransportGraphQLErrorDelegate, it's a separate method which handles GraphQL errors specifically.

All 11 comments

ARGH. Yeah we're getting everything up to parsing errors but because GQL can potentially return a partial result and a partial error, I'll have to think through how to handle this.

For clarity, are you using an Apollo server or a different server?

Yea, wondering if parsing through each response for a non-empty error array is effective. Thats currently what we do on iOS on the response of each specific call.

We use absinthe and the elixir language on phoenix to run GraphQL. And of course Apollo-iOS 0.11.0 for our app.

Right now as a workaround for 401鈥檚, we are checking the expiry for auth before sending the call, authenticating and then making the request.

Checking the auth expiration using the pre-flight delegate is better if you have access to it - that way you don't burn the data/battery of making a call just to have to make two more calls (re-auth and retry).

The problem with offering retry on a non-empty error array is that a non-empty error array doesn't necessarily indicate a total failure. Because GraphQL can return a partial result with partial errors, retry may not be the appropriate response for the partial errors.

I'm gonna mull this over more on Monday.

I decided I'm going to leave this open, but it will probably be a bit before I address it. I need to take a deeper look at how we're handling results, especially with partial failure/partial success, since that has a ton to do with how to handle issues like this.

For now, I'd keep doing what you're doing - like I said, checking that expiration pre-flight is usually a much better way of making sure you're not making unnecessary calls.

sounds good! thanks for keeping it open and addressing it when you are able to

Hey @rajkhatri

Can you show me an example go how you are handling token expiration on pre-flight? I can't manage to do it somehow.

Please take a look at PR #770 which introduces a delegate to handle errors in the GraphQL response body

This has now shipped with 0.19.0 - give CocoaPods about half an hour to update trunk and the CDN, but for SPM or Carthage this is available immediately.

@designatednerd I tested it on version 0.20.0 and I see it still not working. I receive response from backend with status code 200 but with 401 error in response body. I see that method from HTTPNetworkTransportRetryDelegate is not called. Should I implement it in another way?

@nexig Yes, you should use the HTTPNetworkTransportGraphQLErrorDelegate, it's a separate method which handles GraphQL errors specifically.

@designatednerd thanks for help, it works well

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hiteshborse12 picture hiteshborse12  路  4Comments

vishal-p picture vishal-p  路  4Comments

StanislavCekunov picture StanislavCekunov  路  3Comments

wnagrodzki picture wnagrodzki  路  4Comments

plm75 picture plm75  路  4Comments