Introdução
Uma equipe de pedidos precisa aceitar pedidos JSON e retornar totais calculados. Você conectará rotas de saúde, gravação e leitura a uma aplicação Lambda fornecida, testará solicitações válidas e rejeitadas e verificará os registros armazenados no DynamoDB antes da limpeza.
Conclua primeiro Exponha uma Função Lambda com uma HTTP API e Leia e Grave no DynamoDB a partir do Lambda. Este ambiente novo fornece a aplicação, a função IAM e tabelas separadas.
Relação com as certificações
| Certificação | Tarefa do exame | Prática |
|---|---|---|
| Solutions Architect – Associate (SAA-C03) | Tarefa 2.1 | Validação de solicitações API, respostas e dados de negócio persistidos. |
| Developer – Associate (DVA-C02) | Tarefa 1.1, Tarefa 3.2 | Validação de solicitações API, respostas e dados de negócio persistidos. |
| DevOps Engineer – Professional (DOP-C02) | Tarefa 3.2 | Prática dos fundamentos: Validação de solicitações API, respostas e dados de negócio persistidos. |
Visão geral do laboratório

Prepare o Backend de Pedidos
Nesta etapa, você inspecionará o contrato de solicitação fornecido, concederá à função acesso à sua tabela de pedidos e implantará o backend. A aplicação calcula centavos inteiros: quantidade × 250 + uma taxa de processamento de 100 centavos. Use AWS View na parte superior para comparar solicitações com dados armazenados.
Entre no diretório de trabalho e leia a aplicação:
cd /home/labex/project
cat app.py
handler recebe o formato de payload HTTP 2.0. POST /orders espera exatamente dois campos JSON: um id em minúsculas de 2–40 caracteres que comece com uma letra e use letras, dígitos ou hífens, e uma quantity inteira de 1 a 10. O código rejeita outros formatos antes de PutItem. GET /orders?id=... lê o registro armazenado com GetItem. Cada resposta contém um status HTTP e um corpo JSON. Você não precisa reescrever esta aplicação fornecida.
Leia o inventário de tabelas preparado:
aws dynamodb list-tables --query TableNames
Espere labex-a02-orders e labex-a02-reference. Apenas a tabela de pedidos pertence ao trabalho de negócio desta API. Leia seu ARN em uma variável do shell:
TABLE_ARN=$(aws dynamodb describe-table \
--table-name labex-a02-orders \
--query Table.TableArn \
--output text)
echo "$TABLE_ARN"
A função de execução controla o acesso de saída ao banco de dados. Use um heredoc para criar um arquivo de política. O marcador JSON sem aspas permite que $TABLE_ARN seja expandido para o ARN recém-lido; ele não contém credenciais:
cat > orders-policy.json <<JSON
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["dynamodb:PutItem", "dynamodb:GetItem"],
"Resource": "$TABLE_ARN"
}]
}
JSON
Anexe esta política inline nomeada à função de execução preparada:
aws iam put-role-policy \
--role-name labex-a02-execution \
--policy-name OrdersData \
--policy-document file://orders-policy.json
Empacote o código fornecido com app.py na raiz do arquivo compactado:
zip orders.zip app.py
Leia o ARN da função IAM preparada:
ROLE_ARN=$(aws iam get-role \
--role-name labex-a02-execution \
--query Role.Arn \
--output text)
echo "$ROLE_ARN"
Implante a função com um tempo limite de dez segundos. A aplicação lê TABLE_NAME de seu ambiente, mantendo a seleção da tabela separada do código-fonte:
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}'
Espere o nome da função, app.handler e labex-a02-orders. No AWS View, inspecione o cartão Function e confirme que a tabela de pedidos ainda tem zero itens. Implantar código e conceder acesso a dados não cria um pedido.
Mapeie Rotas de Saúde e Pedidos
Nesta etapa, você configurará uma integração para três rotas e concederá a cada rota permissão para invocar a função.
Crie uma HTTP API e salve seu 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
Crie o estágio literal $default com implantação automática:
aws apigatewayv2 create-stage \
--api-id "$API_ID" \
--stage-name '$default' \
--auto-deploy \
--query '{Stage:StageName,AutoDeploy:AutoDeploy}'
Leia o ARN do backend e crie a integração de payload 2.0. Seu método POST invoca o Lambda; cada rota de cliente ainda tem seu próprio método 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"
Mapeie o endpoint público de saúde para esta integração:
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'GET /health' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
Mapeie a rota de gravação JSON:
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'POST /orders' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
Mapeie a rota de leitura de pedidos armazenados:
aws apigatewayv2 create-route \
--api-id "$API_ID" \
--route-key 'GET /orders' \
--target "integrations/$INTEGRATION_ID" \
--authorization-type NONE \
--query RouteKey \
--output text
A política de banco de dados da função de execução não permite que o API Gateway invoque a função. Leia o ID da conta e adicione três concessões precisas de invocação. Cada declaração usa o ID da API, o $default literal, o método do cliente e o caminho da rota; \$ preserva o sinal de dólar em uma string expandida do 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
Construa o endereço preparado da API do ambiente de trabalho usando seu ID gerado. Esse endereço atende a solicitações dentro do ambiente de trabalho e não é um hostname público da AWS:
API_URL="http://127.0.0.1:8081/api/$API_ID"
echo "$API_URL"
Teste a rota de saúde. curl -i inclui os cabeçalhos da resposta HTTP:
curl -i "$API_URL/health"
Espere HTTP 200 e {"healthy": true}. No AWS View, confirme que as três chaves de rota têm NONE, que o estágio tem AutoDeploy habilitado e que a invocação de saúde retornou 200. A tabela de pedidos ainda deve estar vazia, pois essa solicitação verifica a saúde em vez de armazenar um pedido.

Teste Pedidos Válidos e Solicitações Rejeitadas
Nesta etapa, você criará dois pedidos, lerá seus resultados armazenados e verificará falhas antes que elas possam afetar os dados de negócio.
Uma solicitação HTTP consiste em um método, caminho, cabeçalhos e corpo opcional. -X POST escolhe o método de gravação, -H fornece Content-Type: application/json e --data envia a string JSON. Crie um pedido com quantidade 2:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"order-one","quantity":2}'
Espere HTTP 201 Created e um corpo contendo order-one, quantidade 2 e total_cents: 600 (2 × 250 + 100). O status informa ao cliente que um pedido foi armazenado; o corpo informa o resultado calculado.
Crie um segundo pedido com uma quantidade diferente:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"order-two","quantity":5}'
Espere HTTP 201 e total_cents: 1350. Leia ambos os pedidos pela API usando seu parâmetro de consulta:
curl -i "$API_URL/orders?id=order-one"
curl -i "$API_URL/orders?id=order-two"
Ambas as respostas devem ser HTTP 200 com o mesmo ID, quantidade e total da resposta de criação correspondente. O manipulador de leitura recupera o estado do DynamoDB, em vez de recalcular o total a partir de uma nova quantidade enviada pelo cliente.
Inspecione de forma independente o primeiro item armazenado com a CLI:
aws dynamodb get-item \
--table-name labex-a02-orders \
--key '{"id":{"S":"order-one"}}' \
--consistent-read \
--query Item
O item tipado contém quantity: {"N":"2"} e total_cents: {"N":"600"}. No AWS View, compare os dois registros reais da tabela com as respostas das invocações POST e GET.
Uma solicitação JSON sintaticamente válida ainda pode violar o contrato de negócio. Envie uma quantidade negativa:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"bad-negative","quantity":-1}'
Espere HTTP 400 Bad Request e Use an id and an integer quantity from 1 to 10. Um número codificado como string JSON também é rejeitado:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{"id":"bad-type","quantity":"2"}'
Por fim, teste um corpo JSON malformado:
curl -i -X POST "$API_URL/orders" -H 'Content-Type: application/json' --data '{not-json'
As duas últimas solicitações também retornam HTTP 400. Seus eventos reais do manipulador podem aparecer no CloudWatch Logs, mas a tabela ainda deve conter apenas os dois pedidos válidos. A validação de solicitações ocorre na aplicação fornecida antes de PutItem; uma rota de API correspondente sozinha não valida seu corpo.
Um ID de leitura válido pode não corresponder a nenhum pedido armazenado. Consulte um que não tenha sido criado:
curl -i "$API_URL/orders?id=missing-order"
Espere HTTP 404 com Order not found. Isso difere de uma solicitação inválida 400: o ID tem o formato esperado, mas nenhum item existe. Observe AWS View na parte superior e inspecione as respostas reais 201, 200, 400 e 404; expanda Show logs de uma invocação para comparar sua entrada com seu resultado. Esta inspeção manual da interface complementa as verificações independentes e somente de leitura dos registros remotos e das execuções reais.

Role até o cartão DynamoDB tables para comparar esses campos em seu ambiente.
Essas respostas 400 testam a validação da aplicação: a solicitação chega ao Lambda, que rejeita a entrada antes de gravar. A rejeição JWT estudada depois interrompe a solicitação no API Gateway antes do Lambda. Compare o log de execução e os itens armazenados para identificar qual limite rejeitou a solicitação.
Remova a API e os Recursos de Pedidos do Laboratório
Nesta etapa, você excluirá os recursos da API, preservando a tabela de referência não relacionada, os logs e a função de execução preparada.
Seu inventário consiste no ID de API em api-id.txt, em labex-a02-orders-api, em seu grupo de logs /aws/lambda/labex-a02-orders-api, em labex-a02-orders e na política inline OrdersData da função IAM. Exclua a API primeiro, incluindo suas rotas, integração e estágio padrão:
aws apigatewayv2 delete-api --api-id "$API_ID"
Remova a função e sua política de invocação:
aws lambda delete-function --function-name labex-a02-orders-api
Exclua o grupo de logs separado da função:
aws logs delete-log-group --log-group-name /aws/lambda/labex-a02-orders-api
Exclua a tabela de pedidos do laboratório e seus dados:
aws dynamodb delete-table \
--table-name labex-a02-orders \
--query TableDescription.TableName \
--output text
Remova apenas a política de dados que você adicionou à função IAM preparada:
aws iam delete-role-policy --role-name labex-a02-execution --policy-name OrdersData
Leia os inventários com sucesso para comprovar a exclusão. Erros de autenticação ou rede não são evidências de exclusão:
aws apigatewayv2 get-apis --query 'Items[].Name'
aws lambda list-functions --query 'Functions[].FunctionName'
aws dynamodb list-tables --query TableNames
As duas primeiras listas devem estar vazias; a lista de tabelas deve conter apenas labex-a02-reference. Confirme que seu item original permanece:
aws dynamodb get-item \
--table-name labex-a02-reference \
--key '{"id":{"S":"reference"}}' \
--query Item
Espere message: {"S":"keep unchanged"}. A função IAM ainda deve manter sua política de logs não relacionada:
aws iam list-role-policies --role-name labex-a02-execution --query PolicyNames
Espere apenas FunctionLogs. No AWS View, API, Function e registros de invocação devem ter desaparecido, enquanto a tabela de referência e INFO platform reference keep unchanged permanecem. Mantenha esses recursos preparados; as credenciais de teste e o encerramento da VM são tratados após as verificações de recursos.
Resumo
Você conectou três rotas HTTP a uma aplicação Lambda fornecida, com uma política precisa de banco de dados e concessões de invocação da API. Você criou e recuperou pedidos com diferentes totais calculados, verificou registros reais do DynamoDB e distinguiu respostas bem-sucedidas, inválidas e de pedido ausente. Depois, removeu a API e seus dados, função, logs e política do laboratório, preservando os recursos de referência.
Para aprofundar o tema, consulte a documentação da AWS: Eventos Lambda de HTTP API e formatos de resposta; Rotas HTTP API e parâmetros de consulta.



