解析器映射模板上下文参考 - Amazon AppSync
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

解析器映射模板上下文参考

注意

我们现在主要支持 APPSYNC_JS 运行时环境及其文档。请考虑使用 APPSYNC_JS 运行时环境和此处的指南。

Amazon AppSync 定义了一组用于处理解析器映射模板的变量和函数。这样,就可以更轻松地通过 GraphQL 对数据进行逻辑操作。本文档将介绍这些函数,并提供使用模板的示例。

使用 $context

$context 变量是一个映射,它保留进行解析器调用的所有上下文信息。它具有以下结构:

{ "arguments" : { ... }, "source" : { ... }, "result" : { ... }, "identity" : { ... }, "request" : { ... }, "info": { ... } }
注意

如果您尝试按字典/映射条目(例如 context 中的条目)键访问该条目以检索值,Velocity 模板语言 (VTL) 允许您直接使用 <dictionary-element>.<key-name> 表示法。但是,这可能不适用于所有情况,例如当键名称具有特殊字符时(例如,下划线“_”)。建议您始终使用 <dictionary-element>.get("<key-name>") 表示法。

$context 映射中每个字段的定义如下所示:

$context 字段

arguments

包含该字段的所有 GraphQL 参数的映射。

identity

包含有关调用方的信息的对象。有关该字段结构的更多信息,请参阅身份

source

包含父字段解析的映射。

stash

存储区是一个在每个解析器和函数映射模板中提供的映射。同一存储区实例通过单个解析器生效。这意味着,您可以使用存储区来跨请求和响应映射模板以及管道解析器中的函数传递任意数据。存储区公开与 Java 映射数据结构相同的方法。

result

此解析器结果的容器。该字段仅适用于响应映射模板。

例如,如果要解析以下查询的 author 字段:

query { getPost(id: 1234) { postId title content author { id name } } }

那么在处理响应映射模板时,完整的 $context 变量可以是:

{ "arguments" : { id: "1234" }, "source": {}, "result" : { "postId": "1234", "title": "Some title", "content": "Some content", "author": { "id": "5678", "name": "Author Name" } }, "identity" : { "sourceIp" : ["x.x.x.x"], "userArn" : "arn:aws:iam::123456789012:user/appsync", "accountId" : "666666666666", "user" : "AIDAAAAAAAAAAAAAAAAAA" } }
prev.result

在管道解析器中执行的任何以前操作的结果。

如果上一个操作是管道解析器的之前映射模板,则 $ctx.prev.result 表示模板评估的输出,并提供给管道中的第一个函数。

如果上一个操作是第一个函数,则 $ctx.prev.result 表示第一个函数的输出,并且可供管道中的第二个函数使用。

如果上一个操作是最后一个函数,则 $ctx.prev.result 表示最后一个函数的输出,并提供给管道解析器的之后映射模板。

info

包含有关 GraphQL 请求的信息的对象。有关该字段的结构,请参阅信息

求同

identity 部分包含调用方的相关信息。此部分的形态取决于您的 Amazon AppSync API 的授权类型。

有关 Amazon AppSync 安全选项的更多信息,请参阅授权和身份验证

API_KEY 授权

不填充 identity 字段。

AWS_LAMBDA 授权

identity 包含 resolverContext 密钥,其中包含为请求授权的 Lambda 函数返回的相同 resolverContext 内容。

AWS_IAM 授权

identity 采用以下格式:

{ "accountId" : "string", "cognitoIdentityPoolId" : "string", "cognitoIdentityId" : "string", "sourceIp" : ["string"], "username" : "string", // IAM user principal "userArn" : "string", "cognitoIdentityAuthType" : "string", // authenticated/unauthenticated based on the identity type "cognitoIdentityAuthProvider" : "string" // the auth provider that was used to obtain the credentials }
AMAZON_COGNITO_USER_POOLS 授权

identity 采用以下格式:

{ "sub" : "uuid", "issuer" : "string", "username" : "string" "claims" : { ... }, "sourceIp" : ["x.x.x.x"], "defaultAuthStrategy" : "string" }

每个字段的定义如下所示:

accountId

调用方的 Amazon 账户 ID。

claims

用户拥有的声明。

cognitoIdentityAuthType

根据身份类型确定经过身份验证或未经身份验证。

cognitoIdentityAuthProvider

外部身份提供程序信息的逗号分隔列表,用于获取对请求进行签名时使用的凭证。

cognitoIdentityId

调用方的 Amazon Cognito 身份 ID。

cognitoIdentityPoolId

与调用方关联的 Amazon Cognito 身份池 ID。

defaultAuthStrategy

此调用方的默认授权策略(ALLOWDENY)。

issuer

令牌发布者。

sourceIp

Amazon AppSync 收到的调用方的源 IP 地址。如果请求不包含 x-forwarded-for 标头,则源 IP 值仅包含来自 TCP 连接的单个 IP 地址。如果请求中包含 x-forwarded-for 标头,那么源 IP 将是来自 x-forwarded-for 标头的 IP 地址列表,以及来自 TCP 连接的 IP 地址。

sub

经过验证的用户的 UUID。

user

IAM 用户。

userArn

IAM 用户的 Amazon 资源名称 (ARN)。

username

已验证的用户的用户名。对于 AMAZON_COGNITO_USER_POOLS 授权,用户名的值是 cognito:username 属性的值。对于 AWS_IAM 授权,username 值是 Amazon 用户主体的值。如果您将 IAM 授权与从 Amazon Cognito 身份池提供的凭证一起使用,我们建议您使用 cognitoIdentityId

访问请求标头

Amazon AppSync 支持从客户端传递自定义标头,并使用 $context.request.headers 在 GraphQL 解析器中访问这些标头。然后,您可以使用标头值执行操作,例如,将数据插入到数据源或进行授权检查。您可以在命令行中使用 $curl 将一个或多个请求标头与 API 密钥一起使用,如以下示例中所示:

单标头示例

假设您设置一个 custom 标头,值为 nadia,如下所示:

curl -XPOST -H "Content-Type:application/graphql" -H "custom:nadia" -H "x-api-key:<API-KEY-VALUE>" -d '{"query":"mutation { createEvent(name: \"demo\", when: \"Next Friday!\", where: \"Here!\") {id name when where description}}"}' https://<ENDPOINT>/graphql

然后可使用 $context.request.headers.custom 访问它。例如,对于 DynamoDB,它可能位于以下 VTL 中:

"custom": $util.dynamodb.toDynamoDBJson($context.request.headers.custom)

多标头示例

您还可以在一个请求中传递多个标头,并在解析器映射模板中访问它们。例如,如果为 custom 标头设置了两个值:

curl -XPOST -H "Content-Type:application/graphql" -H "custom:bailey" -H "custom:nadia" -H "x-api-key:<API-KEY-VALUE>" -d '{"query":"mutation { createEvent(name: \"demo\", when: \"Next Friday!\", where: \"Here!\") {id name when where description}}"}' https://<ENDPOINT>/graphql

它们可以作为一个数组访问,例如 $context.request.headers.custom[1]

注意

Amazon AppSync 不会在 $context.request.headers 中公开 Cookie 标头。

访问请求自定义域名

Amazon AppSync 支持配置自定义域,您可以使用该域访问 API 的 GraphQL 和实时终端节点。在使用自定义域名发出请求时,您可以使用 $context.request.domainName 获取域名。

在使用默认 GraphQL 终端节点域名时,值为 null

Info

info 部分包含有关 GraphQL 请求的信息。该部分采用以下格式:

{ "fieldName": "string", "parentTypeName": "string", "variables": { ... }, "selectionSetList": ["string"], "selectionSetGraphQL": "string" }

每个字段的定义如下所示:

fieldName

当前正在解析的字段的名称。

parentTypeName

当前正在解析的字段的父类型的名称。

variables

保留传递到 GraphQL 请求的所有变量的映射。

selectionSetList

GraphQL 选择集中字段的列表表示形式。具有别名的字段仅按别名进行引用,而不按字段名称进行引用。以下示例对此详细进行了介绍。

selectionSetGraphQL

选择集的字符串表示形式,格式为 GraphQL 架构定义语言 (SDL)。尽管片段不会合并到选择集中,但会保留内联片段,如以下示例中所示。

注意

默认情况下,在 context.info 上使用 $utils.toJson() 时,不会序列化 selectionSetGraphQLselectionSetList 返回的值。

例如,如果您要解析以下查询的 getPost 字段:

query { getPost(id: $postId) { postId title secondTitle: title content author(id: $authorId) { authorId name } secondAuthor(id: "789") { authorId } ... on Post { inlineFrag: comments: { id } } ... postFrag } } fragment postFrag on Post { postFrag: comments: { id } }

那么,在处理映射模板时可用的完整 $context.info 变量可以是:

{ "fieldName": "getPost", "parentTypeName": "Query", "variables": { "postId": "123", "authorId": "456" }, "selectionSetList": [ "postId", "title", "secondTitle" "content", "author", "author/authorId", "author/name", "secondAuthor", "secondAuthor/authorId", "inlineFragComments", "inlineFragComments/id", "postFragComments", "postFragComments/id" ], "selectionSetGraphQL": "{\n getPost(id: $postId) {\n postId\n title\n secondTitle: title\n content\n author(id: $authorId) {\n authorId\n name\n }\n secondAuthor(id: \"789\") {\n authorId\n }\n ... on Post {\n inlineFrag: comments {\n id\n }\n }\n ... postFrag\n }\n}" }

selectionSetList 仅公开属于当前类型的字段。如果当前类型是接口或联合,则仅公开属于该接口的选定字段。例如,给定以下架构:

type Query { node(id: ID!): Node } interface Node { id: ID } type Post implements Node { id: ID title: String author: String } type Blog implements Node { id: ID title: String category: String }

以及以下查询:

query { node(id: "post1") { id ... on Post { title } ... on Blog { title } } }

如果在进行 Query.node 字段解析时调用 $ctx.info.selectionSetList,则仅公开 id

"selectionSetList": [ "id" ]

清理输入

应用程序必须对不可信的输入进行清理,以防止任何外部方在应用程序的预期用途之外使用该应用程序。由于 $context 包含 $context.arguments$context.identity$context.result$context.info.variables$context.request.headers 等属性中的用户输入,因此,务必谨慎在映射模板中清理它们的值。

由于映射模板代表 JSON,因此输入清理采用从表示用户输入的字符串转义 JSON 保留字符的形式。将 JSON 保留字符放入映射模板时,最佳做法是使用 $util.toJson() 实用程序从敏感字符串值转义 JSON 保留字符。

例如,在以下 Lambda 请求映射模板中,由于我们访问了不安全的客户输入字符串 ($context.arguments.id),因此,我们使用 $util.toJson() 将其包装起来,以防止未转义的 JSON 字符破坏 JSON 模板。

{ "version": "2017-02-28", "operation": "Invoke", "payload": { "field": "getPost", "postId": $util.toJson($context.arguments.id) } }

下面的映射模板与之相反,我们直接插入 $context.arguments.id 而不进行清理。这不适用于包含未转义引号或其他 JSON 保留字符的字符串,并且可能使您的模板很容易失败。

## DO NOT DO THIS { "version": "2017-02-28", "operation": "Invoke", "payload": { "field": "getPost", "postId": "$context.arguments.id" ## Unsafe! Do not insert $context string values without escaping JSON characters. } }