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

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

解析器映射模板更改日志

注意

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

解析器和函数映射模板已版本化。映射模板版本(例如 2018-05-29)规定了以下内容:* 请求模板提供的数据源请求配置的预期形状 * 请求映射模板和响应映射模板的执行行为

版本使用 YYYY-MM-DD 格式表示,较晚的日期对应于更新版本。该页面列出了 Amazon AppSync 中当前支持的映射模板版本之间的差异。

每个版本矩阵的数据源操作可用性

支持的操作/版本 2017-02-28 2018-05-29

Amazon Lambda Invoke

Amazon Lambda BatchInvoke

None Datasource

Amazon OpenSearch GET

Amazon OpenSearch POST

Amazon OpenSearch PUT

Amazon OpenSearch DELETE

Amazon OpenSearch GET

DynamoDB GetItem

DynamoDB Scan

DynamoDB Query

DynamoDB DeleteItem

DynamoDB PutItem

DynamoDB BatchGetItem

DynamoDB BatchPutItem

DynamoDB BatchDeleteItem

HTTP

Amazon RDS

:函数中目前仅支持 2018-05-29 版本。

更改单位解析器映射模板上的版本

对于单位解析器,将版本指定为请求映射模板正文的一部分。要更新版本,只需将 version 字段更新为新版本。

例如,要更新 Amazon Lambda 模板中的版本:

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

您需要将版本字段从 2017-02-28 更新为 2018-05-29,如下所示:

{ "version": "2018-05-29", ## Note the version "operation": "Invoke", "payload": { "field": "getPost", "arguments": $utils.toJson($context.arguments) } }

更改函数上的版本

对于函数,将版本指定为函数对象上的 functionVersion 字段。要更新版本,只需更新 functionVersion注意:目前,函数仅支持 2018-05-29

以下是用于更新现有函数版本的 CLI 命令的示例:

aws appsync update-function \ --api-id REPLACE_WITH_API_ID \ --function-id REPLACE_WITH_FUNCTION_ID \ --data-source-name "PostTable" \ --function-version "2018-05-29" \ --request-mapping-template "{...}" \ --response-mapping-template "\$util.toJson(\$ctx.result)"

注意:建议从函数请求映射模板中省略版本字段,因为它不会被接受。如果您在函数请求映射模板中指定了一个版本,则该版本值将由 functionVersion 字段的值覆盖。

2018-05-29

行为更改

  • 如果数据源调用结果为 null,则执行响应映射模板。

  • 如果数据源调用产生了错误,现在由您来处理该错误,响应映射模板评估结果将始终放置在 GraphQL 响应 data 块中。

Reasoning

  • null 调用结果具有意义,在某些应用程序使用案例中,我们可能希望以自定义方式处理 null 结果。例如,应用程序可能会检查 Amazon DynamoDB 表中是否存在记录以执行某些授权检查。在这种情况下,null 调用结果意味着用户可能未获得授权。现在,执行响应映射模板可以引发未经授权的错误。此行为向 API 设计器提供了更大的控制。

给定以下响应映射模板:

$util.toJson($ctx.result)

之前使用 2017-02-28,如果 $ctx.result 返回 null,则未执行响应映射模板。利用 2018-05-29,我们现在可以处理这种情况。例如,我们可以选择引发授权错误,如下所示:

# throw an unauthorized error if the result is null #if ( $util.isNull($ctx.result) ) $util.unauthorized() #end $util.toJson($ctx.result)

注:从数据源返回的错误有时并不是致命的,或者甚至是预期的,这就是应向响应映射模板提供处理调用错误并决定是否忽略它、重新引发它或引发不同的错误的灵活性。

给定以下响应映射模板:

$util.toJson($ctx.result)

以前,使用 2017-02-28,如果出现调用错误,则会评估响应映射模板,并自动将结果放入 GraphQL 响应的 errors 块中。利用 2018-05-29,我们现在可以选择如何处理错误,重新引发错误、引发不同的错误,或者在返回数据时追加错误。

重新引发调用错误

在以下响应模板中,我们引发了从数据源返回的同一错误。

#if ( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)

如果出现调用错误(例如,出现 $ctx.error),则响应如下所示:

{ "data": { "getPost": null }, "errors": [ { "path": [ "getPost" ], "errorType": "DynamoDB:ConditionalCheckFailedException", "message": "Conditional check failed exception...", "locations": [ { "line": 5, "column": 5 } ] } ] }

引发不同的错误

在以下响应模板中,我们在处理从数据源返回的错误之后引发了自己的自定义错误。

#if ( $ctx.error ) #if ( $ctx.error.type.equals("ConditionalCheckFailedException") ) ## we choose here to change the type and message of the error for ConditionalCheckFailedExceptions $util.error("Error while updating the post, try again. Error: $ctx.error.message", "UpdateError") #else $util.error($ctx.error.message, $ctx.error.type) #end #end $util.toJson($ctx.result)

如果出现调用错误(例如,出现 $ctx.error),则响应如下所示:

{ "data": { "getPost": null }, "errors": [ { "path": [ "getPost" ], "errorType": "UpdateError", "message": "Error while updating the post, try again. Error: Conditional check failed exception...", "locations": [ { "line": 5, "column": 5 } ] } ] }

追加错误以返回数据

在以下响应模板中,我们追加从数据源返回的同一错误,同时将数据返回到响应中。这也称为部分响应。

#if ( $ctx.error ) $util.appendError($ctx.error.message, $ctx.error.type) #set($defaultPost = {id: "1", title: 'default post'}) $util.toJson($defaultPost) #else $util.toJson($ctx.result) #end

如果出现调用错误(例如,出现 $ctx.error),则响应如下所示:

{ "data": { "getPost": { "id": "1", "title: "A post" } }, "errors": [ { "path": [ "getPost" ], "errorType": "ConditionalCheckFailedException", "message": "Conditional check failed exception...", "locations": [ { "line": 5, "column": 5 } ] } ] }

2017-02-28 迁移到 2018-05-29

2017-02-28 迁移到 2018-05-29 非常简单。更改解析器请求映射模板或函数版本对象上的版本字段。但请注意,2018-05-29 执行的行为与 2017-02-28 的不同,此处概述了更改。

2017-02-282018-05-29 保留相同的执行行为

在某些情况下,在执行 2018-05-29 版本的模板时,可以保留与 2017-02-28 版本相同的执行行为。

示例:DynamoDB PutItem

给定以下 2017-02-28 DynamoDB PutItem 请求模板:

{ "version" : "2017-02-28", "operation" : "PutItem", "key": { "foo" : ... typed value, "bar" : ... typed value }, "attributeValues" : { "baz" : ... typed value }, "condition" : { ... } }

以及以下响应模板:

$util.toJson($ctx.result)

迁移到 2018-05-29 会更改这些模板,如下所示:

{ "version" : "2018-05-29", ## Note the new 2018-05-29 version "operation" : "PutItem", "key": { "foo" : ... typed value, "bar" : ... typed value }, "attributeValues" : { "baz" : ... typed value }, "condition" : { ... } }

更改响应模板,如下所示:

## If there is a datasource invocation error, we choose to raise the same error ## the field data will be set to null. #if($ctx.error) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #end ## If the data source invocation is null, we return null. #if($util.isNull($ctx.result)) #return #end $util.toJson($ctx.result)

现在,您有责任处理错误,我们选择使用从 DynamoDB 返回的 $util.error() 来引发同一错误。您可以调整此代码段以将映射模板转换为 2018-05-29,请注意,如果您的响应模板不同,则必须考虑执行行为更改。

示例:DynamoDB GetItem

给定以下 2017-02-28 DynamoDB GetItem 请求模板:

{ "version" : "2017-02-28", "operation" : "GetItem", "key" : { "foo" : ... typed value, "bar" : ... typed value }, "consistentRead" : true }

以及以下响应模板:

## map table attribute postId to field Post.id $util.qr($ctx.result.put("id", $ctx.result.get("postId"))) $util.toJson($ctx.result)

迁移到 2018-05-29 会更改这些模板,如下所示:

{ "version" : "2018-05-29", ## Note the new 2018-05-29 version "operation" : "GetItem", "key" : { "foo" : ... typed value, "bar" : ... typed value }, "consistentRead" : true }

更改响应模板,如下所示:

## If there is a datasource invocation error, we choose to raise the same error #if($ctx.error) $util.error($ctx.error.message, $ctx.error.type) #end ## If the data source invocation is null, we return null. #if($util.isNull($ctx.result)) #return #end ## map table attribute postId to field Post.id $util.qr($ctx.result.put("id", $ctx.result.get("postId"))) $util.toJson($ctx.result)

2017-02-28 版本中,如果数据源调用是 null,则表示 DynamoDB 表中没有与我们的键匹配的项目,响应映射模板将不会执行。在大多数情况下,这都是可行的,但如果您期望 $ctx.result 不是 null,则现在必须处理该情况。

2017-02-28

特性

  • 如果数据源调用结果为 null,则不会执行响应映射模板。

  • 如果数据源调用产生了错误,则将执行响应映射模板,并将评估结果放入 GraphQL 响应 errors.data 块中。