
掌握ChatGPT插件與自定義GPT
基本項目結構需要兩個文件:package.json
和 serverless.yml
。
package.json
文件用于列出項目的 npm 依賴項,這些依賴項在 CLI 打包項目時將被拉取。CLI 會讀取這個文件以確定如何打包項目。
在我的示例項目中,我有一個 Python Lambda 函數,用于對餐食執行基本的創建、讀取、更新、刪除(CRUD)操作。這是我項目中的文件:serverless.yml
。
service: building-an-api-with-serverless
variablesResolutionMode: 20210326
frameworkVersion: ">=1.1.0 <=2.33.1"
configValidationMode: error
provider:
name: aws
region: us-east-1
runtime: python3.8
stage: prod
environment:
DYNAMODB_TABLE: ${self:service}-${opt:stage, self:provider.stage}
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
apiGateway:
shouldStartNameWithService: true
lambdaHashingVersion: 20201221
functions:
createMeals:
handler: meals/create.create
events:
- http:
path: meals/create
method: post
cors: true
listMeals:
handler: meals/list.list
events:
- http:
path: meals/list
method: get
cors: true
getMeals:
handler: meals/get.get
events:
- http:
path: meals/get
method: post
cors: true
updateMeals:
handler: meals/update.update
events:
- http:
path: meals/update
method: put
cors: true
deleteMeals:
handler: meals/delete.delete
events:
- http:
path: meals/delete
method: delete
cors: true
authorizer: ${self:provider.environment.LAMBDA_AUTHORIZER}
resources:
Resources:
MealsDynamoDBTable:
Type: "AWS::DynamoDB::Table"
DeletionPolicy: Retain
Properties:
AttributeDefinitions:
- AttributeName: username
AttributeType: S
KeySchema:
- AttributeName: username
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DYNAMODB_TABLE}
讓我們看看它的結構如何。
第一部分是為其提供一個帶有變量解析設置的服務名稱(讓 CLI 知道如何解析變量名稱):
service: building-an-api-with-serverless
variablesResolutionMode: 20210326
第二部分定義了 lambda 的提供程序、框架(在本例中為 python)以及 IAM 角色語句。這些角色非常重要,因為它們允許 Lambda 在您的 AWS 賬戶中具有與 DynamoDB 交互的權限,以執行 CRUD(創建、讀取、更新和刪除)操作。還有一個環境變量部分,用于定義 Dynamo DB 實例的名稱:
frameworkVersion: ">=1.1.0 <=2.33.1"
configValidationMode: error
provider:
name: aws
region: us-east-1
runtime: python3.8
stage: prod
environment:
DYNAMODB_TABLE: ${self:service}-${opt:stage, self:provider.stage}
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
apiGateway:
shouldStartNameWithService: true
lambdaHashingVersion: 20201221
接下來,我們將定義構建的 lambda 函數:
functions:
createMeals:
handler: meals/create.create
events:
- http:
path: meals/create
method: post
cors: true
listMeals:
handler: meals/list.list
events:
- http:
path: meals/list
method: get
cors: true
getMeals:
handler: meals/get.get
events:
- http:
path: meals/get
method: post
cors: true
updateMeals:
handler: meals/update.update
events:
- http:
path: meals/update
method: put
cors: true
deleteMeals:
handler: meals/delete.delete
events:
- http:
path: meals/delete
method: delete
cors: true
您是否注意到,這些函數的 YAML 文件的主要作用是命名函數、指定 Lambda 處理程序在項目中的位置,并為函數配置 HTTP 路由和請求方法。如果您允許 CORS:
createMeals:
handler: meals/create.create
events:
- http:
path: meals/create
method: post
cors: true
關于處理程序,如果您注意到它指向 meals/create.py
,這是告訴無服務器 CLI 轉到 meals
文件夾并使用其中的 Python 文件。然后在該文件中,它指定了要使用的函數。文件路徑如下所示:meals/create.py
。
import os
import json
import logging
from meals import decimalencoder
import boto3
import traceback
import time
dynamodb = boto3.resource('dynamodb')
initialMeals = [
{
"day": "0",
"breakfast": "",
"lunch": "",
"dinner": ""
},
{
"day": "1",
"breakfast": "",
"lunch": "",
"dinner": ""
},
{
"day": "2",
"breakfast": "",
"lunch": "",
"dinner": ""
},
{
"day": "3",
"breakfast": "",
"lunch": "",
"dinner": ""
},
{
"day": "4",
"breakfast": "",
"lunch": "",
"dinner": ""
},
{
"day": "5",
"breakfast": "",
"lunch": "",
"dinner": ""
},
{
"day": "6",
"breakfast": "",
"lunch": "",
"dinner": ""
}
]
def create(event, context):
response = {}
try:
# select data
data = json.loads(event['body'])
# reference table
table = dynamodb.Table(os.environ['DYNAMODB_TABLE'])
# if username not in body then raise exception
if 'username' not in data:
logging.error("Validation Failed")
raise NameError("username is not provided")
timestamp = int(time.time() * 1000)
# create initial set of meals and then return
item = {
'username': data["username"],
'meals': initialMeals,
'createdAt': timestamp,
'updatedAt': timestamp,
}
# write the todo to the database
table.put_item(Item=item)
response = {
"statusCode": 200,
"headers": {'Access-Control-Allow-Origin': '*'},
"body": json.dumps(item['meals'],
cls=decimalencoder.DecimalEncoder)
}
except NameError as nameError:
nameBody = str("Name error: {0}".format(nameError))
response = {
"statusCode": 500,
"headers": {'Access-Control-Allow-Origin': '*'},
"body": nameBody
}
except:
errorBody = traceback.format_exc()
response = {
"statusCode": 500,
"headers": {'Access-Control-Allow-Origin': '*'},
"body": errorBody
}
return response
關于 CORS,響應包括:
"headers": {'Access-Control-Allow-Origin': '*'},
這樣,響應就可以為任何使用您的 API 的應用程序傳遞一個“印前檢查清單”。當我第一次使用無服務器技術時,我發現解決將 API 連接到我構建的前端應用程序時遇到的各種 CORS 錯誤有些困難。盡管這些信息在無服務器網站上有所記錄,但我認為此配置就是通過 CORS 所需的全部配置。顯然,您也可以將應用程序鎖定到特定域。
yaml 文件的最后一部分是定義資源。您可以在此處定義 DynamoDB 表名稱等內容:
resources:
Resources:
MealsDynamoDBTable:
Type: "AWS::DynamoDB::Table"
DeletionPolicy: Retain
Properties:
AttributeDefinitions:
- AttributeName: username
AttributeType: S
KeySchema:
- AttributeName: username
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DYNAMODB_TABLE}
因此,為了在 AWS Lambda 中定義處理程序,您可以使用與構建控制臺幾乎相同的方法。我分享了上面的文件:create.py 和 get.py。
import os
import json
import logging
from meals import decimalencoder
import boto3
from boto3.dynamodb.conditions import Key
import traceback
dynamodb = boto3.resource('dynamodb')
def get(event, context):
response = {}
try:
# select data
data = json.loads(event['body'])
# reference table
table = dynamodb.Table(os.environ['DYNAMODB_TABLE'])
# if username not in body then raise exception
if 'username' not in data:
logging.error("Validation Failed")
raise NameError("username is not provided")
result = table.query(
KeyConditionExpression=Key('username').eq(data["username"])
)
response = {
"statusCode": 200,
"headers": { 'Access-Control-Allow-Origin': '*' },
"body": json.dumps(result['Items'],
cls=decimalencoder.DecimalEncoder)
}
except NameError as nameError:
nameBody = str("Name error: {0}".format(nameError))
response = {
"statusCode": 500,
"headers": { 'Access-Control-Allow-Origin': '*' },
"body": nameBody
}
except:
errorBody = traceback.format_exc()
response = {
"statusCode": 500,
"headers": { 'Access-Control-Allow-Origin': '*' },
"body": errorBody
}
return response
如您所見,您定義了一個處理程序,然后由 AWS Lambda 使用。AWS 對此有很好的記錄,因此我不打算在此之后進行太多討論。一般您只需定義處理程序,然后在 severless.yml文件中引用它們。當您準備好部署時,無服務器 CLI 會將它們全部打包并為您部署。
因此,一旦你已經構建了 API,你就可以繼續部署它。如前所述,Serverless CLI 使用您的 AWS 憑證來部署您的項目。您需要先設置 AWS CLI,然后才能部署項目。完成此操作后,打開一個終端輸入“serverless deploy”并轉到項目運行以查看其運行情況:
創建完項目后,您應該會看到如下所示:
如果您注意到,最后一條消息會為您提供一組與您的函數對應的終端節點。這些終端節點都具有相同的基 URL,因為它們由 AWS API Gateway 托管。所以它們都是單個項目中的路由。
您可以獲取終端節點并將它們與 postman 掛鉤,然后查看結果:
如果您進入 AWS 控制臺,則可以查看創建的內容。以下是 API Gateway 中的路由:
您還可以在 AWS 控制臺的 Cloud Formation 模板中查看堆棧:
當您準備好關閉項目時,您可以返回到項目的終端并運行“serverless remove
”,這將刪除已創建的堆棧。
我非常希望您能喜歡這篇文章,并在此過程中對無服務器框架有所了解。我已經在多個項目中使用了無服務器框架,并獲得了很好的體驗。它的文檔記錄的很詳細,且提供了豐富的示例來幫助您入門。除了我們示例中提到的創建“PRD”環境外,使用無服務器框架還可以實現許多其他酷炫的功能,比如設置定時任務(cron jobs)等。強烈建議您訪問 serverless framework 的官方文檔頁面,那里有更多詳細的信息和指導。
原文鏈接:https://andrewevans.dev/blog/2021-07-09-building-an-api-with-the-serverless-framework/