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

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

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

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 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

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

如果先前的操作是管道解析器的 Before 映射模板,则$ctx.prev.result表示模板评估的输出,可供管道中的第一个函数使用。

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

如果前一个操作是最后一个函数,则$ctx.prev.result表示最后一个函数的输出,并可供管道解析器的 After 映射模板使用。

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授权的情况下,用户名的值是Amazon用户主体的值。如果您使用来自 Amazon Cognito 身份池的证书的 IAM 授权,我们建议您使用cognitoIdentityId

访问请求标头

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

单标题示例

假设您设置一个 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不会暴露里面的 cookie 标头$context.request.headers

访问请求的自定义域名

Amazon AppSync支持配置自定义域,您可以使用该域来访问您的 GraphQL 和 API 的实时终端节点。使用自定义域名发出请求时,您可以使用获取域名$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)。尽管片段未合并到选择集中,但行内片段会被保留,如以下示例所示。

注意

使用$utils.toJson() on 时context.info,默认情况下,selectionSetGraphQL和 retselectionSetList urn 的值不会序列化。

例如,如果您要解析以下查询的 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.arguments、、和$context.request.headers等属性中$context包含用户输入$context.identity$context.result$context.info.variables,因此必须注意在映射模板中清理其值。

由于映射模板代表 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. } }