Apollo-link-rest: 处理404错误的推荐策略?

创建于 2018-06-06  ·  12评论  ·  资料来源: apollographql/apollo-link-rest


REST API使用404响应来指示记录不存在是很常见的。 现在,当发生这种情况时,结果是一个networkError ,默认情况下,它被视为比Apollo堆栈的GraphQL错误更致命的错误。

例如,使用查询:

query BookQuery($slug: ID!) {
  book(slug: $slug) @rest(type: "Book", path: "book/:slug") {
    name
    author
  }
}

如果端点返回404,它将拒绝网络错误,该错误必须在意图可能仅使用error渲染道具向用户显示非致命错误消息的情况下进行处理。 即,如果这是一个GraphQL查询而不是REST,则不会被分类为网络错误,将以这种方式进行处理。

我要解决的问题是在我的自定义error-link添加了一个检查,这将404网络错误转换为GraphQL错误:

forward(operation).subscribe({
  next: result => {...},
  error: networkError => {
    if (networkError.statusCode === 404) {
      return observer.next({errors: [networkError]});
    }
    //...
    observer.error(networkError);
  },
  complete: observer.complete.bind(observer),
});

也许在这方面仍有改进的余地,但确实可以解决问题。

我想知道是否可以/应该在apollo-link-rest ,所以我认为我将开始对话。

enhancement💡 question❔

所有12条评论

这是一个很好的问题。 -我希望将此模式添加为文档的建议。 我认为这是多个阿波罗链接遭受的一类问题(想到了阿波罗链接状态)。

我不知道我们确定这对ApolloLink的所有用户都是正确的答案吗?

当前,这是在apollo-link-rest中处理所有http错误的方式

        if (res.status >= 300) {
          // Throw a JSError, that will be available under the
          // "Network error" category in apollo-link-error
          let parsed: any;
          try {
            parsed = await res.json();
          } catch (error) {
            // its not json
            parsed = await res.text();
          }
          rethrowServerSideError(
            res,
            parsed,
            `Response not successful: Received status code ${res.status}`,
          );
        }
        return res;

也许我们添加了一个大小写匹配功能,该功能可以让用户指定如何处理错误?
可以为404 == null等常见情况提供一些有用的默认实用程序

尽管我与@fbartho一样担心,我们介绍的解决方案可能不适用于此链接的所有用户,但我想到了一种情况,其中404错误特别有害。 如果我们从测试中举这个例子:

query postAndTags {
  post @rest(type: "Post", path: "/post/1") {
    id
    title
  }
  tags @rest(type: "[Tag]", path: "/tags") {
    name
  }
}

并且post不存在并返回404,则整个查询由于网络错误而失败。 尽管在某些情况下可能需要这样做,但结果似乎应该是:

const data = {
  post: null,
  tags: [{ name: 'apollo' }, { name: 'graphql' }],
}

如果我们要满足此要求,则按照@paulpdaniels的建议添加其他错误处理将非常容易。 查看4xx错误,我只能真正看到404和400/412/422(关于突变)可能是非致命错误,需要进行特殊处理,例如GraphQL错误或将结果设置为null

问题仍然是为这些错误提供一些固定的处理程序是否合理,还是应该留给error-link或应用程序使用。 因为不支持多个变异查询(我认为?),所以当前唯一看起来特别相关的缺点是我从上面开始的404示例。

也可以在配置中添加一个错误处理程序,但这似乎是在盗用error-link ,而后者实际上确实属于其中。 这也很可能使此链接的API变得不必要地复杂。

@marnusw这是一个很好的回应。 我会支持默认情况下实现您的行为的修复程序!

142添加了404错误处理。 我认为这是这次讨论中最重要的事情。

基于许多其他api标准,所有错误代码都应始终包含一条人类可读的消息。 就像#142中所做的那样,取消该结果与之直接相反。

我已将PR恢复为正常的网络错误,以恢复404,以符合良好的REST API惯例: https :

@christrude虽然我无法同意您对REST API的看法,但该库的目的是使REST API像GraphQL一样工作。 因此,如果GraphQL解决资源丢失的方法是返回null ,则此库应将RESTful 404约定转换为GraphQL null返回值约定。

@christrude虽然我无法同意您对REST API的看法,但该库的目的是使REST API像GraphQL一样工作。 因此,如果GraphQL解决资源丢失的方法是返回null ,则此库应将RESTful 404约定转换为GraphQL null返回值约定。

那么GraphQL如何建议您在UI中处理404响应? 没做什么? 因此,请求只是悄悄地死掉了吗? 那真是令人难以置信的糟糕/糟糕的UX / api管理。

如果您通过ID查询项目并返回空值,请在UI中进行相应处理。 如果它包含数据,则显示它。

我在这里同意@marnusw ,我们不能真正控制用户的rest API做什么,因此该库在允许的内容上不应过分严格。 404 => null映射是一种相对直观的语义,它使您可以从REST的每个请求模型的单个资源转移到GraphQL的每个请求的多个资源(从客户端角度),而不会丢失丢失的数据。

也许可以有一种更好的方法来退出此行为,例如响应转换器的预包装版本或让用户完全控制http状态处理的请求处理逻辑的抽象。 但是我不认为将其恢复为以前的行为是正确的方法。

该方法的部分问题是,在结果订阅中,您不知道它是否为空结果(因为它为404),或者是否为无内容返回201或类似内容。 我在固件中对此进行了修复,检查状态并强制其引发出现问题的错误,因为我无法访问实际的服务器错误消息,尤其是在我的情况下,因为我们使用自定义提取来注入auth令牌,并且在apollo删除响应之前无法使用它获取响应。 除了一个案例,我的解决方案对于整个应用程序中的其他404响应来说是一个糟糕的毯子。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Paddy-Hamilton picture Paddy-Hamilton  ·  7评论

kevinrobayna picture kevinrobayna  ·  6评论

eranimo picture eranimo  ·  5评论

sinisterra picture sinisterra  ·  6评论

MichelDiz picture MichelDiz  ·  7评论