学习教程
验证

验证

¥Validation

Learn how GraphQL validates operations using a schema

在此页面上,我们将探索 GraphQL 请求生命周期中的一个重要阶段,称为 validation。请求必须在语法上正确才能运行,但在根据 API 的架构进行检查时也应该有效。

¥On this page, we’ll explore an important phase in the lifecycle of a GraphQL request called validation. A request must be syntactically correct to run, but it should also be valid when checked against the API’s schema.

实际上,当 GraphQL 操作到达服务器时,首先解析文档,然后使用类型系统进行验证。这允许服务器和客户端在创建无效查询时有效地通知开发者,而无需依赖运行时检查。一旦操作经过验证,它可以在服务器上为 executed,并且响应将传递给客户端。

¥In practice, when a GraphQL operation reaches the server, the document is first parsed and then validated using the type system. This allows servers and clients to effectively inform developers when an invalid query has been created, without relying on runtime checks. Once the operation is validated, it can be executed on the server and a response will be delivered to the client.

验证示例

¥Validation examples

GraphQL 规范描述了请求被视为有效必须满足的详细条件。在接下来的部分中,我们将介绍 GraphQL 操作中可能出现的几个常见验证问题的示例。

¥The GraphQL specification describes the detailed conditions that must be satisfied for a request to be considered valid. In the sections that follow, we’ll look at a few examples of common validation issues that may occur in GraphQL operations.

请求不存在的字段

¥Requesting non-existent fields

当我们查询字段时,该字段必须在相关类型上定义。由于 hero 返回 Character 类型,因此其选择集可能仅请求 Character 类型的字段;Character 没有 favoriteSpaceship 字段,因此此查询无效:

¥When we query for a field, the field must be defined on the relevant type. As hero returns a Character type, its selection set may only request the Character type’s fields; Character does not have a favoriteSpaceship field, so this query is invalid:

Operation
Response

选择集和叶字段

¥Selection sets and leaf fields

每当我们查询字段并且它返回除标量或枚举类型以外的内容时,我们都需要指定我们想要从字段(“选择集”)返回什么数据。hero 查询字段返回 Character,我们已经看到了在其上请求 nameappearsIn 等字段的示例。如果我们省略这些叶字段选择,则查询将无效:

¥Whenever we query for a field and it returns something other than a Scalar or Enum type, we need to specify what data we want to get back from the field (a “selection set”). The hero query field returns a Character, and we’ve already seen examples that request fields like name and appearsIn on it. If we omit those leaf field selections, then the query will not be valid:

Operation
Response

类似地,查询标量或枚举的字段没有意义,因此将选择集添加到叶字段将使查询无效:

¥Similarly, querying fields of a scalar or enum doesn’t make sense, therefore adding a selection set to a leaf field will make the query invalid:

Operation
Response

输出抽象类型的字段缺少片段

¥Missing fragments for fields that output abstract types

之前,有人指出查询只能请求相关类型的字段。因此,当我们查询返回 Characterhero 时,我们只能请求存在于 Character 接口类型上的字段。但是,如果我们想查询 R2-D2 的主要功能会发生什么?

¥Earlier, it was noted that a query can only ask for fields on the type in question. So when we query for hero which returns a Character, we can only request fields that exist on the Character Interface type. What happens if we want to query for R2-D2’s primary function, though?

Operation
Response

该查询无效,因为 primaryFunction 不是 Character 接口类型定义的共享字段之一。我们需要某种方式来表明,如果 CharacterDroid,我们希望获取 primaryFunction,否则忽略该字段。我们可以使用 fragments 来做到这一点。通过设置在 Droid 上定义的片段并将其包含在选择集中,我们确保仅在定义它的地方查询 primaryFunction

¥That query is invalid, because primaryFunction is not one of the shared fields defined by the Character Interface type. We want some way of indicating that we wish to fetch primaryFunction if the Character is a Droid, and to ignore that field otherwise. We can use the fragments to do this. By setting up a fragment defined on Droid and including it in the selection set, we ensure that we only query for primaryFunction where it is defined:

Operation
Response

这个查询是有效的,但是有点冗长;当我们多次使用命名片段时,上面的命名片段很有价值,但我们只使用了一次。我们可以使用 内联片段;而不是使用命名片段这仍然允许我们指示我们正在查询的类型,但无需命名单独的片段:

¥This query is valid, but it’s a bit verbose; named fragments were valuable above when we used them multiple times, but we’re only using this one once. Instead of using a named fragment, we can use an inline fragment; this still allows us to indicate the type we are querying on, but without naming a separate fragment:

Operation
Response

循环片段扩展

¥Cyclic fragment spreads

首先,让我们进行一个复杂的有效查询。这是一个嵌套查询,但重复的字段被分解为一个片段:

¥To start, let’s take a complex valid query. This is a nested query, but with the duplicated fields factored out into a fragment:

Operation
Response

以下是上述查询的替代方法,尝试使用递归而不是显式的三层嵌套。这个新查询无效,因为片段不能引用自身(直接或间接),因为结果循环可能会产生无界结果!

¥The following is an alternative to the above query, attempting to use recursion instead of the explicit three levels of nesting. This new query is invalid because a fragment cannot refer to itself (directly or indirectly) since the resulting cycle could create an unbounded result!

Operation
Response

这只是验证系统的表面;有许多验证规则可以确保 GraphQL 操作在语义上有意义。规范在 验证部分 中更详细地介绍了此主题,参考实现中的验证目录 包含实现符合规范的 GraphQL 验证器的代码。

¥This has just scratched the surface of the validation system; there are a number of validation rules in place to ensure that a GraphQL operation is semantically meaningful. The specification goes into more detail about this topic in the validation section, and the validation directory in the reference implementation contains code implementing a specification-compliant GraphQL validator.

验证错误

¥Validation errors

正如我们在上面的示例中所看到的,当 GraphQL 服务器在请求中遇到验证错误时,它将返回有关响应的 errors 键中发生的情况的信息。具体来说,当 GraphQL 检测到文档中的验证问题时,它会在执行开始之前引发请求错误,这意味着响应中不会包含任何部分数据。

¥As we have seen in the examples above, when a GraphQL server encounters a validation error in a request, it will return information about what happened in the errors key of the response. Specifically, when GraphQL detects a validation issue in a document, it raises a request error before execution begins, meaning that no partial data will be included in the response.

由于 GraphQL 规范要求所有实现都根据架构验证传入的请求,因此开发者无需编写特定的运行时逻辑来手动处理这些验证问题。

¥And because the GraphQL specification requires all implementations to validate incoming requests against the schema, developers won’t need to write specific runtime logic to handle these validation issues manually.

后续步骤

¥Next steps

回顾一下我们对订阅的了解:

¥To recap what we’ve learned about validation:

  • 要执行,请求必须包含语法正确的文档,该文档在与架构检查时被视为有效

    ¥To be executed, requests must include a syntactically correct document that is considered valid when checked against the schema

  • 规范要求实现检查传入请求是否包含有效的字段选择、正确的片段使用等

    ¥The specification requires implementations check incoming requests contain valid field selections, correct fragment usage, and more

  • 当发生验证问题时,服务器将引发请求错误并向客户端返回有关发生情况的信息;字段执行将不会启动

    ¥When a validation issue occurs, the server will raise a request error and return to the client information about what happened; field execution will not start

转到 执行 页面以了解 GraphQL 如何在验证步骤成功完成后为请求中的每个字段提供数据。

¥Head over to the Execution page to learn how GraphQL provides data for each field in a request after the validation step successfully completes.