Tutorial: uso de AWS Lambda con Amazon API Gateway - AWS Lambda

Tutorial: uso de AWS Lambda con Amazon API Gateway

En este ejemplo se crea una API sencilla utilizando Amazon API Gateway. Una instancia de Amazon API Gateway es un conjunto de recursos y métodos. En este tutorial, se crea un recurso (DynamoDBManager) y se define un método (POST) en él. El método está respaldado por una función de Lambda (LambdaFunctionOverHttps). Es decir, cuando se llama al API a través de un punto de enlace HTTPS, Amazon API Gateway invoca la función de Lambda.

El método POST del recurso DynamoDBManager admite las siguientes operaciones de DynamoDB:

  • Crear, actualizar y eliminar un elemento.

  • Leer un elemento.

  • Examinar un elemento.

  • Otras operaciones (echo, ping), no relacionadas con DynamoDB, que puede utilizar para las pruebas.

La carga de solicitud que se envía en la solicitud POST identifica la operación de DynamoDB y proporciona los datos necesarios. Por ejemplo:

  • A continuación se muestra una carga de solicitud de ejemplo para una operación create item de DynamoDB:

    { "operation": "create", "tableName": "lambda-apigateway", "payload": { "Item": { "id": "1", "name": "Bob" } } }
  • A continuación se muestra una carga de solicitud de ejemplo para una operación read item de DynamoDB:

    { "operation": "read", "tableName": "lambda-apigateway", "payload": { "Key": { "id": "1" } } }
  • A continuación se muestra una carga de solicitud de ejemplo para una operación echo. Envía una solicitud HTTP POST al punto de enlace usando los datos siguientes en el cuerpo de la solicitud.

    { "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }
nota

API Gateway ofrece capacidades avanzadas, como por ejemplo:

  • Transferencia de la solicitud completa: una función de Lambda puede recibir la solicitud HTTP completa (en lugar de solo el cuerpo de la solicitud) y establecer la respuesta HTTP (en lugar de solo el cuerpo de la respuesta) utilizando el tipo de integración AWS_PROXY.

  • Métodos catch-all: mapea todos los métodos de un recurso de la API a una sola función de Lambda con un único mapeo, utilizando el método catch-all ANY.

  • Recursos catch-all: mapea todas las subrutas de un recurso a una función de Lambda sin necesidad de realizar ninguna configuración adicional, mediante el nuevo parámetro de ruta ({proxy+}).

Para obtener más información acerca de estas características de la gateway API, consulte Configuración de la integración del proxy para un recurso de proxy.

Requisitos previos

En este tutorial, se le presuponen algunos conocimientos sobre las operaciones básicas de Lambda y la consola de Lambda. Si aún no lo ha hecho, siga las instrucciones que se indican en Introducción a Lambda para crear la primera función Lambda.

Para completar los siguientes pasos, necesita un terminal de línea de comandos o shell para ejecutar comandos. Los comandos y la salida esperada se muestran en bloques separados:

aws --version

Debería ver los siguientes datos de salida:

aws-cli/2.0.57 Python/3.7.4 Darwin/19.6.0 exe/x86_64

Para los comandos largos, se utiliza un carácter de escape (\) para dividir un comando en varias líneas.

En Linux y macOS, use su administrador de shell y paquetes preferido. En Windows 10, puede instalar Windows Subsystem para Linux para obtener una versión de Ubuntu y Bash integrada con Windows.

Creación del rol de ejecución

Creación del rol de ejecución. Esta función utiliza una política personalizada con el fin de otorgar permiso a la función para que tenga acceso a los recursos de AWS necesarios. Primero se crea la política y luego el rol de ejecución.

Para crear una política personalizada

  1. Abra la página Policies (Políticas) en la consola de IAM.

  2. Elija Create Policy (Crear política).

  3. Seleccione la pestaña JSON. Pegue la siguiente política personalizada en el cuadro de entrada.

    { "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1428341300017", "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": "*" }, { "Sid": "", "Resource": "*", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow" } ] }
  4. Elija Next: Tags (Siguiente: Etiquetas).

  5. Elija Next: Review.

  6. Para el nombre de la política, escriba lambda-apigateway-policy.

  7. Escriba Create policy (Crear política).

Esta política incluye permisos para que la función tenga acceso a DynamoDB y CloudWatch Logs.

Para crear un rol de ejecución

  1. Abra la página Roles en la consola de IAM.

  2. Elija Create role (Crear rol).

  3. Para la entidad de confianza, elija AWS Service (Servicio de AWS) y, para el caso de uso, elija Lambda.

  4. Elija Next: Permissions.

  5. En el cuadro de búsqueda de políticas, escriba lambda-apigateway-policy.

  6. En los resultados, seleccione lambda-apigateway-policy y elija Next: Tags (Siguiente: Etiquetas).

  7. Elija Next: Review (Siguiente: Revisar).

  8. Para el nombre del rol, escriba lambda-apigateway-role.

  9. Escriba Create role (Crear rol).

Anote el nombre de recurso de Amazon (ARN) del rol de ejecución para uso posterior.

Creación de la función

A continuación se muestra código de ejemplo que recibe un evento de API Gateway como entrada y procesa los mensajes que contiene. Con fines ilustrativos, el código escribe parte de los datos de los eventos de entrada en CloudWatch Logs.

nota

Para ver código de muestra en otros lenguajes, consulte Código de función de ejemplo.

ejemplo index.js

console.log('Loading function'); var AWS = require('aws-sdk'); var dynamo = new AWS.DynamoDB.DocumentClient(); /** * Provide an event that contains the following keys: * * - operation: one of the operations in the switch statement below * - tableName: required for operations that interact with DynamoDB * - payload: a parameter to pass to the operation being performed */ exports.handler = function(event, context, callback) { //console.log('Received event:', JSON.stringify(event, null, 2)); var operation = event.operation; if (event.tableName) { event.payload.TableName = event.tableName; } switch (operation) { case 'create': dynamo.put(event.payload, callback); break; case 'read': dynamo.get(event.payload, callback); break; case 'update': dynamo.update(event.payload, callback); break; case 'delete': dynamo.delete(event.payload, callback); break; case 'list': dynamo.scan(event.payload, callback); break; case 'echo': callback(null, "Success"); break; case 'ping': callback(null, "pong"); break; default: callback(`Unknown operation: ${operation}`); } };

Para crear la función

  1. Copie el código de muestra en un archivo con el nombre index.js.

  2. Crear un paquete de implementación.

    zip function.zip index.js
  3. Cree una función de Lambda con el comando create-function. Para el parámetro role, introduzca el ARN del rol de ejecución que creó anteriormente.

    aws lambda create-function --function-name LambdaFunctionOverHttps \ --zip-file fileb://function.zip --handler index.handler --runtime nodejs12.x \ --role arn:aws:iam::123456789012:role/service-role/lambda-apigateway-role

Pruebe la función de Lambda

Invoque la función de forma manual utilizando los datos del evento de muestra. Recomendamos que invoque la función utilizando la consola, ya que la interfaz de usuario de la consola proporciona una interfaz fácil de utilizar para examinar los resultados de la ejecución, incluido el resumen de ejecución, los registros escritos por el código y los resultados devueltos por la función (dado que la consola siempre realiza una ejecución síncrona, invoca la función de Lambda utilizando el tipo de invocación RequestResponse).

Para probar la función de Lambda

  1. Copie el siguiente JSON en un archivo y guárdelo como input.txt.

    { "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }
  2. Ejecute el siguiente comando invoke:

    aws lambda invoke --function-name LambdaFunctionOverHttps \ --payload file://input.txt outputfile.txt
    nota

    Si utiliza la versión 2 de la AWS CLI, agregue los siguientes parámetros al comando:

    --cli-binary-format raw-in-base64-out

Creación de una API con Amazon API Gateway

En este paso, asociará la función de Lambda a un método de la API que ha creado utilizando Amazon API Gateway y probará la experiencia integral. Es decir, cuando se envíe una solicitud HTTPS a un método de la API, Amazon API Gateway invocará la función de Lambda.

En primer lugar, debe crear una API (DynamoDBOperations) utilizando Amazon API Gateway con un recurso (DynamoDBManager) y un método (POST). A continuación, asociará el método POST a la función de Lambda. Y, por último, probará la experiencia integral.

Cree el API

Ejecute el siguiente comando create-rest-api para crear la API DynamoDBOperations para este tutorial.

aws apigateway create-rest-api --name DynamoDBOperations

Debería ver los siguientes datos de salida:

{ "id": "bs8fqo6bp0", "name": "DynamoDBOperations", "createdDate": 1539803980, "apiKeySource": "HEADER", "endpointConfiguration": { "types": [ "EDGE" ] } }

Guarde el ID de API para su uso en comandos futuros. También necesita el ID del recurso raíz de la API. Para obtener el ID, ejecute el comando get-resources.

API=bs8fqo6bp0 aws apigateway get-resources --rest-api-id $API

Debería ver los siguientes datos de salida:

{ "items": [ { "path": "/", "id": "e8kitthgdb" } ] }

En ese momento solo tiene el recurso raíz, pero añadirá más recursos en el siguiente paso.

Creación de un recurso en la API

Ejecute el siguiente comando create-resource para crear un recurso (DynamoDBManager) en la API que ha creado en la sección anterior.

aws apigateway create-resource --rest-api-id $API --path-part DynamoDBManager \ --parent-id e8kitthgdb

Debería ver los siguientes datos de salida:

{ "path": "/DynamoDBManager", "pathPart": "DynamoDBManager", "id": "iuig5w", "parentId": "e8kitthgdb" }

Anote el ID de la respuesta. Este es el ID del recurso DynamoDBManager que ha creado.

Creación de un método POST en el recurso

Ejecute el siguiente comando put-method para crear un método POST en el recurso DynamoDBManager de la API.

RESOURCE=iuig5w aws apigateway put-method --rest-api-id $API --resource-id $RESOURCE \ --http-method POST --authorization-type NONE

Debería ver los siguientes datos de salida:

{ "apiKeyRequired": false, "httpMethod": "POST", "authorizationType": "NONE" }

Especificamos NONE para el parámetro --authorization-type, lo que significa que se admiten solicitudes sin autenticar para este método. Esto está bien para las pruebas, pero en producción debe utilizar la autenticación basada en claves o en roles.

Definición de la función de Lambda como destino para el método POST

Ejecute el siguiente comando para establecer la función de Lambda como punto de integración para el método POST. Este es el método que invoca Amazon API Gateway cuando hace una solicitud HTTP para el método de punto de enlace POST. Este comando y otros usan ARN que incluyen su ID de cuenta y su región. Guarde estos en variables (encontrará su ID de cuenta en el rol ARN que usó para crear la función).

REGION=us-east-2 ACCOUNT=123456789012 aws apigateway put-integration --rest-api-id $API --resource-id $RESOURCE \ --http-method POST --type AWS --integration-http-method POST \ --uri arn:aws:apigateway:$REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:$REGION:$ACCOUNT:function:LambdaFunctionOverHttps/invocations

Debería ver los siguientes datos de salida:

{ "type": "AWS", "httpMethod": "POST", "uri": "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps/invocations", "passthroughBehavior": "WHEN_NO_MATCH", "timeoutInMillis": 29000, "cacheNamespace": "iuig5w", "cacheKeyParameters": [] }

--integration-http-method es el método que usa API Gateway para comunicarse con AWS Lambda. --uri es identificador único para el punto de enlace al cual Amazon API Gateway puede mandar solicitud.

Establezca el content-type de la respuesta de integración y de la respuesta del método POST en JSON como se indica a continuación:

  • Ejecute el siguiente comando para establecer la respuesta del método POST en JSON. Este es el tipo de respuesta que devuelve el método de la API.

    aws apigateway put-method-response --rest-api-id $API \ --resource-id $RESOURCE --http-method POST \ --status-code 200 --response-models application/json=Empty

    Debería ver los siguientes datos de salida:

    { "statusCode": "200", "responseModels": { "application/json": "Empty" } }
  • Ejecute el siguiente comando para establecer la respuesta de integración del método POST en JSON. Este es el tipo de respuesta que devuelve la función de Lambda.

    aws apigateway put-integration-response --rest-api-id $API \ --resource-id $RESOURCE --http-method POST \ --status-code 200 --response-templates application/json=""

    Debería ver los siguientes datos de salida:

    { "statusCode": "200", "responseTemplates": { "application/json": null } }
    nota

    Si encuentra un error al ejecutar este comando, puede utilizar caracteres de escape alrededor del campo de plantilla de respuesta para obtener más claridad. El texto application/json="" se convierte en "{\"application/json"\":""\"\"}"".

Implementar la API

En este paso, implementará la API que ha creado en una etapa denominada prod.

aws apigateway create-deployment --rest-api-id $API --stage-name prod

Debería ver los siguientes datos de salida:

{ "id": "20vgsz", "createdDate": 1539820012 }

Conceda permiso de invocación a la API

Ahora que ha creado una API con Amazon API Gateway y la ha implementado, puede probarla. En primer lugar, debe agregar permisos para que Amazon API Gateway; pueda invocar la función de Lambda cuando se envía la solicitud HTTP al método POST.

Para ello, debe añadir un permiso a la política de permisos asociada a la función de Lambda. Ejecute el siguiente comando add-permission de AWS Lambda para conceder a la entidad principal del servicio de Amazon API Gateway (apigateway.amazonaws.com) permisos para invocar la función de Lambda (LambdaFunctionOverHttps).

aws lambda add-permission --function-name LambdaFunctionOverHttps \ --statement-id apigateway-test-2 --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn "arn:aws:execute-api:$REGION:$ACCOUNT:$API/*/POST/DynamoDBManager"

Debería ver los siguientes datos de salida:

{ "Statement": "{\"Sid\":\"apigateway-test-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-2:123456789012:mnh1yprki7/*/POST/DynamoDBManager\"}}}" }

Debe conceder este permiso para poder realizar pruebas (si va a Amazon API Gateway y elige Test (Probar) para probar el método de la API, necesitará este permiso). Observe que --source-arn especifica un carácter comodín (*) como valor para la etapa (indica que solo es para pruebas). Esto le permite hacer pruebas sin implementar la API.

nota

Si la función y la API se encuentran en regiones diferentes, el identificador de región en el ARN del origen debe coincidir con la región de la función, no la región de la API.

Ahora, ejecute el mismo comando de nuevo, pero esta vez conceda a la API implementada permisos para invocar la función de Lambda.

aws lambda add-permission --function-name LambdaFunctionOverHttps \ --statement-id apigateway-prod-2 --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com \ --source-arn "arn:aws:execute-api:$REGION:$ACCOUNT:$API/prod/POST/DynamoDBManager"

Debería ver los siguientes datos de salida:

{ "Statement": "{\"Sid\":\"apigateway-prod-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-2:123456789012:function:LambdaFunctionOverHttps\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-2:123456789012:mnh1yprki7/prod/POST/DynamoDBManager\"}}}" }

Puede conceder este permiso para que la API implementada tenga permisos para invocar la función de Lambda. Observe que --source-arn especifica prod, que es el nombre de la etapa que se utilizó al implementar la API.

Crear una tabla de Amazon DynamoDB

Cree la tabla de DynamoDB que usa la funció de Lambda.

Para crear una tabla de DynamoDB

  1. Abra la consola de DynamoDB.

  2. Seleccione Create table.

  3. Cree una tabla con la siguiente configuración:

    • Nombre de la tablalambda-apigateway

    • Primary key (Clave principal)id (cadena)

  4. Seleccione Create.

Desencadene la función con una solicitud HTTP

En este paso, puede enviar una solicitud HTTP al punto de enlace del método POST. Puede utilizar Curl o un método (test-invoke-method) proporcionado por Amazon API Gateway.

Puede utilizar comandos de la CLI de Amazon API Gateway para enviar una solicitud de HTTP POST al punto de enlace del recursoDynamoDBManager. Dado que ha implementado su Amazon API Gateway, puede utilizar Curl para invocar los métodos para realizar la misma operación.

La función de Lambda permite utilizar la operación create para crear un elemento en la tabla de DynamoDB. Para solicitar esta operación, utilice el siguiente JSON:

ejemplo create-item.json

{ "operation": "create", "tableName": "lambda-apigateway", "payload": { "Item": { "id": "1234ABCD", "number": 5 } } }

Guarde la información de pruebas en un archivo llamado create-item.json. Ejecute el comando de Amazon API Gateway test-invoke-method para enviar una solicitud de método HTTP POST al punto de enlace recursoDynamoDBManager

aws apigateway test-invoke-method --rest-api-id $API \ --resource-id $RESOURCE --http-method POST --path-with-query-string "" \ --body file://create-item.json

También puede utilizar el siguiente comando Curl:

curl -X POST -d "{\"operation\":\"create\",\"tableName\":\"lambda-apigateway\",\"payload\":{\"Item\":{\"id\":\"1\",\"name\":\"Bob\"}}}" https://$API.execute-api.$REGION.amazonaws.com/prod/DynamoDBManager

Para enviar la solicitud para la operación echo que admite la función de Lambda, puede utilizar la siguiente carga de solicitud:

ejemplo echo.json

{ "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }

Guarde la información de pruebas en un archivo llamado echo.json. Ejecute el comando CLI de Amazon API Gateway test-invoke-method para enviar una solicitud de método HTTP POST al punto de enlace recursoDynamoDBManagerusando el JSON anterior en el cuerpo de solicitud.

aws apigateway test-invoke-method --rest-api-id $API \ --resource-id $RESOURCE --http-method POST --path-with-query-string "" \ --body file://echo.json

También puede utilizar el siguiente comando Curl:

curl -X POST -d "{\"operation\":\"echo\",\"payload\":{\"somekey1\":\"somevalue1\",\"somekey2\":\"somevalue2\"}}" https://$API.execute-api.$REGION.amazonaws.com/prod/DynamoDBManager

Limpiar los recursos

Ahora puede eliminar los recursos que creó para este tutorial, a menos que desee conservarlos. Si elimina los recursos de AWS que ya no utiliza, evitará gastos innecesarios en su cuenta de AWS.

Para eliminar la función de Lambda

  1. Abra la Página de Funciones de la consola de Lambda.

  2. Seleccione la función que ha creado.

  3. Elija Actions (Acciones), Delete (Eliminar).

  4. Elija Eliminar.

Para eliminar el rol de ejecución

  1. Abra la Página de Roles de la consola de IAM.

  2. Seleccione el rol de ejecución que ha creado.

  3. Elija Delete role (Eliminar rol).

  4. Elija Sí, eliminar.

Para eliminar la API

  1. Abra la Página de las API de la consola de API Gateway.

  2. Seleccione la API que ha creado.

  3. Elija Actions (Acciones), Delete (Eliminar).

  4. Elija Eliminar.

Eliminar la tabla DynamoDB

  1. Abra la Página de Tablas de la consola de DynamoDB.

  2. Seleccione la tabla que ha creado.

  3. Elija Eliminar.

  4. Escriba delete en el cuadro de texto.

  5. Elija Eliminar.