本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
在 中使用管道解析器 AWS AppSync
注意
我們現在主要支援 APPSYNC_JS 執行期及其文件。請考慮在此處使用 APPSYNC_JS 執行期及其指南。
AWS AppSync 提供透過單位解析器將 GraphQL 欄位連接至單一資料來源的簡單方法。不過,執行單一操作可能還是不夠。管道解析程式的功能是對資料來源依序執行操作。在 中建立函數API,並將其連接至管道解析器。每個函數執行結果都會輸送到下一個函數,直到沒有要執行的函數。使用管道解析器,您現在可以直接在 中建置更複雜的工作流程 AWS AppSync。在此教學課程中,您會建置一個簡單的圖片檢視應用程式,而使用者可以透過此應用程式來張貼圖片和檢視朋友所張貼的圖片。
一鍵設定
如果您想要在 中自動設定 GraphQL 端點, AWS AppSync 並設定所有解析器和必要的 AWS 資源,您可以使用下列 AWS CloudFormation 範本:
這個堆疊會在您的帳戶中建立下列資源:
-
IAM AWS AppSync 存取您帳戶中資源的角色
-
2 個 DynamoDB 資料表
-
1 個 Amazon Cognito 使用者工具
-
2 個 Amazon Cognito 使用者集區群組
-
3 個 Amazon Cognito 使用者集區使用者
-
1 AWS AppSync API
在 AWS CloudFormation 堆疊建立程序結束時,您會收到建立的三個 Amazon Cognito 使用者各一封電子郵件。每封電子郵件都包含臨時密碼,用於以 Amazon Cognito 使用者身分登入 AWS AppSync 主控台。儲存這些密碼,以供教學課程其餘內容使用。
手動設定
如果您想要手動透過 AWS AppSync主控台完成程序 step-by-step,請遵循下列設定程序。
設定您的非 AWS AppSync 資源
會與兩個 DynamoDB 資料表API通訊:存放圖片的相片資料表,以及存放使用者之間關係的朋友資料表。API 設定為使用 Amazon Cognito 使用者集區作為身分驗證類型。下列 AWS CloudFormation 堆疊會在 帳戶中設定這些資源。
在 AWS CloudFormation 堆疊建立程序結束時,您會收到建立的三個 Amazon Cognito 使用者各一封電子郵件。每封電子郵件都包含臨時密碼,您可用來以 AWS AppSyncAmazon Cognito 使用者身分登入主控台。儲存這些密碼,以供教學課程其餘內容使用。
建立您的 GraphQL API
若要在 API中建立 GraphQL AWS AppSync:
-
開啟 AWS AppSync 主控台,然後選擇從速寫開始,然後選擇開始 。
-
將 的名稱API設定為
AppSyncTutorial-PicturesViewer
。 -
選擇 Create (建立)。
AWS AppSync 主控台會使用API金鑰身分驗證模式API為您建立新的 GraphQL。您可以使用 主控台來設定 GraphQL 的其餘部分,API並在本教學課程的其餘部分對其執行查詢。
設定 GraphQL API
您需要使用剛建立的 Amazon Cognito 使用者集區來設定 AWS AppSync API。
-
選擇 Settings (設定) 標籤。
-
在 Authorization Type (授權類型) 區段下,選擇 Amazon Cognito User Pool (Amazon Cognito 使用者集區)。
-
在使用者集區組態 下,為區域 選擇 US-WEST-2。 AWS
-
選擇 AppSyncTutorial- UserPool使用者集區。
-
選擇 DENY作為預設動作 。
-
將AppId 用戶端 regex 欄位保留空白。
-
選擇 Save (儲存)。
API 現已設定為使用 Amazon Cognito 使用者集區作為其授權類型。
設定 DynamoDB 資料表的資料來源
建立 DynamoDB 資料表後,請在主控台API中導覽至 AWS AppSync GraphQL,然後選擇資料來源索引標籤。現在,您要 AWS AppSync 為您剛建立的每個 DynamoDB 資料表在 中建立資料來源。
-
選擇 Data source (資料來源) 標籤。
-
選擇 New (新建) 來建立新資料來源。
-
輸入
PicturesDynamoDBTable
做為資料來源名稱。 -
選擇 Amazon DynamoDB table (Amazon DynamoDB 資料表) 做為資料來源類型。
-
針對區域,選擇 US-WEST-2。
-
從資料表清單中,選擇 AppSyncTutorial-Pictures DynamoDB 資料表。
-
在建立或使用現有角色區段中,選擇現有角色 。
-
選擇剛從 CloudFormation 範本建立的角色。如果您未變更 ResourceNamePrefix,角色的名稱應為 AppSyncTutorial-D ynamoDBRole。
-
選擇 Create (建立)。
針對朋友資料表重複相同的程序,如果您在建立 CloudFormation 堆疊時未變更 ResourceNamePrefix 參數,則 DynamoDB 資料表的名稱應為 AppSyncTutorial- 朋友。
建立 GraphQL 結構描述
現在資料來源已連接至 DynamoDB 資料表,讓我們建立 GraphQL 結構描述。從 AWS AppSync 主控台的結構描述編輯器中,確保您的結構描述符合下列結構描述:
schema { query: Query mutation: Mutation } type Mutation { createPicture(input: CreatePictureInput!): Picture! @aws_auth(cognito_groups: ["Admins"]) createFriendship(id: ID!, target: ID!): Boolean @aws_auth(cognito_groups: ["Admins"]) } type Query { getPicturesByOwner(id: ID!): [Picture] @aws_auth(cognito_groups: ["Admins", "Viewers"]) } type Picture { id: ID! owner: ID! src: String } input CreatePictureInput { owner: ID! src: String! }
選擇 Save Schema (儲存結構描述) 來儲存結構描述。
有些結構描述欄位已標註 @aws_auth 指令。由於API預設動作組態設定為 DENY,因此 會API拒絕不是 @aws_auth 指令中提及群組成員的所有使用者。如需有關如何保護 的詳細資訊API,請參閱安全頁面。在此情況下,只有管理員使用者可以存取 Mutation.createPicture 和 Mutation.createFriendship 欄位,而管理員或檢視器群組的成員使用者可以存取 Query.getPicturesByOwner 欄位。其他所有使用者都無存取權。
設定解析程式
現在,您已備妥有效的 GraphQL 結構描述和兩個資料來源,您可以將解析程式連接到結構描述上的 GraphQL 欄位。API 提供下列功能:
-
透過 Mutation 欄位建立圖片。createPicture
-
透過 Mutation 欄位建立友誼。createFriendship
-
透過查詢欄位擷取圖片。getPicture
突變。createPicture
從 AWS AppSync 主控台的結構描述編輯器中,在右側選擇連接解析程式createPicture(input: CreatePictureInput!): Picture!
。選擇 DynamoDBPicturesDynamoDBTable 資料來源。在 request mapping template (要求映射範本) 區段中,新增下列範本:
#set($id = $util.autoId()) { "version" : "2018-05-29", "operation" : "PutItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($id), "owner": $util.dynamodb.toDynamoDBJson($ctx.args.input.owner) }, "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args.input) }
在 response mapping template (回應映射範本) 區段中,新增下列範本:
#if($ctx.error) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)
建立圖片功能完成。您要將圖片儲存在圖片表中,使用隨機產生的圖片 ID,並使用 Cognito UUID 使用者名稱作為圖片的擁有者。
突變。createFriendship
從 AWS AppSync 主控台的結構描述編輯器中,選擇適用於 的連接解析程式createFriendship(id: ID!, target: ID!): Boolean
。選擇 DynamoDBFriendsDynamoDBTable 資料來源。在 request mapping template (要求映射範本) 區段中,新增下列範本:
#set($userToFriendFriendship = { "userId" : "$ctx.args.id", "friendId": "$ctx.args.target" }) #set($friendToUserFriendship = { "userId" : "$ctx.args.target", "friendId": "$ctx.args.id" }) #set($friendsItems = [$util.dynamodb.toMapValues($userToFriendFriendship), $util.dynamodb.toMapValues($friendToUserFriendship)]) { "version" : "2018-05-29", "operation" : "BatchPutItem", "tables" : { ## Replace 'AppSyncTutorial-' default below with the ResourceNamePrefix you provided in the CloudFormation template "AppSyncTutorial-Friends": $util.toJson($friendsItems) } }
重要:在BatchPutItem請求範本中,DynamoDB 資料表的確切名稱應存在。預設資料表名稱為 AppSyncTutorial- 朋友 。如果您使用的資料表名稱錯誤, AppSync 嘗試擔任提供的角色時,會出現錯誤。
為了本教學課程的簡單性,請繼續執行,如同友誼請求已核准一樣,並將關係項目直接儲存至AppSyncTutorialFriends資料表中。
很快地,您就能為每個朋友關係儲存兩個項目,做為雙向關係。如需 Amazon DynamoDB 表示 many-to-many關係的最佳實務的詳細資訊,請參閱 DynamoDB 最佳實務 。
在 response mapping template (回應映射範本) 區段中,新增下列範本:
#if($ctx.error) $util.error($ctx.error.message, $ctx.error.type) #end true
注意:請確定您的要求範本包含適當的資料表名稱。預設名稱為 AppSyncTutorial- 朋友 ,但如果您變更 參數, CloudFormation ResourceNamePrefix資料表名稱可能會有所不同。
Query.getPicturesByOwner
現在您已經備妥朋友關係和圖片,您還需要提供讓使用者檢視其朋友圖片的權限。為了滿足這項要求,您必須先檢查申請者是內容擁有者的朋友,最後提供圖片查詢功能。
由於此功能需要兩個資料來源操作,所以您要建立兩個函數。第一個函數 會isFriend檢查請求者和擁有者是否為朋友。第二個函數getPicturesBy擁有者 會擷取指定擁有者 ID 的請求圖片。讓我們來看看 Query.getPicturesByOwner 欄位上提議解析器的執行流程:
-
Before 映射範本:準備內容和欄位輸入引數。
-
isFriend 函數:檢查請求者是否為圖片的擁有者。如果不是,它會透過在朋友資料表上執行 DynamoDB GetItem 操作,檢查請求者和擁有者使用者是否為朋友。
-
getPicturesBy擁有者函數:使用擁有者索引全域次要索引上的 DynamoDB 查詢操作,從圖片資料表擷取圖片。
-
After 映射範本:映射圖片結果,讓 DynamoDB 屬性正確映射到預期的 GraphQL 類型欄位。
首先,讓我們來建立下列函數。
isFriend 函數
-
選擇 Functions (函數) 索引標籤。
-
選擇 Create Function (建立函數) 來建立函數。
-
輸入
FriendsDynamoDBTable
做為資料來源名稱。 -
對於函數名稱,輸入 isFriend。
-
在要求映射範本文字區域中,貼上下列範本:
#set($ownerId = $ctx.prev.result.owner) #set($callerId = $ctx.prev.result.callerId) ## if the owner is the caller, no need to make the check #if($ownerId == $callerId) #return($ctx.prev.result) #end { "version" : "2018-05-29", "operation" : "GetItem", "key" : { "userId" : $util.dynamodb.toDynamoDBJson($callerId), "friendId" : $util.dynamodb.toDynamoDBJson($ownerId) } }
-
在回應映射範本文字區域中,貼上下列範本:
#if($ctx.error) $util.error("Unable to retrieve friend mapping message: ${ctx.error.message}", $ctx.error.type) #end ## if the users aren't friends #if(!$ctx.result) $util.unauthorized() #end $util.toJson($ctx.prev.result)
-
選擇 Create Function (建立函數)。
結果:您已建立isFriend函數。
getPicturesBy擁有者函數
-
選擇 Functions (函數) 索引標籤。
-
選擇 Create Function (建立函數) 來建立函數。
-
輸入
PicturesDynamoDBTable
做為資料來源名稱。 -
對於函數名稱,輸入
getPicturesByOwner
。 -
在要求映射範本文字區域中,貼上下列範本:
{ "version" : "2018-05-29", "operation" : "Query", "query" : { "expression": "#owner = :owner", "expressionNames": { "#owner" : "owner" }, "expressionValues" : { ":owner" : $util.dynamodb.toDynamoDBJson($ctx.prev.result.owner) } }, "index": "owner-index" }
-
在回應映射範本文字區域中,貼上下列範本:
#if($ctx.error) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)
-
選擇 Create Function (建立函數)。
結果:您已建立getPicturesBy擁有者函數。現在已建立函數,請將管道解析程式連接至 Query.getPicturesByOwner 欄位。
從 AWS AppSync 主控台的結構描述編輯器中,選擇連接解析程式。 Query.getPicturesByOwner(id: ID!): [Picture]
在接下來的頁面,選擇會出現在資料來源下拉式清單中的 Convert to pipeline resolver (轉換成管道解析程式) 連結。使用下列程序來使用 Before 映射範本:
#set($result = { "owner": $ctx.args.id, "callerId": $ctx.identity.username }) $util.toJson($result)
在 after mapping template (After 映射範本) 區段中,使用下列範本:
#foreach($picture in $ctx.result.items) ## prepend "src://" to picture.src property #set($picture['src'] = "src://${picture['src']}") #end $util.toJson($ctx.result.items)
選擇 Create Resolver (建立解析程式)。您已成功連接第一個管道解析程式。在相同頁面上,新增您之前建立的兩個函數。在函數區段中,選擇新增函數,然後選擇或輸入第一個函數的名稱 isFriend。按照getPicturesBy擁有者函數的相同程序新增第二個函數。請確定isFriend函數先出現在清單中,然後是getPicturesBy擁有者函數。您可以使用上下箭頭,重新安排管道中的函數執行順序。
現在管道解析程式已建立且您已連接函數,讓我們測試新建立的 GraphQL API。
測試您的 GraphQL API
首先,您必須透過您先前建立的管理員使用者,執行少量變動來填入圖片和朋友關係。在 AWS AppSync 主控台左側,選擇查詢索引標籤。
createPicture 突變
-
在 AWS AppSync 主控台中,選擇查詢索引標籤。
-
選擇 Login With User Pools (登入使用者集區)。
-
在模型上,輸入 CloudFormation 堆疊建立的 Cognito 範例用戶端 ID,例如 37solo6mmhh7k4v63cqdfgdg5d)。
-
輸入您作為 參數傳遞至 CloudFormation 堆疊的使用者名稱。預設為 nadia。
-
使用傳送給您作為 CloudFormation 堆疊參數提供的電子郵件的臨時密碼 (例如 UserPoolUserEmail)。
-
選擇 Login (登入)。您現在應該會看到重新命名為 Logout nadia 的按鈕,或您在建立 CloudFormation 堆疊時選擇的任何使用者名稱 (即 UserPoolUsername)。
讓我們傳送一些createPicture突變來填入圖片表。在主控台中,執行以下 GraphQL 查詢:
mutation { createPicture(input:{ owner: "nadia" src: "nadia.jpg" }) { id owner src } }
回應看起來應如下所示:
{ "data": { "createPicture": { "id": "c6fedbbe-57ad-4da3-860a-ffe8d039882a", "owner": "nadia", "src": "nadia.jpg" } } }
讓我們新增更多圖片:
mutation { createPicture(input:{ owner: "shaggy" src: "shaggy.jpg" }) { id owner src } }
mutation { createPicture(input:{ owner: "rex" src: "rex.jpg" }) { id owner src } }
您已透過管理使用者的身分,使用 nadia 新增三張圖片。
createFriendship 突變
讓我們來新增朋友關係項目。在主控台中,執行下列變動。
注意:您仍必須登入管理使用者 (預設管理使用者是 nadia)。
mutation { createFriendship(id: "nadia", target: "shaggy") }
回應看起來應該會像這樣:
{ "data": { "createFriendship": true } }
nadia 和 shaggy 是朋友。rex 不是任何人的朋友。
getPicturesBy擁有者查詢
第一步是使用 Cognito 使用者集區,以及本教學課程一開始所設定的登入資料,登入成為 nadia 使用者。登入為 nadia 時,擷取 shaggy 擁有的圖片。
query { getPicturesByOwner(id: "shaggy") { id owner src } }
由於 nadia 和 shaggy 是朋友,所以查詢應該會傳回相對應的圖片。
{ "data": { "getPicturesByOwner": [ { "id": "05a16fba-cc29-41ee-a8d5-4e791f4f1079", "owner": "shaggy", "src": "src://shaggy.jpg" } ] } }
同樣地,嘗試擷取自己圖片的 nadia 也能順利擷取。管道解析程式已最佳化,以避免在這種情況下執行isFriend GetItem 操作。嘗試下列查詢:
query { getPicturesByOwner(id: "nadia") { id owner src } }
如果您在 API(在設定窗格中) 上啟用記錄,請將偵錯層級設定為 ALL,然後再次執行相同的查詢,則會傳回欄位執行的日誌。透過查看日誌,您可以判斷isFriend函數是否在請求映射範本階段提早傳回:
{ "errors": [], "mappingTemplateType": "Request Mapping", "path": "[getPicturesByOwner]", "resolverArn": "arn:aws:appsync:us-west-2:XXXX:apis/XXXX/types/Query/fields/getPicturesByOwner", "functionArn": "arn:aws:appsync:us-west-2:XXXX:apis/XXXX/functions/o2f42p2jrfdl3dw7s6xub2csdfs", "functionName": "isFriend", "earlyReturnedValue": { "owner": "nadia", "callerId": "nadia" }, "context": { "arguments": { "id": "nadia" }, "prev": { "result": { "owner": "nadia", "callerId": "nadia" } }, "stash": {}, "outErrors": [] }, "fieldInError": false }
earlyReturnedValue 金鑰代表 #return 指令傳回的資料。
最後,即使 rex 是 Viewers Cognito UserPool 群組的成員,而且由於 rex 不是任何人的朋友,他將無法存取任何由晃動或 nadia 擁有的圖片。如果您以 rex 登入主控台,並執行下列查詢時:
query { getPicturesByOwner(id: "nadia") { id owner src } }
您會收到下列關於未經授權的錯誤:
{ "data": { "getPicturesByOwner": null }, "errors": [ { "path": [ "getPicturesByOwner" ], "data": null, "errorType": "Unauthorized", "errorInfo": null, "locations": [ { "line": 2, "column": 9, "sourceName": null } ], "message": "Not Authorized to access getPicturesByOwner on type Query" } ] }
這表示您已成功使用管道解析程式,實作複雜的授權程序。