如何在 GraphQL 中包含突变请求元数据?
Posted
技术标签:
【中文标题】如何在 GraphQL 中包含突变请求元数据?【英文标题】:How to include mutation request metadata in GraphQL? 【发布时间】:2019-02-05 15:02:27 【问题描述】:我正在使用 API 后端从头开始构建 GraphQL 服务器,以替换 REST API 服务器。目前,现有 API 服务器中的一些请求,主要是在 GraphQL 中将发生突变的 Create / Update 请求,包括客户端使用的请求 id。此请求 ID 是关于请求本身的元数据,而不是域资源的一部分。
我的问题是如何在 GraphQL 查询和突变中建模/包含请求元数据?到目前为止,我唯一的解决方案是创建一个请求类型,其他类型可以作为字段包含在内,因此请求数据可以包含在突变返回类型中。但是我不喜欢这种方法,因为它将请求数据混合到我的域类型中,这非常违背 GraphQL 的精神。是否有一种可接受的方式来传递“任意”,例如GraphQL 中的查询或突变响应中的非域类型数据?
示例 - 我想避免的:
type UserType
id: ID
name: String
request: RequestType // mixing request data in with domain type of User
type RequestType
id: ID
更新
对于其他对此问题感兴趣的人,根据此处的响应,我认为 GraphQL extensions
键是向 GraphQL 响应添加任意数据而不使数据成为数据图的一部分的好选择。在 Express-GraphQL 中,可以在此处找到有关向响应添加扩展键的文档:https://github.com/graphql/express-graphql#providing-extensions。这里有一个很好的扩展概述:https://marmelab.com/blog/2017/09/06/dive-into-graphql-part-iii-building-a-graphql-server-with-nodejs.html#server-logging
也就是说,如果请求元数据在概念上是域数据的一部分,那么按照下面 Kashif 的建议创建嵌入域类型的 ResponseType 可能是正确的方法。
【问题讨论】:
【参考方案1】:这种元元素通常在每个请求的 HEADERS 中传递。然后你就可以在你的 GraphQL 服务器中随意处理这些了
例如。
//Request Headers
...
X-Request-Id: <Your_Request_Id>
...
更新
标头可以双向工作,因此在客户端上使用它们也不会有任何问题。需要时将它们从响应中拉出来。
但是,如果您真的想要突变响应中的 requestId,那么它就是您域的一部分。自定义响应类型并没有错,许多现有的 GraphQL api 确实有一个自定义响应类型,例如 LoginResponse
、RegisterResponse
,它会包裹您的域对象,但还会在 meta
字段中包含额外的内容
【讨论】:
感谢 Kashif,问题是没有将请求 ID 从后端获取到 GraphQL,而是从 GraphQL 获取到客户端。我将使用 React-Apollo 作为客户端。我需要通过 React Apollo 发送给客户端的突变/查询中传递的所有响应数据。所以问题更多的是如何在 GraphQL 突变模式中对请求元数据进行建模,这样我就不必将它混合到我的域类型中 标题是双向的。所以在客户端上使用它们也不应该有任何问题。只需在需要时从响应中取出它们即可。 感谢 Kashif 的更新。当与 Apollo 客户端后件结合使用时,标头的想法似乎是一个不错的选择,但我也喜欢以更封装的方式解决问题的响应类型,将所有数据保持在 GraphQL 模式中处理,但不会污染不相关字段的类型。所有值得思考的好食物【参考方案2】:由于 GraphQL 被设计为与协议无关,因此您应该使用所选协议的元数据模式。如果您使用的是 HTTP,则应传递标头。如果您使用的是 WS/STOMP/MQTT/AMQP,您可以在每个帧中包含元数据。
另外,GraphQL 有一个extensions protocol。您可以在扩展对象中的响应中添加request-id
。 Apollo 使用扩展来进行缓存、遥测等。
我们已经在生产环境中使用 GraphQL 大约一年了,我们犯了将元数据添加到 GraphQL 的错误,并且很难管理。不要失去您正在使用的协议的功能所带来的好处。
【讨论】:
感谢赛斯的反馈,很高兴听到其他人的试验和错误的结论。我认为这可能是一个不错的选择 - 将元数据添加到请求标头中,然后编写一些 Apollo 客户端后件来检查标头并将其注入响应中,可能是这样的:github.com/benawad/slack-clone-client/blob/…。我一定会进一步探索这条道路。以上是关于如何在 GraphQL 中包含突变请求元数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Stripe Checkout 仅客户端实现中包含元数据?
如何在 Dropzone 上传请求的标头中包含 CSRF 令牌?
请求在 Graphql 解析器中未定义,但在中间件中包含一些值。 (节点,快递)