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

解析程序映射模板上下文参考

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

使用 $context

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

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

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

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

arguments

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

identity

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

source

包含父字段解析的映射。

stash

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

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" : "123456789012", "user" : "AIDAAAAAAAAAAAAAAAAAA" } }
prev.result

它表示在管道解析程序中执行的任何先前操作的结果。如果上一个操作是管道解析程序请求映射模板,则 $ctx.prev.result 表示模板评估的输出,并且可供管道中的第一个函数使用。如果上一个操作是第一个函数,则 $ctx.prev.result 表示第一个函数的输出,并且可供管道中的第二个函数使用。如果上一个操作是最后一个函数,则 $ctx.prev.result 表示第一个函数的输出,并且可供管道解析程序响应映射模板使用。

info

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

求同

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

有关此部分内容以及如何使用的更多信息,请参阅安全

API_KEY 授权

identity 字段未填充。

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

调用者的 AWS 账户 ID。

claims

用户拥有的声明。

cognitoIdentityAuthType

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

cognitoIdentityAuthProvider

外部身份提供商,用于获取用于为请求签名的凭证。

cognitoIdentityId

调用者的 Amazon Cognito 身份 ID。

cognitoIdentityPoolId

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

defaultAuthStrategy

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

issuer

令牌发布者。

sourceIp

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

sub

经过验证的用户的 UUID。

user

IAM 用户。

userArn

IAM 角色的 ARN。

username

已验证的用户的用户名。对于 AMAZON_COGNITO_USER_POOLS 授权,用户名的值是 cognito:username 属性的值。对于 AWS_IAM 授权,用户名的值是 AWS 用户委托人的值。如果您使用的 AWS IAM 授权由 Amazon Cognito 身份池提供凭证,我们建议您使用 cognitoIdentityId

访问请求标头

AWS 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]"

注意:AWS AppSync 不会公开 $context.request.headers 中的 cookie 标头。

Info

info 部分包含有关 GraphQL 请求的信息。

info 具有以下形态:

{ "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}" }

清理输入

应用程序必须对不可信的输入进行清理,以防止任何外部方在应用程序的预期用途之外使用该应用程序。由于 $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": $utils.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. } }