教學課程:使用 Lambda 和 DynamoDB 建立 CRUD API - Amazon API Gateway

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

教學課程:使用 Lambda 和 DynamoDB 建立 CRUD API

在本教學課程中,您會建立無伺服器 API,以建立、讀取、更新和刪除 DynamoDB 資料表中的項目。DynamoDB 是全受管 NoSQL 資料庫服務,提供快速且可預期的效能,以及無縫的可擴展性。本教學課程大約需要 30 分鐘完成,您可以在 AWS 免費方案中完成。

首先,您可以使用 DynamoDB 主控台建立 DynamoDB 資料表。然後,您可以使用 AWS Lambda 主控台建立 Lambda 函數。接著,您可以使用 API Gateway 主控台建立 HTTP API。最後,測試您的 API。

在您叫用 HTTP API 時,API Gateway 會將請求路由至您的 Lambda 函數。Lambda 函數會與 DynamoDB 互動,並傳回 API Gateway 的回應。API Gateway 隨後將回應傳回給您。

您在本教學課程中建立的 HTTP API 概觀。

要完成這個練習,您需要一個 AWS 帳戶和一個具有控制台訪問權限的 AWS Identity and Access Management 用戶。如需詳細資訊,請參閱 開始使用 API Gateway 的必要條件

在本教學課程中,您需使用 AWS Management Console。如需建 AWS SAM 立此 API 及所有相關資源的範本,請參閱template.yaml

步驟 1:建立 DynamoDB 資料表

您可以使用 DynamoDB 資料表來儲存 API 的資料。

每個項目都有一個唯一的 ID,我們將其作為資料表的分割區索引鍵

建立 DynamoDB 資料表
  1. 請在 https://console.aws.amazon.com/dynamodb/ 開啟 DynamoDB 主控台。

  2. 選擇 Create Table (建立資料表)。

  3. 對於 Table name (資料表名稱),請輸入 http-crud-tutorial-items

  4. 對於 Partition key (分區索引鍵),請輸入 id

  5. 選擇 建立資料表

步驟 2:建立 Lambda 函數

您可以為您的 API 的後端建立 Lambda 函數。此 Lambda 函數會從 DynamoDB 建立、讀取、更新和刪除項目。此函數會使用來自 API Gateway 的事件來決定如何與 DynamoDB 互動。為了簡單起見,本教學課程使用了單一 Lambda 函數。最佳實務是,您應該為每個路由建立不同的函數。

建立 Lambda 函數
  1. 在以下網址登入 Lambda 主控台:https://console.aws.amazon.com/lambda

  2. 選擇 Create function (建立函數)。

  3. 針對 Function name (函數名稱),請輸入 http-crud-tutorial-function

  4. 針對執行期,請選擇最新支援的 Node.jsPython 執行期。

  5. Permissions (許可) 下選擇 Change default execution role (變更預設執行角色)。

  6. 選取從 AWS 策略範本建立新角色

  7. 針對 Role name (角色名稱),請輸入 http-crud-tutorial-role

  8. 對於 Policy templates (政策範本),請選擇 Simple microservice permissions。此政策會授予 Lambda 函數許可,以與 DynamoDB 互動。

    注意

    本教學課程為了簡單起見,使用受管理政策。最佳實務是,您應建立自己的 IAM 政策以授予所需的最低許可。

  9. 選擇 Create function (建立函數)。

  10. 在主控台的程式碼編輯器中開啟 Lambda 函數,並以下列程式碼取代其內容。選擇 Deploy (部署) 以更新您的功能。

Node.js
import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; import { DynamoDBDocumentClient, ScanCommand, PutCommand, GetCommand, DeleteCommand, } from "@aws-sdk/lib-dynamodb"; const client = new DynamoDBClient({}); const dynamo = DynamoDBDocumentClient.from(client); const tableName = "http-crud-tutorial-items"; export const handler = async (event, context) => { let body; let statusCode = 200; const headers = { "Content-Type": "application/json", }; try { switch (event.routeKey) { case "DELETE /items/{id}": await dynamo.send( new DeleteCommand({ TableName: tableName, Key: { id: event.pathParameters.id, }, }) ); body = `Deleted item ${event.pathParameters.id}`; break; case "GET /items/{id}": body = await dynamo.send( new GetCommand({ TableName: tableName, Key: { id: event.pathParameters.id, }, }) ); body = body.Item; break; case "GET /items": body = await dynamo.send( new ScanCommand({ TableName: tableName }) ); body = body.Items; break; case "PUT /items": let requestJSON = JSON.parse(event.body); await dynamo.send( new PutCommand({ TableName: tableName, Item: { id: requestJSON.id, price: requestJSON.price, name: requestJSON.name, }, }) ); body = `Put item ${requestJSON.id}`; break; default: throw new Error(`Unsupported route: "${event.routeKey}"`); } } catch (err) { statusCode = 400; body = err.message; } finally { body = JSON.stringify(body); } return { statusCode, body, headers, }; };
Python
import json import boto3 from decimal import Decimal client = boto3.client('dynamodb') dynamodb = boto3.resource("dynamodb") table = dynamodb.Table('http-crud-tutorial-items') tableName = 'http-crud-tutorial-items' def lambda_handler(event, context): print(event) body = {} statusCode = 200 headers = { "Content-Type": "application/json" } try: if event['routeKey'] == "DELETE /items/{id}": table.delete_item( Key={'id': event['pathParameters']['id']}) body = 'Deleted item ' + event['pathParameters']['id'] elif event['routeKey'] == "GET /items/{id}": body = table.get_item( Key={'id': event['pathParameters']['id']}) body = body["Item"] responseBody = [ {'price': float(body['price']), 'id': body['id'], 'name': body['name']}] body = responseBody elif event['routeKey'] == "GET /items": body = table.scan() body = body["Items"] print("ITEMS----") print(body) responseBody = [] for items in body: responseItems = [ {'price': float(items['price']), 'id': items['id'], 'name': items['name']}] responseBody.append(responseItems) body = responseBody elif event['routeKey'] == "PUT /items": requestJSON = json.loads(event['body']) table.put_item( Item={ 'id': requestJSON['id'], 'price': Decimal(str(requestJSON['price'])), 'name': requestJSON['name'] }) body = 'Put item ' + requestJSON['id'] except KeyError: statusCode = 400 body = 'Unsupported route: ' + event['routeKey'] body = json.dumps(body) res = { "statusCode": statusCode, "headers": { "Content-Type": "application/json" }, "body": body } return res

步驟 3:建立 HTTP API

HTTP API 將針對您的 Lambda 函數提供 HTTP 端點。在此步驟中,您將建立空白 API。在下列步驟中,您可以設定路由和整合,以連接您的 API 和 Lambda 函數。

建立 HTTP API
  1. 在以下網址登入 API Gateway 主控台:https://console.aws.amazon.com/apigateway

  2. 選擇 Create API (建立 API),然後針對 HTTP API,選擇 Build (建置)。

  3. 針對 API name (API 名稱),請輸入 http-crud-tutorial-api

  4. 選擇 Next (下一步)。

  5. 對於 Configure routes (設定路由),請選擇 Next (下一步) 以略過建立路由。您可以稍後建立路由。

  6. 檢閱 API Gateway 為您建立的階段,然後選擇 Next (下一步)。

  7. 選擇 Create (建立)。

步驟 4:建立路由

路由是將傳入的 API 請求傳送到後端資源的一種方式。路由由兩部分組成:HTTP 方法和資源路徑,例如 GET /items。對於此示例 API,我們建立了四個路由:

  • GET /items/{id}

  • GET /items

  • PUT /items

  • DELETE /items/{id}

若要建立路由
  1. 在以下網址登入 API Gateway 主控台:https://console.aws.amazon.com/apigateway

  2. 選擇您的 API。

  3. 選擇 Routes (路由)。

  4. 選擇 Create (建立)。

  5. 對於 Method (方法),請選擇 GET

  6. 對於路徑,請輸入 /items/{id}。路徑結尾處 {id} 是一個路徑參數,是當用戶端發出請求時,API Gateway 從請求路徑中擷取的參數。

  7. 選擇 Create (建立)。

  8. GET /itemsDELETE /items/{id}PUT /items 重複步驟 4-7。

您的 API 有 GET /items、GET /items/{id}、DELETE /items/{id} 和 PUT /items 的路由。

步驟 5:建立整合

您可以建立整合以連接到後端資源的路由。在此範例 API 中,您可以建立一個用於所有路由的 Lambda 整合。

若要建立整合
  1. 在以下網址登入 API Gateway 主控台:https://console.aws.amazon.com/apigateway

  2. 選擇您的 API。

  3. 選擇 Integrations (整合)。

  4. 選擇 Manage integrations (管理整合),然後選擇 Create (建立)。

  5. 略過 Attach this integration to a route (將此整合連接到路由)。您可以在稍後的步驟中完成該操作。

  6. 對於 Integration type (整合類型),請選擇 Lambda function (Lambda 函數)。

  7. 對於 Lambda function (Lambda 函數),請輸入 http-crud-tutorial-function

  8. 選擇 Create (建立)。

步驟 6:將整合連接至路由

在此範例 API 中,您可以對所有路由使用相同的 Lambda 整合。將整合連接至所有 API 的路由之後,當用戶端呼叫您的任何路由時,會叫用 Lambda 函數。

若要將整合連接至路由
  1. 在以下網址登入 API Gateway 主控台:https://console.aws.amazon.com/apigateway

  2. 選擇您的 API。

  3. 選擇 Integrations (整合)。

  4. 選擇路由。

  5. Choose an existing integration (選擇現有的整合) 下,請選擇 http-crud-tutorial-function

  6. 選擇 Attach integration (連接整合)。

  7. 對所有路由重複步驟 4-6。

所有路由都會顯示已貼附 AWS Lambda 整合。

主控台會 AWS Lambda 在所有路由上顯示,表示您的整合已連接。

現在您擁有包含路由和整合的 HTTP API,您可以測試您的 API 了。

步驟 7:測試您的 API

為了確保您的 API 正常工作,您可以使用 curl

要取得 URL 來叫用您的 API
  1. 在以下網址登入 API Gateway 主控台:https://console.aws.amazon.com/apigateway

  2. 選擇您的 API。

  3. 請注意 API 的叫用 URL。它會出現在 Details (詳細資訊) 頁面上的 Invoke URL (叫用 URL) 下。

    在建立 API 之後,主控台會顯示 API 的叫用 URL。
  4. 複製您的 API 叫用 URL。

    完整的 URL 如 https://abcdef123.execute-api.us-west-2.amazonaws.com

若要建立或更新項目
  • 請使用下列命令來建立或更新項目。該命令包括具有項目 ID、價格和名稱的請求主體。

    curl -X "PUT" -H "Content-Type: application/json" -d "{\"id\": \"123\", \"price\": 12345, \"name\": \"myitem\"}" https://abcdef123.execute-api.us-west-2.amazonaws.com/items
若要取得所有項目
  • 使用下列命令列出所有項目。

    curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items
若要取得項目
  • 使用下列命令,透過其 ID 取得項目。

    curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items/123
刪除項目
  1. 使用下列命令刪除項目。

    curl -X "DELETE" https://abcdef123.execute-api.us-west-2.amazonaws.com/items/123
  2. 取得所有項目,以確認該項目已刪除。

    curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items

步驟 8:清除

若要避免不必要的成本,請刪除您在此入門練習中建立的資源。採用下列步驟刪除您的 HTTP API、您的 Lambda 函式和相關資源。

刪除 DynamoDB 資料表
  1. 請在 https://console.aws.amazon.com/dynamodb/ 開啟 DynamoDB 主控台。

  2. 選取您的資料表。

  3. 選擇 Delete table (刪除資料表)。

  4. 確認您的選擇,然後選擇 Delete (刪除)。

刪除 HTTP API
  1. 在以下網址登入 API Gateway 主控台:https://console.aws.amazon.com/apigateway

  2. API 頁面上,選取 API。選擇 Actions (動作),然後選擇 Delete (刪除)。

  3. 選擇 Delete (刪除)。

刪除 Lambda 函數
  1. 在以下網址登入 Lambda 主控台:https://console.aws.amazon.com/lambda

  2. Functions (函數) 頁面上,選取函數。選擇 Actions (動作),然後選擇 Delete (刪除)。

  3. 選擇 Delete (刪除)。

刪除 Lambda 函數的日誌群組
  1. 在 Amazon 主 CloudWatch 控台中,開啟日誌群組頁面

  2. Log groups (日誌群組) 頁面上,選取函數的日誌群組 (/aws/lambda/http-crud-tutorial-function)。選擇 Actions (動作),然後選擇 Delete log group (刪除日誌群組)。

  3. 選擇 Delete (刪除)。

刪除 Lambda 函數的執行角色
  1. 在 AWS Identity and Access Management 主控台中,開啟 [角色] 頁面

  2. 選取函數的角色,例如,http-crud-tutorial-role

  3. 選擇 Delete role (刪除角色)。

  4. 選擇 Yes, delete (是,刪除)。

後續步驟:使用 AWS SAM 或自動化 AWS CloudFormation

您可以使用 AWS CloudFormation 或來自動建立和清理 AWS 資源 AWS SAM。如需本教學課程的 AWS SAM 範本範例,請參閱 template.yaml

如需 AWS CloudFormation 範本,請參閱AWS CloudFormation 範例範本