如何使用 Apollo Server 2.0 GraphQL 将来自架构指令的信息作为返回的数据包含在内?



我正在使用架构指令对字段进行授权。Apollo 服务器在解析器返回后调用指令。因此,指令无法访问输出,因此当授权失败时,如果没有复杂的解决方法抛出错误,我就无法包含用户的相关信息,无论查询是否请求它们,最终总是返回错误数据。

我希望有人比我更了解 Apollo 的内部结构,并可以指出我可以在哪里插入指令中的正确信息,这样我就不必破坏 GraphQL 的标准功能。

我尝试将我的输出包含在上下文中,但尽管指令具有访问权限,但这不起作用,因为数据已经从解析器返回,之后不需要上下文版本。

截至目前,我在带有代码DIRECTIVE_ERROR的指令中抛出了一个自定义错误,并包含我想返回给用户的消息。在 formatResponse 函数中,我查找指令错误,并通过将它们传输到数据的内部错误数组来过滤错误数组。我知道formatResponse不是用来修改数据内容的,但据我所知,这是我唯一可以访问我需要的东西的地方。同样令人沮丧的是,响应中的错误对象不包括错误中的所有字段。

type User implements Node {
id: ID!
email: String @requireRole(requires: "error")
}
type UserError implements Error {
path: [String!]!
message: String!
}
type UserPayload implements Payload {
isSuccess: Boolean!
errors: [UserError]
data: User
}
type UserOutput implements Output {
isSuccess: Boolean!
payload: [UserPayload]
}
/**
* All output responses should be of format:
* {
*  isSuccess: Boolean
*  payload: {
*    isSuccess: Boolean
*    errors: {
*      path: [String]
*      message: String
*    }
*    data: [{Any}]
*  }
* }
*/
const formatResponse = response => {
if (response.errors) {
response.errors = response.errors.filter(error => {
// if error is from a directive, extract into errors
if (error.extensions.code === "DIRECTIVE_ERROR") {
const path = error.path;
const resolverKey = path[0];
const payloadIndex = path[2];
// protect from null
if (response.data[resolverKey] == null) {
response.data[resolverKey] = {
isSuccess: false,
payload: [{ isSuccess: false, errors: [], data: null }]
};
} else if (
response.data[resolverKey].payload[payloadIndex].errors == null
) {
response.data[resolverKey].payload[payloadIndex].errors = [];
}
// push error into data errors array
response.data[resolverKey].payload[payloadIndex].errors.push({
path: [path[path.length - 1]],
message: error.message,
__typename: "DirectiveError"
});
} else {
return error;
}
});
if (response.errors.length === 0) {
return { data: response.data };
}
}
return response;
};

我对阿波罗行动顺序的理解是:

解析器返回
根据查询参数筛选的数据数据?
指令在对象/字段上调用,其中应用
的数据根据查询参数过滤?
格式响应有机会修改输出
格式错误有机会修改错误
返回客户端

我想要的是不必在指令中抛出错误,以便通过在 formatResponse 中提取信息来创建要传递给用户的信息。预期结果是客户端仅接收它请求的字段,但当前方法会破坏它并返回数据错误和所有字段,无论客户端是否请求它们。

您可以使用 destruct 注入它:

const { SchemaDirectiveVisitor } = require("apollo-server-express");
const { defaultFieldResolver } = require("graphql");
const _ = require("lodash");
class AuthDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const { resolve = defaultFieldResolver } = field;
field.resolve = async function (parent, args, context, info) {
// You could e.g get something from the header
//
// The verification below its necessary because
// my application runs locally and on Serverless
const authorization = _.has(context, "req")
? context.req.headers.authorization
: context.headers.Authorization;
return resolve.apply(this, [
parent,
args,
{
...context,
user: { authorization, name: "", id: "" }
},
info,
]);
};
}
}

然后在解析器上,您可以通过context.user.

最新更新