Conceitos básicos da AWS
Crie uma aplicação Web sem servidor
com o AWS Lambda, Amazon API Gateway, AWS Amplify, Amazon DynamoDB e Amazon Cognito
Módulo 3: Serviço de backend sem servidor
Você usará o AWS Lambda e o Amazon DynamoDB para criar um processo de backend para processar solicitações de sua aplicação Web.
Visão geral
Neste módulo, você usará o AWS Lambda e o Amazon DynamoDB para criar um processo de backend para processar solicitações de sua aplicação Web. A aplicação do navegador que você implantou no primeiro módulo permite que os usuários solicitem o envio de um unicórnio para um local escolhido por eles. Para processar essas solicitações, o JavaScript executado no navegador precisará invocar um serviço executado na nuvem.
Visão geral da arquitetura
![Visão geral da arquitetura Visão geral da arquitetura](https://d1.awsstatic.com/Test%20Images/Kate%20Test%20Images/Serverless_Web_App_LP_assets_04.76030d61413ff43bd6aa75fbd16e02ad23aec67a.png)
Você implementará uma função do Lambda que será invocada sempre que um usuário solicitar um unicórnio. A função vai selecionar um unicórnio da frota, gravar a solicitação em uma tabela do DynamoDB e, então, responder a aplicação de front-end com detalhes sobre o unicórnio que será despachado.
A função é invocada do navegador usando o Amazon API Gateway. Você implementará essa conexão no próximo módulo. Para este módulo, você apenas testará sua função em isolamento.
Tempo para a conclusão
30 minutos
Serviços usados
Implementação
-
Criar uma tabela do Amazon DynamoDB
Use o console do Amazon DynamoDB para criar uma nova tabela do DynamoDB.
- No console do Amazon DynamoDB, escolha Criar tabela.
- Insira Ridescomo o Nome da tabela. Esse campo diferencia letras maiúsculas de minúsculas.
- Insira RideId para a Chave de partição e selecione String para o tipo de chave. Esse campo diferencia letras maiúsculas de minúsculas.
- Na seção Configurações da tabela, verifique se as Configurações padrão estão selecionadas e escolha Criar tabela.
- Na página Tabelas, aguarde a conclusão da criação da tabela. Depois de concluído, o status será Ativo. Selecione o nome da sua tabela.
- Na guia Visão geral > seção Informações gerais da sua nova tabela, escolha Informações adicionais. Copie o ARN. Ele será usado na próxima seção.
-
Criar um perfil do IAM para sua função do Lambda
Cada função do Lambda tem um perfil do IAM associado a ela. Essa função define com quais outros serviços da AWS a função tem permissão para interagir. Para os fins deste tutorial, você precisará criar um perfil do IAM que conceda permissão à função do Lambda para gravar logs no Amazon CloudWatch Logs e acesso para gravar itens na tabela do DynamoDB.
- No console do IAM, selecione Perfis no painel de navegação esquerdo e escolha Criar perfil.
- Na seção Tipo de entidade confiável, selecione Serviço da AWS. Em Caso de uso, selecione Lambda e, em seguida, escolha Avançar.
Observação: selecionar um tipo de perfil automaticamente cria uma política de confiança para o perfil que permite que os serviços da AWS assumam esse perfil em seu nome. Se estiver criando essa função a partir da CLI, do AWS CloudFormation ou de outro mecanismo, especifique diretamente uma política de confiança. - Insira AWSLambdaBasicExecutionRole na caixa de texto do filtro e pressione Enter.
- Marque a caixa de seleção ao lado do nome da política AWSLambdaBasicExecutionRole e escolha Avançar.
- Insira WildRydesLambda como Nome do perfil. Mantenha as configurações padrão para os outros parâmetros.
- Selecione Criar perfil.
- Na caixa de filtro na página Perfis, digite WildRydesLambda e selecione o nome do perfil que você acabou de criar.
- Na guia Permissões, escolha Adicionar permissões e, em seguida, escolha Criar política em linha.
- Na seção Selecionar um serviço, digite DynamoDB na barra de pesquisa e selecione DynamoDB quando ele aparecer.
- Escolha Selecionar ações.
- Na seção Ações permitidas, digite PutItem na barra de pesquisa e marque a caixa de seleção ao lado de PutItem quando ela aparecer.
- Na seção Recursos, com a opção Específico selecionada, selecione o link Adicionar ARN na seção tabela.
- Selecione a guia Texto. Cole o ARN da tabela que você criou no DynamoDB (Etapa 6 na seção anterior) e escolha Adicionar ARNs.
- Escolha Próxima.
- Insira DynamoDBWriteAccess para o nome da política e selecione Criar política.
-
Criar uma função do Lambda para processar solicitações
O AWS Lambda executará seu código como resposta a eventos como uma solicitação HTTP. Nesta etapa, você criará a função básica que processará solicitações de API a partir do aplicativo web para despachar um unicórnio. No próximo módulo, você usará o Amazon API Gateway para criar uma API RESTful que vai expor um endpoint HTTP que pode ser invocado a partir dos navegadores dos usuários. Você se conectará a função do Lambda criada nesta etapa a essa API para criar um backend totalmente funcional para sua aplicação Web.
Use o console do AWS Lambda para criar uma função do Lambda chamada RequestUnicorn, que processará as solicitações de API. Use a implementação de exemplo do requestUnicorn.js a seguir para o código da função. Basta copiar e colar daquele arquivo para o editor do console do AWS Lambda.
Certifique-se de configurar sua função para usar o perfil do IAM WildRydesLambda criado na seção anterior.
- No console do AWS Lambda, escolha Criar função.
- Mantenha o cartão padrão Criar do zero selecionado.
- Insira RequestUnicorn no campo Nome da função.
- Selecione Node.js 16.x para o Runtime (as versões mais recentes do Node.js não funcionarão neste tutorial).
- Selecione Usar um perfil existente no menu suspenso Alterar perfil de execução padrão.
- Selecione WildRydesLambda na lista suspensa Perfil existente.
- Clique em Criar função.
- Role para baixo até a seção Origem do código e substitua o código existente no editor de código index.js pelo conteúdo de requestUnicorn.js. O bloco de código a seguir exibe o arquivo requestUnicorn.js. Copie e cole esse código na guia index.js do editor de código.
const randomBytes = require('crypto').randomBytes; const AWS = require('aws-sdk'); const ddb = new AWS.DynamoDB.DocumentClient(); const fleet = [ { Name: 'Angel', Color: 'White', Gender: 'Female', }, { Name: 'Gil', Color: 'White', Gender: 'Male', }, { Name: 'Rocinante', Color: 'Yellow', Gender: 'Female', }, ]; exports.handler = (event, context, callback) => { if (!event.requestContext.authorizer) { errorResponse('Authorization not configured', context.awsRequestId, callback); return; } const rideId = toUrlString(randomBytes(16)); console.log('Received event (', rideId, '): ', event); // Because we're using a Cognito User Pools authorizer, all of the claims // included in the authentication token are provided in the request context. // This includes the username as well as other attributes. const username = event.requestContext.authorizer.claims['cognito:username']; // The body field of the event in a proxy integration is a raw string. // In order to extract meaningful values, we need to first parse this string // into an object. A more robust implementation might inspect the Content-Type // header first and use a different parsing strategy based on that value. const requestBody = JSON.parse(event.body); const pickupLocation = requestBody.PickupLocation; const unicorn = findUnicorn(pickupLocation); recordRide(rideId, username, unicorn).then(() => { // You can use the callback function to provide a return value from your Node.js // Lambda functions. The first parameter is used for failed invocations. The // second parameter specifies the result data of the invocation. // Because this Lambda function is called by an API Gateway proxy integration // the result object must use the following structure. callback(null, { statusCode: 201, body: JSON.stringify({ RideId: rideId, Unicorn: unicorn, Eta: '30 seconds', Rider: username, }), headers: { 'Access-Control-Allow-Origin': '*', }, }); }).catch((err) => { console.error(err); // If there is an error during processing, catch it and return // from the Lambda function successfully. Specify a 500 HTTP status // code and provide an error message in the body. This will provide a // more meaningful error response to the end client. errorResponse(err.message, context.awsRequestId, callback) }); }; // This is where you would implement logic to find the optimal unicorn for // this ride (possibly invoking another Lambda function as a microservice.) // For simplicity, we'll just pick a unicorn at random. function findUnicorn(pickupLocation) { console.log('Finding unicorn for ', pickupLocation.Latitude, ', ', pickupLocation.Longitude); return fleet[Math.floor(Math.random() * fleet.length)]; } function recordRide(rideId, username, unicorn) { return ddb.put({ TableName: 'Rides', Item: { RideId: rideId, User: username, Unicorn: unicorn, RequestTime: new Date().toISOString(), }, }).promise(); } function toUrlString(buffer) { return buffer.toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=/g, ''); } function errorResponse(errorMessage, awsRequestId, callback) { callback(null, { statusCode: 500, body: JSON.stringify({ Error: errorMessage, Reference: awsRequestId, }), headers: { 'Access-Control-Allow-Origin': '*', }, }); }
9. Escolha Implantar.
-
Validar sua implementação
Para este módulo, você testará a função criada usando o console do AWS Lambda. No próximo módulo, você adicionará uma API REST com o API Gateway para poder invocar sua função a partir da aplicação baseada em navegador implantado no primeiro módulo.
- Na função RequestUnicorn que você criou na seção anterior, escolha Testar na seção Origem do código e selecione Configurar evento de teste no menu suspenso.
- Mantenha a seleção padrão de Criar novo evento.
- Insira TestRequestEvent no campo Nome do evento.
- Copie e cole o seguinte evento de teste na seção JSON do evento:
{ "path": "/ride", "httpMethod": "POST", "headers": { "Accept": "*/*", "Authorization": "eyJraWQiOiJLTzRVMWZs", "content-type": "application/json; charset=UTF-8" }, "queryStringParameters": null, "pathParameters": null, "requestContext": { "authorizer": { "claims": { "cognito:username": "the_username" } } }, "body": "{\"PickupLocation\":{\"Latitude\":47.6174755835663,\"Longitude\":-122.28837066650185}}" }
5. Escolha Save (Salvar).
6. Na seção Origem do código da sua função, escolha Testar e selecione TestRequestEvent no menu suspenso.
7. Na guia Testar, escolha Testar.
8. Na mensagem Executando função: êxito exibida, expanda o menu suspenso Detalhes.
9. Verifique se o resultado da função se parece com o seguinte:
{ "statusCode": 201, "body": "{\"RideId\":\"SvLnijIAtg6inAFUBRT+Fg==\",\"Unicorn\":{\"Name\":\"Rocinante\",\"Color\":\"Yellow\",\"Gender\":\"Female\"},\"Eta\":\"30 seconds\"}", "headers": { "Access-Control-Allow-Origin": "*" } }