学习教程
内省

内省

¥Introspection

Learn how to query information about a GraphQL schema

询问 GraphQL 模式以获取有关其支持哪些功能的信息通常很有用。GraphQL 允许我们使用 自省系统 来执行此操作。

¥It’s often useful to ask a GraphQL schema for information about what features it supports. GraphQL allows us to do so using the introspection system.

自省查询是一种特殊的查询,可让你了解 GraphQL API 的模式,它们还有助于增强 GraphQL 开发工具。在此页面上,我们将学习如何运行不同的查询以了解有关底层模式的类型、字段和描述的更多信息。

¥Introspection queries are special kinds of queries that allow you to learn about a GraphQL API’s schema, and they also help power GraphQL development tools. On this page, we’ll learn how to run different queries to learn more about an underlying schema’s types, fields, and descriptions.

类型名称自省

¥Type name introspection

我们已经看到了 模式和类型页面 上的自省示例。查询返回 Union 类型的字段时,我们将 __typename 元字段直接包含在选择集中,以获取搜索查询返回的不同类型名称的字符串值。让我们再看一遍这个例子:

¥We have already seen an example of introspection on the Schemas and Types page. When querying a field that returned Union type, we included the __typename meta-field directly in a selection set to get the string value of the names of the different types returned by a search query. Let’s look at this example again:

Operation
Response

我们没有明确地将 __typename 字段添加到我们的 GraphQL API 中 - GraphQL 规范规定它必须由 GraphQL 实现提供给客户端。可以查询此字段以查找任何具有对象、接口或联合类型作为基础输出类型的字段。

¥We didn’t add the __typename field to our GraphQL API explicitly—the GraphQL specification says that it must be provided to clients by a GraphQL implementation. This field can be queried for any field with an Object, Interface, or Union type as the underlying output type.

架构自省

¥Schema introspection

自省可以做的不仅仅是在查询中提供类型名称。如果你为 GraphQL API 设计了类型系统,那么你可能已经知道可用的类型。但如果你没有设计它,你可以通过查询 __schema 字段来询问 GraphQL,该字段在 query 根操作类型上始终可用。

¥Introspection can do more than provide type names in a query. If you designed the type system for a GraphQL API, then you’ll likely already know what types are available. But if you didn’t design it, you can ask GraphQL by querying the __schema field, which is always available on the query root operation type.

现在让我们这样做,并询问星球大战架构中有哪些类型可用:

¥Let’s do so now and ask what types are available in the Star Wars schema:

Operation
Response

哇,种类真多啊!这些是什么?让我们将它们分组:

¥Wow, that’s a lot of types! What are they? Let’s group them:

  • 我们在类型系统中定义的类型:QueryMutationCharacterHumanEpisodeDroidLengthUnitFriendsConnectionFriendsEdgePageInfoReviewReviewInputStarshipSearchResult

    ¥Types that we defined in our type system: Query, Mutation, Character, Human, Episode, Droid, LengthUnit, FriendsConnection, FriendsEdge, PageInfo, Review, ReviewInput, Starship, and SearchResult

  • 类型系统提供的内置标量:BooleanFloatIDIntString

    ¥Built-in scalars that the type system provided: Boolean, Float, ID, Int, and String

  • 以双下划线开头的类型是自省系统的一部分:__Schema__Type__TypeKind__Field__InputValue__EnumValue__Directive__DirectiveLocation

    ¥Types preceded with a double underscore that are part of the introspection system: __Schema, __Type, __TypeKind, __Field, __InputValue, __EnumValue, __Directive, and __DirectiveLocation

现在,让我们尝试找出一个好的起点来开始探索可用的查询。当我们设计类型系统时,我们指定了所有查询将从什么类型开始;让我们向内省系统询问这个问题:

¥Now, let’s try to figure out a good place to start exploring what queries are available. When we designed our type system, we specified what type all queries would start at; let’s ask the introspection system about that:

Operation
Response

结果与我们在 类型系统部分 中所说的相符 - Query 类型是我们将开始的地方。请注意,这里的命名只是按照惯例;我们可以将 Query 类型命名为其他任何名称,如果我们指定它是查询的起始类型,它仍然会在这里返回。不过,将其命名为 Query 是一个有用的约定。

¥The result matches what we said in the type system section—that the Query type is where we will start. Note that the naming here was just by convention; we could have named our Query type anything else, and it still would have been returned here had we specified it was the starting type for queries. Naming it Query, though, is a useful convention.

检查一种特定类型通常很有用。我们先来看看 Droid 型:

¥It is often useful to examine one specific type. Let’s take a look at the Droid type:

Operation
Response

但如果我们想了解更多关于 Droid 的信息怎么办?例如,它是接口类型还是对象类型?

¥But what if we want to know more about Droid? For example, is it an Interface or Object type?

Operation
Response

kind 返回 __TypeKind Enum 类型,其中一个值是 OBJECT。如果我们询问 Character,我们会发现它是一个接口类型:

¥kind returns a __TypeKind Enum type, one of whose values is OBJECT. If we asked about Character instead we’d find that it is an Interface type:

Operation
Response

对象类型知道哪些字段可用很有用,所以让我们向内省系统询问有关 Droid 的信息:

¥It’s useful for an Object type to know what fields are available, so let’s ask the introspection system about Droid:

Operation
Response

这些是我们在 Droid 上定义的字段!

¥Those are the fields that we defined on Droid!

id 看起来有点奇怪,它没有该类型的名称。这是因为它是 NON_NULL 类型的封装器类型。如果我们在该字段的类型上查询 ofType,我们会在那里找到 ID 类型,告诉我们这是一个非空 ID。

¥id looks a bit weird there, it has no name for the type. That’s because it’s a wrapper type of kind NON_NULL. If we queried for ofType on that field’s type, we would find the ID type there, telling us this is a non-null ID.

同样,friendsappearsIn 都没有名称,因为它们是 LIST 封装类型。我们可以在这些类型上查询 ofType,这将告诉我们列表中有哪些类型:

¥Similarly, both friends and appearsIn have no name, since they are the LIST wrapper type. We can query for ofType on those types, which will tell us what types are inside the list:

Operation
Response

让我们以内省系统的一个功能作为结束,该功能对于工具特别有用;让我们向系统询问文档:

¥Let’s end with a feature of the introspection system particularly useful for tooling; let’s ask the system for documentation:

Operation
Response

如上所示,我们可以使用自省访问有关类型系统的文档,并创建文档浏览器或丰富的 IDE 体验。

¥As demonstrated above, we can access the documentation about the type system using introspection and create documentation browsers or rich IDE experiences.

这仅仅触及了内省系统的表面;我们可以查询枚举类型值、另一种类型实现的接口类型等等。我们甚至可以对内省系统本身进行内省。

¥This has just scratched the surface of the introspection system; we can query for Enum type values, what Interface types another type implements, and more. We can even introspect on the introspection system itself.

要查看符合规范的 GraphQL 查询自省系统在代码中实现的示例,你可以在参考实现中查看 src/type/introspection.ts

¥To see an example of a specification-compliant GraphQL query introspection system implemented in code, you can view src/type/introspection.ts in the reference implementation.

生产中的自省

¥Introspection in production

自省是 GraphQL 的一个有用功能,尤其是对于客户端开发者和工具而言。但是,对于仅用于你自己的应用的 API,通常在生产中不需要它 - 所需的操作通常在构建时嵌入到这些应用中,因此运行时自省是不必要的。

¥Introspection is a useful feature of GraphQL, especially for client developers and tooling. However, for APIs intended only for your own applications, it’s typically not needed in production—required operations are usually baked into these applications at build time, making runtime introspection unnecessary.

为了减少 API 的攻击面,在生产中禁用自省是很常见的。这通常是更广泛的 API 安全策略的一部分,该策略还可能包括身份验证和授权、操作安全列表(或一系列替代保护,例如深度限制、广度限制、别名限制、循环拒绝、成本分析等)、执行超时等。

¥Disabling introspection in production is common in order to reduce the API’s attack surface. This is often part of a broader API security strategy, which may also include authentication and authorization, operation safe-listing (or a range of alternative protections, such as depth-limiting, breadth-limiting, alias limits, cycle rejection, cost analysis, etc.), execution timeouts, and more.

后续步骤

¥Next steps

回顾我们学到的关于执行的知识:

¥To recap what we’ve learned about introspection:

  • 可以使用 __typename 元字段在对象、接口或联合类型的字段选择集中查询类型名称

    ¥Type names can be queried in a field selection set for an Object, Interface, or Union type using the __typename meta-field

  • 可以使用 query 根操作类型上的 __schema 字段查询有关 GraphQL 模式元素的信息

    ¥Information about the elements of a GraphQL schema can be queried using the __schema field on the query root operation type

  • 自省通常在生产环境中被禁用

    ¥Introspection is often disabled in production environments

现在你已经探索了 GraphQL 类型系统、如何从 API 查询数据以及请求的生命周期是什么样的,请转到 最佳实践 部分以了解有关在生产中运行 GraphQL 的更多信息。

¥Now that you’ve explored the GraphQL type system, how to query data from an API, and what the lifecycle of a request looks like, head over to the Best Practices section to learn more about running GraphQL in production.