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

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

Lambda 的解析程序映射模板参考

您可以使用AmazonAppSync 解析器映射模板Amazon Lambda调整来自的请求Amazon对于位于您账户中的 Lambda 函数的 AppSync 函数以及从 Lambda 函数返回到的响应AmazonAppSync。您还可以使用映射模板向提供提示:AmazonAppSync 介绍要调用的操作的性质。本节介绍用于支持的 Lambda 操作的不同映射模板。

请求映射模板

Lambda 请求映射模板相当简单,允许尽可能多的上下文信息传递到 Lambda 函数。

{ "version": string, "operation": Invoke|BatchInvoke, "payload": any type }

下面是 Lambda 请求映射模板的 JSON 架构表示形式(解析后)。

{ "definitions": {}, "$schema": "https://json-schema.org/draft-06/schema#", "$id": "https://aws.amazon.com/appsync/request-mapping-template.json", "type": "object", "properties": { "version": { "$id": "/properties/version", "type": "string", "enum": [ "2018-05-29" ], "title": "The Mapping template version.", "default": "2018-05-29" }, "operation": { "$id": "/properties/operation", "type": "string", "enum": [ "Invoke", "BatchInvoke" ], "title": "The Mapping template operation.", "description": "What operation to execute.", "default": "Invoke" }, "payload": {} }, "required": [ "version", "operation" ], "additionalProperties": false }

下面是我们通过的示例:field值以及上下文中的 GraphQL 字段参数。

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

将整个映射文档作为输入传递到 Lambda 函数,因此,前面的示例将如下所示:

{ "version": "2018-05-29", "operation": "Invoke", "payload": { "field": "getPost", "arguments": { "id": "postId1" } } }

版本

version 定义模板使用的版本,这一点对于所有请求映射模板都相同。version 是必需的。

"version": "2018-05-29"

运算

Lambda 数据源允许您定义两种操作:InvokeBatchInvoke. 这些区域有:Invoke操作允许AmazonAppSync 知道为每个 GraphQL 字段解析程序调用 Lambda 函数。BatchInvoke指示AmazonAppSync 用于批量对当前 GraphQL 字段的请求。

operation 是必需的。

适用于Invoke,已解析的请求映射模板与 Lambda 函数的输入负载完全匹配。因此,下面的示例模板:

{ "version": "2018-05-29", "operation": "Invoke", "payload": { "arguments": $util.toJson($context.arguments) } }

经过解析并传递给 Lambda 函数,如下所示:

{ "version": "2018-05-29", "operation": "Invoke", "payload": { "arguments": { "id": "postId1" } } }

适用于BatchInvoke,映射模板将应用于批处理中的每个字段解析程序。为了简洁起见,AmazonAppSync 合并所有已解析的映射模板payload在与映射模板匹配的单一对象下的列表中。

以下示例模板显示合并:

{ "version": "2018-05-29", "operation": "BatchInvoke", "payload": $util.toJson($context) }

此模板解析为以下映射文档:

{ "version": "2018-05-29", "operation": "BatchInvoke", "payload": [ {...}, // context for batch item 1 {...}, // context for batch item 2 {...} // context for batch item 3 ] }

其中,payload 列表的每个元素对应于一个批处理项目。Lambda 函数也预期返回列表形状的响应,并与请求中发送的项目顺序匹配,如下所示:

[ { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 1 { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 2 { "data": {...}, "errorMessage": null, "errorType": null } // result for batch item 3 ]

operation 是必需的。

有效负载

payload 字段是一个容器,可用于将任何格式正确的 JSON 传递到 Lambda 函数。

如果operation字段设置为BatchInvoke、AmazonAppSync 包装了现有的payload值转入列表中。

payload 为可选项。

响应映射模板

与其他数据源一样,Lambda 函数将响应发送到Amazon必须转换为 GraphQL 类型的 AppSync。

Lambda 函数的结果设置在context通过 Velocity 模板语言 (VTL) 提供的对象(VTL)$context.result财产。

如果 Lambda 函数响应的形状与 GraphQL 类型的形状完全匹配,您可以使用以下响应映射模板转发响应:

$util.toJson($context.result)

没有必填字段,也没有形状限制应用于响应映射模板。但是,由于 GraphQL 是强类型化的,因此解析的映射模板必须与预期的 GraphQL 类型匹配。

响应 Lambda 函数批处理

如果operation字段设置为BatchInvoke、AmazonAppSync 预计从 Lambda 函数返回项目列表。为了AmazonAppSync 要将每个结果映射回原始请求项目,响应列表在大小和顺序方面必须匹配。没关系null响应列表中的项目;$ctx.result设置为null相应地。

直接 Lambda 解析程序

如果你想完全规避使用映射模板,AmazonAppSync 可以为您的 Lambda 函数提供默认负载以及 Lambda 函数对 GraphQL 类型的默认响应。您可以选择提供请求模板、响应模板或两者都不提供,以及AmazonAppSync 会相应地处理它。

直接 Lambda 请求映射模板

如果未提供请求映射模板,AmazonAppSync 将发送Context直接将对象作为 Lambda 函数Invokeoperation. 有关 Context 对象结构的更多信息,请参阅 解析程序映射模板上下文参考

直接 Lambda 响应映射模板

如果没有提供响应映射模板,AmazonAppSync 在收到 Lambda 函数响应后执行以下两件事之一。如果您没有提供请求映射模板,或者如果您提供了版本为 “2018-05-29” 的请求映射模板,则响应逻辑功能与以下响应映射模板相当:

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

如果您提供了版本为 “2017-02-28” 的模板,则响应逻辑的功能与以下响应映射模板相同:

$util.toJson($ctx.result)

表面上,映射模板绕过的操作方式与使用某些映射模板类似,如前面的示例所示。但是,在幕后,完全绕过了对映射模板的评估。由于模板评估步骤被绕过,因此与需要评估的响应映射模板的 Lambda 函数相比,在某些情况下,应用程序在响应期间可能会遇到的开销和延迟较少。

直接 Lambda 解决器响应中的自定义错误处理

您可以通过引发自定义异常,从直接 Lambda 解析器调用的 Lambda 函数自定义错误响应。以下示例演示如何使用 JavaScript 创建自定义异常:

class CustomException extends Error { constructor(message) { super(message); this.name = "CustomException"; } } throw new CustomException("Custom message");

当出现例外情况时,errorTypeerrorMessagenamemessage,分别是引发的自定义错误的信息。

如果errorTypeUnauthorizedException、AmazonAppSync 返回默认消息("You are not authorized to make this call.") 而不是自定义消息。

以下是 GraphQL 响应示例,演示自定义:errorType.

{ "data": { "query": null }, "errors": [ { "path": [ "query" ], "data": null, "errorType": "CustomException", "errorInfo": null, "locations": [ { "line": 5, "column": 10, "sourceName": null } ], "message": "Custom Message" } ] }

直接 Lambda 解析程序:启用批处理

您可以通过配置为直接 Lambda 解析器启用批处理maxBatchSize在解析程序上。何时maxBatchSize对于直接 Lambda 解析程序,设置为大于 0 的值,AmazonAppSync 将请求批量发送到您的 Lambda 函数,其大小不超过maxBatchSize.

设置maxBatchSize直接 Lambda 解析器上的设置为 0 关闭批处理。

有关使用 Lambda 解析程序批处理的更多信息,请参阅:高级用例:批处理.

请求映射模板

启用批处理且未提供请求映射模板时,AmazonAppSync 发送了一份列表Context对象作为BatchInvoke直接对 Lambda 函数进行操作。

响应映射模板

启用批处理且未提供响应映射模板时,响应逻辑等同于以下响应映射模板:

#if( $context.result && $context.result.errorMessage ) $utils.error($context.result.errorMessage, $context.result.errorType, $context.result.data) #else $utils.toJson($context.result.data) #end

Lambda 函数必须按照与列表相同的顺序返回结果列表Context已发送的对象。您可以通过提供一个errorMessageerrorType获取具体结果。列表中的每个结果都遵循以下格式:

{ "data" : { ... }, // your data "errorMessage" : { ... }, // optional, if included an error entry is added to the "errors" object in the AppSync response "errorType" : { ... } // optional, the error type }
注意

结果对象中的其他字段当前被忽略。

处理 Lambda 的错误

您可以通过在 Lambda 函数中抛出异常或错误来返回所有结果的错误。如果批处理请求的有效负载请求或响应大小太大,Lambda 会返回错误。在这种情况下,您应当考虑减少您的maxBatchSize或减小响应负载的大小。

有关处理单个错误的信息,请参阅返回单个错误.

示例 Lambda 函数

使用下面的模式,Lambda 可以为Post.relatedPosts字段解析器并通过设置启用批处理maxBatchSize大于 0:

schema { query: Query mutation: Mutation } type Query { getPost(id:ID!): Post allPosts: [Post] } type Mutation { addPost(id: ID!, author: String!, title: String, content: String, url: String): Post! } type Post { id: ID! author: String! title: String content: String url: String ups: Int downs: Int relatedPosts: [Post] }

在以下查询中,将通过批次请求调用 Lambda 函数以解决relatedPosts

query getAllPosts { allPosts { id relatedPosts { id } } }

下面提供了 Lambda 函数的简单实现:

const posts = { 1: { id: '1', title: 'First book', author: 'Author1', url: 'https://amazon.com/', content: 'SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1', ups: '100', downs: '10', }, 2: { id: '2', title: 'Second book', author: 'Author2', url: 'https://amazon.com', content: 'SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT', ups: '100', downs: '10', }, 3: { id: '3', title: 'Third book', author: 'Author3', url: null, content: null, ups: null, downs: null }, 4: { id: '4', title: 'Fourth book', author: 'Author4', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4', ups: '1000', downs: '0', }, 5: { id: '5', title: 'Fifth book', author: 'Author5', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT', ups: '50', downs: '0', }, } const relatedPosts = { 1: [posts['4']], 2: [posts['3'], posts['5']], 3: [posts['2'], posts['1']], 4: [posts['2'], posts['1']], 5: [], } exports.handler = async (event) => { console.log('event ->', event) // retrieve the ID of each post const ids = event.map((context) => context.source.id) // fetch the related posts for each post id const related = ids.map((id) => relatedPosts[id]) // return the related posts; or an error if none were found return related.map((r) => { if (r.length > 0) { return { data: r } } else { return { data: null, errorMessage: 'Not found', errorType: 'ERROR' } } }) }