View a markdown version of this page

AWS AppSync 解析程式映射範本內容參考 - AWS AppSync GraphQL

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

AWS AppSync 解析程式映射範本內容參考

注意

我們現在主要支援 APPSYNC_JS 執行期及其文件。請考慮在此處使用 APPSYNC_JS 執行期及其指南。

AWS 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

此 stash 是每個解析程式和函數映射範本中都會提供的「映射」。在單一個解析程式執行期間,則會存在相同的 stash 執行個體。這表示您可以使用 stash 在管道解析程式中的所有要求和回應映射範本、以及全部函數中,傳遞任意資料。此 stash 會公開與 Java 映射資料結構相同的方法。

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 區段。本節的形狀取決於 AWS AppSync API 的授權類型。

如需 AWS 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

發起人 AWS 的帳戶 ID。

claims

使用者擁有的宣告。

cognitoIdentityAuthType

經身分驗證或未經身分驗證 (根據身分類型)。

cognitoIdentityAuthProvider

以逗號分隔的外部身分提供者資訊清單,用於取得用於簽署請求的登入資料。

cognitoIdentityId

發起人的 Amazon Cognito 身分 ID。

cognitoIdentityPoolId

與發起人相關聯的 Amazon Cognito 身分集區 ID。

defaultAuthStrategy

此發起人 (ALLOW 或 DENY) 的預設授權策略。

issuer

字符發行者。

sourceIp

AWS AppSync 接收的發起人的來源 IP 地址。如果請求不包含 x-forwarded-for標頭,來源 IP 值只會包含來自 TCP 連線的單一 IP 地址。如果要求包含 x-forwarded-for 標頭,則來源 IP 除了有 TCP 連線的 IP 地址外,也將有 x-forwarded-for 標頭中 IP 地址的清單。

sub

已驗證使用者的 UUID。

user

IAM 使用者。

userArn

IAM 使用者的 Amazon Resource Name (ARN)。

username

已驗證使用者的使用者名稱。如果是 AMAZON_COGNITO_USER_POOLS 授權,使用者名稱的值是屬性 cognito:username 的值。在AWS_IAM授權的情況下,使用者名稱的值是 AWS 使用者主體的值。如果您使用 IAM 授權搭配來自 Amazon Cognito 身分集區的憑證,我們建議您使用 cognitoIdentityId。

存取請求標頭

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

注意

AWS AppSync 不會在 中公開 Cookie 標頭$context.request.headers。

存取請求自訂網域名稱

AWS AppSync 支援設定自訂網域,您可以用來存取 APIs的 GraphQL 和即時端點。使用自訂網域名稱提出請求時,您可以使用 取得網域名稱$context.request.domainName。

使用預設 GraphQL 端點網域名稱時,值為 null。

資訊

info 區段包含有關 GraphQL 請求的資訊。本節的格式如下:

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

每個欄位的定義如下:

fieldName

目前正在解析的欄位名稱。

parentTypeName

目前正在解析的欄位父類型名稱。

variables

包含傳遞給 GraphQL 請求之所有變數的映射。

selectionSetList

此清單表示 GraphQL 選取範圍中的欄位。別名的欄位僅由別名名稱參考,而非欄位名稱。以下範例詳細說明這一點。

selectionSetGraphQL

此字串表示格式為 GraphQL 結構描述定義語言 (SDL) 的選取範圍。雖然片段不會合併到選取集,但會保留內嵌片段,如下列範例所示。

注意

在 $utils.toJson()上使用 時context.info,預設不會序列化 selectionSetGraphQL和 selectionSetList傳回的值。

例如,如果您解析下列查詢的 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.selectionSetList 以Query.node欄位解析度呼叫 時,只會id公開:

"selectionSetList": [ "id" ]

處理輸入

應用程式必須處理不受信任的輸入,以防止任何外部方使用其預期用途之外的應用程式。由於 包含 $context.arguments、、$context.info.variables、 $context.identity $context.result和 等屬性中的$context使用者輸入$context.request.headers,因此必須小心在映射範本中淨化其值。

由於對應範本代表 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. } }