Apollo-link-rest: 处理错误响应

创建于 2018-10-02  ·  16评论  ·  资料来源: apollographql/apollo-link-rest

您好,我有这个登录API,它将请求正文如下:

{
    "authentications": {
        "emailAddress": "[email protected]",
        "password": "11111111"
    }
}

如果成功,服务器将返回令牌:

{
    "authentications": {
        "token": "eyJhbGoiU3RvcmUifV0sImNyZWF0ZWRBdCI6IjIwMTgtMDktMTZUMTg6NTA6NTYuNT"
    }
}

如果电子邮件或密码输入不正确,它将返回:

{
    "message": "Cannot find document for class 'User'. searched with parameters: '{\"emailAddress\":\"[email protected]\"}'",
    "errorCode": 1103,
    "status": 404
}

我可以使用GraphQL模式成功登录,如下所示:

gql`
  fragment Authentications on any {
    emailAddress: String
    password: String
  }

  fragment AuthInput on REST {
    authentications {
      Authentications
    }
  }

  mutation signIn($input: AuthInput!) {
    authPayload(input: $input) 
      @rest(type: "AuthPayload", path: "/api/v1/authentications", endpoint:"UsersService", method:"POST") {
      authentications @type(name:"Auth"){
        token
      }
    }
  }
`;

我的问题是在出现错误(错误的电子邮件/密码)的情况下如何获得响应? 因为现在如果服务器返回错误,则响应始终为null:

Object {
    "data": Object {
        "authPayload": null,
    },
    "errors": undefined,
}
help wanted 🛠 question❔

最有用的评论

我也坚持这个问题。 是否有理由不返回完整的404响应,而不是返回null?

所有16条评论

如果您无法捕获400+错误,我认为此问题将非常有用。
https://github.com/apollographql/apollo-link-rest/issues/151

仅供参考:对于错误的凭据,您应该返回401。
https://stackoverflow.com/questions/1959947/whats-an-appropriate-http-status-code-to-return-by-a-rest-api-service-for-a-val

大家好,

我只是遇到这个问题,我也想知道处理404的推荐方法是什么。例如,它不会触发apollo-link-error

到目前为止,我正在考虑编写一个自定义错误处理程序链接,或者检查每个<Query />组件的响应中的数据内容。

FWIW我也有相同的情况,例如服务器返回404而不是401,但是不幸的是,此时更改服务器不是一种选择。

我认为解决这个用例是值得的,因为REST的状态码与GraphQL的状态码是非常不同的-并且更加多样化和重要。

我也坚持这个问题。 是否有理由不返回完整的404响应,而不是返回null?

我还没有遇到过这样的情况:没有将404错误视为对我有帮助的错误,我一直在努力寻找解决该问题的好方法。

是否认为“ 404未找到”可以描述成功地正确产生空集的数据查询?

它还可能表明服务所有者进行了如此重大的更改,以至于先前可用的端点已消失。

我认为最好用200 OK以及空或空的应用程序实体来处理第一种情况。 至少,这两种情况似乎很容易被客户辨别,因为它们非常不同。

是的,有意为空的数据集比人们想象的普遍得多吗? (至少让我感到惊讶!)由于用户经常将多个网络和其他呼叫收集到单个meta呼叫中,因此默认情况下在404上引发错误会产生巨大的影响,因为404会终止并行发生的所有其他数据提取。 我同意,如果每个GraphQL查询只执行一个REST调用,在我看来,鉴于官方的REST语义,我们应该抛出一个错误。

实际上,默认情况下不抛出错误似乎更好! 由于您可以通过添加自定义抓取方法来解决此问题,因此感觉就像“在接受的内容上保持自由”; 这种选择似乎与Apollo-link-rest的主要目的之一相匹配:帮助不一定控制后端的用户,并且那里只有许多“主要是REST”服务器,因此语义冲突很常见。 。

@williamboman ,如果使用customFetch参数,将Apollo-link-rest配置为抛出404相对简单,我不在电脑上,但是如果需要帮助,请告诉我!

嗨, @ fbartho,您能帮我编写customFetch处理404错误吗? 有一些例子吗?

@anasnain

在javascript中,它看起来像这样:

export async function customFetch(requestInfo, init) {
  const response = await fetch(requestInfo, init);
  if (response.status === 404) {
    throw new Error("404 File Not Found"); // Customize this however you like!
  }
  return response;
}

(在TypeScript中,它会更加冗长)

@fbartho感谢您的快速回复。 我现在可以抓到404。
但是,如何确定apollo-link-error的networkError捕获自定义提取中写入的错误(抛出新的Error(“ 404未找到文件”))?

啊,不幸的是,由于ApolloClient内部规则(关于链接的工作方式),我认为它会附加在graphQLErrors数组上(不在networkError属性上)。

这可能是可修复的,但我不知道如何。 -HTTPLink必须知道该怎么做,而我还没有机会进行调查。 我们的(工作)代码库中有一个辅助方法,可以解压缩嵌套的错误。 (这对于从apollo-link-state给我们抛出的错误也是必要的,因此它并不是真正的优先事项)

@fbartho在这种情况下,我完全没有收到任何错误。 数据返回null。 如果我们抛出错误,那是在期待一个错误而不是数据。 不知道如何实现这一点。

@anasnain自设置以来已经很久了,我忘记了。

您还需要配置一个apollo-link-error实例,这是我的配置:

const attachGQLErrorsToNetworkError = (
    graphQLErrors: readonly GraphQLError[],
    networkError: Error,
): void => {
    (networkError as any).tr_graphQLErrors = graphQLErrors;
    return;
};

/** Set behavior when errors occur and handle our own TR errors */
export const apolloErrorLink = onError((errorResponse: ErrorResponse) => {
    const {
        graphQLErrors = [],
        networkError,
    }: {
        graphQLErrors?: readonly GraphQLError[];
        networkError?: Error;
    } = errorResponse;

    /**
     * Our error parsing (function recursiveGQLErrorsFromNetworkError) rely
     * on attaching the following graphql errors.
     * Let's make sure to not attach anything `wrong` (ie: null, empty, ...)
     */
    const hasGraphQLErrors: boolean =
        graphQLErrors != null &&
        Array.isArray(graphQLErrors) &&
        graphQLErrors.length > 0;

    if (networkError && hasGraphQLErrors) {
        /*
         * graphQLErrors are not being passed through the chain of links,
         * but network errors are attaching the graphQLErrors to networkError
         * to be able to access them in a component
         */
        attachGQLErrorsToNetworkError(graphQLErrors, networkError);
    }
});

经过进一步的思考:我不能完全确定我了解您所描述的情况。

是无法在组件/反应代码中读取“ 404错误”的问题吗?

@fbartho
场景:我在其余的APIquery下运行,期望是我应该得到一个错误对象,以防它返回404错误代码,就像其他4xx错误和5xx错误一样。 但是在这种情况下,错误是不确定的,并且数据为空。
const {loading,error,data} = useQuery(CLIENT_API_QUERY);

这是Apollo客户端实例:

async function customFetch(requestInfo, init) {
    const response = await fetch(requestInfo, init);
    if (response.status === 404) {
        response.json().then((errorResponse) => {
          throw new Error(errorResponse);
        });
    }
    return response;
  }

const errorLink = onError(({ operation, response, graphQLErrors, networkError }) => {
    if (graphQLErrors) {
      graphQLErrors.forEach(({ message, path }) =>
           console.log(`[GraphQL error]: Message: ${message}, Path: ${path}`),
      );
    }
    if (networkError) {
        console.log(`[Network error ${operation.operationName}]: ${networkError.message}`);
    }
  });

const restLink = new RestLink({
    uri: 'https://run.mocky.io/v3/df72bacd-39cb-476d-bfda-06d7f5e9d77d',
    customFetch: (requestInfo, init) => customFetch(requestInfo, init)
});

const apolloClient = new ApolloClient({
    link: ApolloLink.from([errorLink, restLink]),
    new InMemoryCache(),
  });
export default apolloClient;

@anasnain-我知道的一件事是,我认为您在执行new Error时不能传递任意对象

另外,我认为您错过了一个等待,因此throw语句发生在restLink customFetch调用之外!

const err = new Error("404 Error");
try {
  err.responseJson = await response.json(); // This await crucial to get the error in the right spot!
} catch (parsingError) {
  // figure out what you want to do with parsingError?
}
throw err;
此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Simply007 picture Simply007  ·  5评论

dphaener picture dphaener  ·  5评论

sinisterra picture sinisterra  ·  6评论

Daniel-Griffiths picture Daniel-Griffiths  ·  5评论

kevinrobayna picture kevinrobayna  ·  6评论