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

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

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

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

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

info

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

Identity

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

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

API_KEY 授权

identity 字段未填充。

AWS_LAMBDA 授权

这些区域有:identity包含resolverContextkey,包含相同的resolverContext由授权请求的 Lambda 函数返回的内容。

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

接收的调用方的源 IP 地址Amazon AppSync. 如果请求中不包含 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授权,值username是的价值Amazon用户主体。建议使用cognitoIdentityId如果你在使用IAM使用从 Amazon Cognito 身份池中出售的凭证进行授权。

访问请求标头

Amazon支持从客户端传递自定义标头,还支持使用在您的 GraphQL 解析 AppSync 序中访问它们。$context.request.headers. 您可以使用标头值进行操作,如将数据插入数据源,还能进行授权检查。以下示例展示了如何通过命令行结合使用 $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 访问它。例如,它可能在的以下 VTL DynamoDB:

"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中的 cookie 标头不会公开$context.request.headers.

Info

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

info 具有以下形态:

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

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

fieldName

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

parentTypeName

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

variables

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

selectionSetList

GraphQL 选择集中字段的列表表示形式。具有别名的字段只会通过别名(而不是字段名称)引用。以下示例对此详细进行了介绍。

selectionSetGraphQL

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

注意:使用$utils.toJson()上的context.info,返回的值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 } } }

打电话时$ctx.info.selectionSetListQuery.node仅限现场分辨率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. } }