GraphQL 操作名称

GraphQL Operation Name

当我在后端(即 Apollo)设置我的 GraphQL 定义时,定义操作名称有什么方法或好处吗?

例如,我有一个更新操作可以将枚举作为参数:

mutation {
  updateOrder(status: StatusEnum): Order
}

但我在想我可以为每个状态做特定的命名操作,后端解析器被连接到每个(然后知道“好的,我是取消解析器,我不需要关心一些枚举").

mutation {
  makeOrderCanceled(): Order
  makeOrderPending(): Order
  makeOrderComplete(): Order
}

resolvers = {
  makeOrderCanceled: () => {
    // don't need to infer the status from a param, in essence could 
    // just hardcode the enum here and prevent the API consumers from 
    // having to know about it.
  }
}

这很好,可能是我会做的。但这遗漏了操作名称。我读过它对日志记录很有用,并且作为实际 HTTP 请求中的一个字段出现。我明白了。但是,如果我作为后端开发人员定义我的类型、查询和变更,我能做些什么来帮助改进我的模式的意图和建议使用吗?例如,我能看到的最后一种方法是这样的:

mutation CancelOrder {
  updateOrder(status: "cancel"): Order   # this
  updateOrder(): Order                   # or this like the examples above
}

mutation CompleteOrder {
  updateOrder(status: "complete"): Order  # this
  updateOrder(): Order                    # or this like the examples above
}

问题

不,您不能在后端定义操作名称,因为操作是动态的,由 API 的消费者创建。我相信您在这里混合了概念。无论您决定构建您的架构(updateOrdermakeOrder****),您最终要说的是:

Here are the mutations that this server can handle, have fun!

您的消费者可以决定发出任意数量的不同查询,例如我可以很好地决定在一个操作中执行:

mutation TryToBreakAPI {
   makeOrderCanceled {
     id
   }
   makeOrderPending {
     id
   }
}

根据 graphql 规范,突变按顺序执行(与并行执行的查询相比),因此它将首先调用 makeOrderCanceled 解析器(及其子级),然后 makeOrderPending 解析器(及其子项)。

记录操作名称仍然是一个好主意,可以更轻松地调试私有 APIs,因为您可以要求您的前端工程师编写一个,这样如果查询失败,可以更容易地调试它的到来从。但这不是灵丹妙药,因此您通常也应该记录完整的查询(如果只是为了捕获一些可能试图以意想不到的方式使用您的 API 的潜在恶意行为者)。

有一些方法可以限制您的服务器可以接受的查询,这通常称为 query whitelisting 并且它的实现将取决于您使用的服务器(老实说,您甚至可以自己构建)。它通常包括对前端使用的每个查询执行 SHA256,并告诉后端仅接受散列为“已批准”散列之一的查询。