我在使用Graphql和Apollo Client时遇到了麻烦。
当我使用REST时,我总是创建不同的响应,如401代码,但在这里我不知道如何做类似的行为。
当我得到响应时,我希望它转到catch函数。 我在前面有这个代码:
client.query({
query: gql`
query TodoApp {
todos {
id
text
completed
}
}
`,
})
.then(data => console.log(data))
.catch(error => console.error(error));
有人能帮助我吗?
答案 0 :(得分:17)
在GraphQL中返回错误的方法(至少在graphql-js中)是在resolve函数中抛出错误。由于HTTP状态代码特定于HTTP传输,而GraphQL不关心传输,因此您无法在那里设置状态代码。你可以做的是在你的解析函数中抛出一个特定的错误:
age: (person, args) => {
try {
return fetchAge(person.id);
} catch (e) {
throw new Error("Could not connect to age service");
}
}
GraphQL错误会在响应中发送到客户端,如下所示:
{
"data": {
"name": "John",
"age": null
},
"errors": [
{ "message": "Could not connect to age service" }
]
}
如果消息信息不足,您可以为GraphQL服务器创建一个包含状态代码的特殊错误类。要确保状态代码包含在您的响应中,您必须在创建中间件时指定formatError
函数:
app.use('/graphql', bodyParser.json(), graphqlExpress({
schema: myGraphQLSchema,
formatError: (err) => ({ message: err.message, status: err.status }),
}));
答案 1 :(得分:2)
spec最近增加了一个有关错误输出的信息:
GraphQL服务可以通过键扩展名提供错误的附加条目。如果设置了该条目,则其值必须具有一个映射。此项保留给实现者,用于为错误添加附加信息,但他们认为合适,并且对其内容没有附加限制。
现在,使用extensions
字段,您可以为errors
项自定义机器可读信息:
{
"errors": [
{
"message": "Name for character with ID 1002 could not be fetched.",
"locations": [ { "line": 6, "column": 7 } ],
"path": [ "hero", "heroFriends", 1, "name" ],
"extensions": {
"code": "CAN_NOT_FETCH_BY_ID",
"timestamp": "Fri Feb 9 14:33:09 UTC 2018"
}
}
]
}
Apollo-Server的最新版本与此功能兼容,请检出Here。
答案 2 :(得分:0)
仅是对Glenn的回答的补充,here是Graphql Spec的一部分,它定义了应如何处理错误。因此,要知道请求是否失败(或部分失败),可以检查响应根目录中的“错误”键。
答案 3 :(得分:0)
尝试了一下之后,我意识到缺少一些重要的细节。主要是,如果您有一个带有自定义字段的自定义错误对象,上述示例将使您能够读取自定义属性,因为看来自定义错误被强制转换为仅具有message属性的标准A
对象。
这是我的Error
函数的外观(请注意formatError
属性):
originalError
app.use('/graphql', auth.verifyAccess, graphqlHTTP((req, res) => {
return {
schema: makeExecutableSchema({
typeDefs: typeDefs,
resolvers: rootResolver
}),
graphiql: true,
formatError: (err) => ({
message: err.originalError.message || err.message,
code: err.originalError.code || 500
}),
}
}));
属性似乎总是被设置,但是作为一种保护措施,您可以使用lodash的originalError
属性。
我有一个名为get
APIError
在我的解析器中,我抛出诸如此类的异常:
class APIError extends Error {
constructor({ code, message }) {
const fullMsg = `${code}: ${message}`;
super(fullMsg);
this.code = code;
this.message = message;
}
}
export default APIError;
答案 4 :(得分:0)
我认为关于 graphql 和错误的讨论中缺少的一个问题是从 http 到 gql 的转换中的错误,这通常是 401 应该发生的地方。
在转换请求时,您应该将 Authorization 标头(或您使用的任何身份验证方法)转换为用户,如果无法通过身份验证,则应返回 HTTP 401 错误 - 这不是图表的一部分或api 的规范,只是用户是否可以被验证的问题。您甚至不必检查查询。
另一方面,403 错误很可能会出现在 gql 层(并且可能不会使用 http 状态代码,但这是另一个讨论),因为它可能非常特定于域,您必须知道查询决定是否禁止。
HTTP 403 状态可用于告诉用户他根本无法访问 gql api。
我们在 express/nestjs 中解决了这个问题,方法是在到达 graphql 层之前使用中间件来丰富用户的请求(可能未定义),或者如果用户无法通过身份验证则失败。如果您不提供凭据(或类似信息),我认为不应返回 401。