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
,所以我认为我将开始对话。
这是一个很好的问题。 -我希望将此模式添加为文档的建议。 我认为这是多个阿波罗链接遭受的一类问题(想到了阿波罗链接状态)。
我不知道我们确定这对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这是一个很好的回应。 我会支持默认情况下实现您的行为的修复程序!
我已将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约定转换为GraphQLnull
返回值约定。
那么GraphQL如何建议您在UI中处理404响应? 没做什么? 因此,请求只是悄悄地死掉了吗? 那真是令人难以置信的糟糕/糟糕的UX / api管理。
如果您通过ID查询项目并返回空值,请在UI中进行相应处理。 如果它包含数据,则显示它。
我在这里同意@marnusw ,我们不能真正控制用户的rest API做什么,因此该库在允许的内容上不应过分严格。 404 => null映射是一种相对直观的语义,它使您可以从REST的每个请求模型的单个资源转移到GraphQL的每个请求的多个资源(从客户端角度),而不会丢失丢失的数据。
也许可以有一种更好的方法来退出此行为,例如响应转换器的预包装版本或让用户完全控制http状态处理的请求处理逻辑的抽象。 但是我不认为将其恢复为以前的行为是正确的方法。
该方法的部分问题是,在结果订阅中,您不知道它是否为空结果(因为它为404),或者是否为无内容返回201或类似内容。 我在固件中对此进行了修复,检查状态并强制其引发出现问题的错误,因为我无法访问实际的服务器错误消息,尤其是在我的情况下,因为我们使用自定义提取来注入auth令牌,并且在apollo删除响应之前无法使用它获取响应。 除了一个案例,我的解决方案对于整个应用程序中的其他404响应来说是一个糟糕的毯子。