介绍
订单团队需要接收 JSON 订单并返回计算总额。你将把健康检查、写入和读取路由连接到提供的 Lambda 应用,测试有效请求和被拒绝的请求,并在清理前检查存储的 DynamoDB 记录。
请先完成 通过 HTTP API 暴露 Lambda 函数 和 通过 Lambda 读取和写入 DynamoDB。这个全新环境提供应用、角色和独立的表。
认证考点
| 认证 | 考点 | 本实验练习 |
|---|---|---|
| Solutions Architect – Associate (SAA-C03) | 任务 2.1 | API 请求验证、响应与持久化业务数据。 |
| Developer – Associate (DVA-C02) | 任务 1.1, 任务 3.2 | API 请求验证、响应与持久化业务数据。 |
| DevOps Engineer – Professional (DOP-C02) | 任务 3.2 | 基础练习:API 请求验证、响应与持久化业务数据。 |
实验概览

准备订单后端
本步骤中,你将检查提供的请求约定,授予函数访问订单表的权限,并部署后端。应用以整数分计算金额:数量 × 250 + 100 分处理费。使用上方的 AWS View,比较请求与存储数据。
进入工作目录并读取应用:
cd /home/labex/project
cat app.py
handler 接收 HTTP 载荷格式 2.0。POST /orders 要求 JSON 恰好包含两个字段:一个长度为 2–40 个字符的小写 id,以字母开头,只使用字母、数字或连字符;以及一个 1 到 10 之间的整数 quantity。代码在 PutItem 前拒绝其他结构。GET /orders?id=... 使用 GetItem 读取存储记录。每个响应包含 HTTP 状态和 JSON 响应体。无需重写提供的应用。
读取准备好的表清单:
aws dynamodb list-tables --query TableNames
预期看到 labex-a02-orders 和 labex-a02-reference。只有订单表用于这个 API 的业务操作。将它的 ARN 读入 shell 变量:
TABLE_ARN=$(aws dynamodb describe-table \
--table-name labex-a02-orders \
--query Table.TableArn \
--output text)
echo "$TABLE_ARN"
执行角色控制出站数据库访问。使用 here-document 创建策略文件。不带引号的 JSON 标记允许将 $TABLE_ARN 展开为刚读取的 ARN;其中不包含凭证:
cat > orders-policy.json <<JSON
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["dynamodb:PutItem", "dynamodb:GetItem"],
"Resource": "$TABLE_ARN"
}]
}
JSON
将这个具名内联策略附加到准备好的执行角色:
aws iam put-role-policy \
--role-name labex-a02-execution \
--policy-name OrdersData \
--policy-document file://orders-policy.json
打包提供的代码,将 app.py 放在归档文件根目录:
zip orders.zip app.py
读取准备好的角色 ARN:
ROLE_ARN=$(aws iam get-role \
--role-name labex-a02-execution \
--query Role.Arn \
--output text)
echo "$ROLE_ARN"
以十秒超时部署函数。应用从环境中读取 TABLE_NAME,使表选择与源代码分离:
aws lambda create-function \
--function-name labex-a02-orders-api \
--runtime python3.12 \
--handler app.handler \
--role "$ROLE_ARN" \
--timeout 10 \
--environment '{"Variables":{"TABLE_NAME":"labex-a02-orders"}}' \
--zip-file fileb://orders.zip \
--query '{Name:FunctionName,Handler:Handler,Table:Environment.Variables.TABLE_NAME}'
预期看到函数名称、app.handler 和 labex-a02-orders。在 AWS View 中检查 Function 卡片,并确认订单表仍有零个项目。部署代码和授予数据访问权限不会创建订单。
映射健康检查和订单路由
本步骤中,你将为三个路由配置一个集成,并授予每个路由调用函数的权限。
创建 HTTP API 并保存 ID:
API_ID=$(aws apigatewayv2 create-api \
--name labex-a02 \
--protocol-type HTTP \
--query ApiId \
--output text)
echo "$API_ID"
printf '%s\n' "$API_ID" > api-id.txt
创建名称为字面值 $default 的阶段,并启用自动部署:
aws apigatewayv2 create-stage \
--api-id "$API_ID" \
--stage-name '$default' \
--auto-deploy \
--query '{Stage:StageName,AutoDeploy:AutoDeploy}'
读取后端 ARN,创建载荷 2.0 集成。它的 POST 方法用于调用 Lambda;每个客户端路由仍有自己的 HTTP 方法:
FUNCTION_ARN=$(aws lambda get-function-configuration \
--function-name labex-a02-orders-api \
--query FunctionArn \
--output text)
echo "$FUNCTION_ARN"
INTEGRATION_ID=$(aws apigatewayv2 create-integration \
--api-id "$API_ID" \
--integration-type AWS_PROXY \
--integration-method POST \
--integration-uri "$FUNCTION_ARN" \
--payload-format-version 2.0 \
--query IntegrationId \
--output text)
echo "$INTEGRATION_ID"
将公开健康检查端点映射到这个集成:
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'GET /health' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
映射 JSON 写入路由:
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'POST /orders' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
映射存储订单的读取路由:
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'GET /orders' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
执行角色的数据库策略不会允许 API Gateway 调用函数。读取账户 ID,再添加三个准确的调用授权。每条语句使用 API ID、字面值 $default、客户端方法和路由路径;\$ 在展开的 shell 字符串中保留美元符号:
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo "$ACCOUNT_ID"
aws lambda add-permission \
--function-name labex-a02-orders-api \
--statement-id ApiHealth \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-account "$ACCOUNT_ID" \
--source-arn "arn:aws:execute-api:us-east-1:$ACCOUNT_ID:$API_ID/\$default/GET/health" \
--query Statement \
--output text
aws lambda add-permission \
--function-name labex-a02-orders-api \
--statement-id ApiWriteOrder \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-account "$ACCOUNT_ID" \
--source-arn "arn:aws:execute-api:us-east-1:$ACCOUNT_ID:$API_ID/\$default/POST/orders" \
--query Statement \
--output text
aws lambda add-permission \
--function-name labex-a02-orders-api \
--statement-id ApiReadOrder \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-account "$ACCOUNT_ID" \
--source-arn "arn:aws:execute-api:us-east-1:$ACCOUNT_ID:$API_ID/\$default/GET/orders" \
--query Statement \
--output text
使用生成的 ID 构造准备好的工作环境 API 地址。这个地址在工作环境内提供请求服务,不是 AWS 公共主机名:
API_URL="http://127.0.0.1:8081/api/$API_ID"
echo "$API_URL"
测试健康检查路由。curl -i 包含 HTTP 响应头:
curl -i "$API_URL/health"
预期得到 HTTP 200 和 {"healthy": true}。在 AWS View 中确认三个路由键都使用 NONE,阶段已启用 AutoDeploy,健康检查调用返回 200。订单表仍应为空,因为这个请求检查健康状态,不会存储订单。

测试有效订单和被拒绝的请求
本步骤中,你将创建两个订单,读取存储结果,并检查失败请求在影响业务数据前是否被拒绝。
HTTP 请求由方法、路径、请求头和可选的请求体组成。-X POST 选择写入方法,-H 提供 Content-Type: application/json,--data 发送 JSON 字符串。创建数量为 2 的订单:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"order-one","quantity":2}'
预期得到 HTTP 201 Created,响应体包含 order-one、数量 2 和 total_cents: 600(2 × 250 + 100)。状态告诉客户端订单已存储;响应体报告计算结果。
使用不同数量创建第二个订单:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"order-two","quantity":5}'
预期得到 HTTP 201 和 total_cents: 1350。通过 API 使用查询参数读取两个订单:
curl -i "$API_URL/orders?id=order-one"
curl -i "$API_URL/orders?id=order-two"
两个响应都应为 HTTP 200,且 ID、数量和总额与对应的创建响应相同。读取处理程序获取 DynamoDB 状态,不会根据客户端提供的新数量重新计算总额。
使用 CLI 独立检查第一个存储项目:
aws dynamodb get-item \
--table-name labex-a02-orders \
--key '{"id":{"S":"order-one"}}' \
--consistent-read \
--query Item
带类型的项目包含 quantity: {"N":"2"} 和 total_cents: {"N":"600"}。在 AWS View 中,将两条实际表记录与 POST 和 GET 调用响应进行比较。
语法有效的 JSON 请求也可能违反业务约定。发送负数数量:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"bad-negative","quantity":-1}'
预期得到 HTTP 400 Bad Request 和 Use an id and an integer quantity from 1 to 10。编码为 JSON 字符串的数字也会被拒绝:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"bad-type","quantity":"2"}'
最后,测试格式错误的 JSON 请求体:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{not-json'
最后两个请求也返回 HTTP 400。它们实际的处理程序事件可能出现在 CloudWatch Logs 中,但表仍必须只包含两个有效订单。请求验证在提供的应用中、PutItem 之前执行;仅匹配 API 路由不会验证请求体。
有效的读取 ID 可能没有对应的存储订单。查询一个尚未创建的 ID:
curl -i "$API_URL/orders?id=missing-order"
预期得到 HTTP 404 和 Order not found。这与 400 无效请求不同:ID 格式符合要求,但项目不存在。查看上方的 AWS View,检查实际的 201、200、400 和 404 响应;展开某次调用的 Show logs,比较输入与结果。这项手动 UI 检查补充了对远端记录和实际执行的独立只读检查。

向下滚动到 DynamoDB tables 卡片,在自己的环境中比较这些字段。
这里的 400 响应检验应用校验:请求到达 Lambda,由函数在写入前拒绝输入。后续 JWT 拒绝会在 API Gateway 阻止请求,使其无法到达 Lambda。结合执行日志和存储记录,判断是哪一层边界拒绝了请求。
移除 API 和本实验的订单资源
本步骤中,你将删除 API 的资源,同时保留无关的参考表、日志和准备好的执行角色。
你的资源清单包括 api-id.txt 中的 API ID、labex-a02-orders-api、它的 /aws/lambda/labex-a02-orders-api 日志组、labex-a02-orders,以及 OrdersData 内联角色策略。先删除 API,包括它的路由、集成和默认阶段:
aws apigatewayv2 delete-api --api-id "$API_ID"
移除函数及其调用策略:
aws lambda delete-function --function-name labex-a02-orders-api
删除独立的函数日志组:
aws logs delete-log-group --log-group-name /aws/lambda/labex-a02-orders-api
删除本实验的订单表及其数据:
aws dynamodb delete-table \
--table-name labex-a02-orders \
--query TableDescription.TableName \
--output text
仅移除你添加到准备好的角色中的数据策略:
aws iam delete-role-policy --role-name labex-a02-execution --policy-name OrdersData
成功读取资源清单以证明删除完成。身份验证或网络错误不能作为删除证据:
aws apigatewayv2 get-apis --query 'Items[].Name'
aws lambda list-functions --query 'Functions[].FunctionName'
aws dynamodb list-tables --query TableNames
前两个列表应为空;表列表应只包含 labex-a02-reference。确认它的原始项目仍然存在:
aws dynamodb get-item \
--table-name labex-a02-reference \
--key '{"id":{"S":"reference"}}' \
--query Item
预期看到 message: {"S":"keep unchanged"}。角色仍应保留无关的日志策略:
aws iam list-role-policies --role-name labex-a02-execution --query PolicyNames
预期只有 FunctionLogs。在 AWS View 中,API、Function 和调用记录应消失,参考表和 INFO platform reference keep unchanged 仍然保留。保留这些准备好的资源;测试凭证和 VM 关闭在资源检查之后处理。
总结
你使用准确的数据库策略和 API 调用授权,将三个 HTTP 路由连接到提供的 Lambda 应用。你创建并读取了计算总额不同的订单,检查了实际 DynamoDB 记录,并区分了成功、无效和订单不存在的响应。随后,你移除了 API 及其数据、函数、日志和策略,同时保留了参考资源。
进一步阅读 AWS 官方资料:HTTP API 的 Lambda 事件与响应格式; HTTP API 路由与查询参数。



