

# Tutorial: Creación de una API de HTTP CRUD con Lambda y DynamoDB
<a name="http-api-dynamo-db"></a>

En este tutorial, creará una API sin servidor para crear, leer, actualizar y eliminar elementos de una tabla de DynamoDB. DynamoDB es un servicio de bases de datos NoSQL totalmente administrado que proporciona un rendimiento rápido y predecible, así como una perfecta escalabilidad. Completar este tutorial lleva aproximadamente 30 minutos, y puede hacerse dentro del [nivel gratuito de AWS](https://aws.amazon.com/free/).

En primer lugar, se crea una tabla [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) utilizando la consola de DynamoDB. Luego, se crea una función de [Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) con la consola de AWS Lambda. A continuación, crea una API HTTP mediante la consola de API Gateway. Por último, se prueba la API.

Cuando invoca su API HTTP, API Gateway enruta la solicitud a su función de Lambda. La función Lambda interactúa con DynamoDB y devuelve una respuesta a API Gateway. API Gateway, a continuación, le devuelve una respuesta.

![\[Información general de la API HTTP creada en este tutorial.\]](http://docs.aws.amazon.com/es_es/apigateway/latest/developerguide/images/ddb-crud.png)


Para completar este ejercicio, necesita una cuenta de AWS y un usuario de AWS Identity and Access Management con acceso a la consola. Para obtener más información, consulte [Configuración para usar API Gateway](setting-up.md).

En este tutorial, se utiliza la Consola de administración de AWS. Para obtener una plantilla de AWS SAM que cree esta API y todos los recursos relacionados, consulte [samples/http-dynamo-tutorial.zip](samples/http-dynamo-tutorial.zip).

**Topics**
+ [Paso 1: crear una tabla de DynamoDB](#http-api-dynamo-db-create-table)
+ [Paso 2: crear una función Lambda](#http-api-dynamo-db-create-function)
+ [Paso 3: crear una API HTTP](#http-api-dynamo-db-create-api)
+ [Paso 4: crear rutas](#http-api-dynamo-db-create-routes)
+ [Paso 5: crear una integración](#http-api-dynamo-db-create-integration)
+ [Paso 6: conectar la integración a las rutas](#http-api-dynamo-db-attach-integrations)
+ [Paso 7: probar la API](#http-api-dynamo-db-invoke-api)
+ [Paso 8: Eliminar](#http-api-dynamo-db-cleanup)
+ [Pasos siguientes: automatización con AWS SAM o CloudFormation](#http-api-dynamo-db-next-steps)

## Paso 1: crear una tabla de DynamoDB
<a name="http-api-dynamo-db-create-table"></a>

Se utiliza una tabla [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) para almacenar datos para la API. 

Cada elemento tiene un ID único, que usamos como [clave de partición](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey) para la tabla.

**Cree una tabla de DynamoDB**

1. Abra la consola de DynamoDB en [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/).

1. Seleccione **Create table**.

1. En **Nombre de la tabla**, introduzca **http-crud-tutorial-items**.

1. En **Partition key** (Clave de partición), ingrese **id**.

1. Seleccione **Create table (Creación de tabla)**.

## Paso 2: crear una función Lambda
<a name="http-api-dynamo-db-create-function"></a>

Se crea una función [Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) para el backend de la API. Esta función Lambda crea, lee, actualiza y elimina elementos de DynamoDB. La función utiliza [ eventos de API Gateway](http-api-develop-integrations-lambda.md#http-api-develop-integrations-lambda.proxy-format) para determinar cómo interactuar con DynamoDB. Para simplificar el proceso, este tutorial utiliza una sola función Lambda. Como práctica recomendada, se deben crear funciones separadas para cada ruta. Para obtener más información sobre Lambda, consulte [The Lambda monolith](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/monolith) (El monolito de Lambda).

**Cómo crear una función de Lambda**

1. Inicie sesión en la consola de Lambda en [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda).

1. Elija **Create function (Crear función)**.

1. En **Function name (Nombre de función)**, introduzca **http-crud-tutorial-function**.

1. En **Tiempo de ejecución**, elija el último tiempo de ejecución de **Node.js** o **Python** compatible.

1. En **Permisos**, seleccione **Cambiar el rol de ejecución predeterminado**.

1. Seleccione **Create a new role from AWS policy templates** (Crear un nuevo rol en plantillas de políticas de AWS).

1. En **Nombre del rol**, introduzca **http-crud-tutorial-role**.

1. En **Plantillas de políticas**, seleccione **Simple microservice permissions**. Esta política concede a la función Lambda permiso para interactuar con DynamoDB.
**nota**  
Para simplificar el proceso, este tutorial utiliza una política administrada. Como práctica recomendada, se deben crear políticas de IAM propias para otorgar los permisos mínimos requeridos.

1. Elija **Create function (Crear función)**.

1. Abra la función de Lambda en el editor de código de la consola y sustituya su contenido con el siguiente código. Seleccione **Implementar** para actualizar la función.

------
#### [ Node.js ]

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
  DynamoDBDocumentClient,
  ScanCommand,
  PutCommand,
  GetCommand,
  DeleteCommand,
} from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});

const dynamo = DynamoDBDocumentClient.from(client);

const tableName = "http-crud-tutorial-items";

export const handler = async (event, context) => {
  let body;
  let statusCode = 200;
  const headers = {
    "Content-Type": "application/json",
  };

  try {
    switch (event.routeKey) {
      case "DELETE /items/{id}":
        await dynamo.send(
          new DeleteCommand({
            TableName: tableName,
            Key: {
              id: event.pathParameters.id,
            },
          })
        );
        body = `Deleted item ${event.pathParameters.id}`;
        break;
      case "GET /items/{id}":
        body = await dynamo.send(
          new GetCommand({
            TableName: tableName,
            Key: {
              id: event.pathParameters.id,
            },
          })
        );
        body = body.Item;
        break;
      case "GET /items":
        body = await dynamo.send(
          new ScanCommand({ TableName: tableName })
        );
        body = body.Items;
        break;
      case "PUT /items":
        let requestJSON = JSON.parse(event.body);
        await dynamo.send(
          new PutCommand({
            TableName: tableName,
            Item: {
              id: requestJSON.id,
              price: requestJSON.price,
              name: requestJSON.name,
            },
          })
        );
        body = `Put item ${requestJSON.id}`;
        break;
      default:
        throw new Error(`Unsupported route: "${event.routeKey}"`);
    }
  } catch (err) {
    statusCode = 400;
    body = err.message;
  } finally {
    body = JSON.stringify(body);
  }

  return {
    statusCode,
    body,
    headers,
  };
};
```

------
#### [ Python ]

```
import json
import boto3
from decimal import Decimal

client = boto3.client('dynamodb')
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table('http-crud-tutorial-items')
tableName = 'http-crud-tutorial-items'


def lambda_handler(event, context):
    print(event)
    body = {}
    statusCode = 200
    headers = {
        "Content-Type": "application/json"
    }

    try:
        if event['routeKey'] == "DELETE /items/{id}":
            table.delete_item(
                Key={'id': event['pathParameters']['id']})
            body = 'Deleted item ' + event['pathParameters']['id']
        elif event['routeKey'] == "GET /items/{id}":
            body = table.get_item(
                Key={'id': event['pathParameters']['id']})
            body = body["Item"]
            responseBody = [
                {'price': float(body['price']), 'id': body['id'], 'name': body['name']}]
            body = responseBody
        elif event['routeKey'] == "GET /items":
            body = table.scan()
            body = body["Items"]
            print("ITEMS----")
            print(body)
            responseBody = []
            for items in body:
                responseItems = [
                    {'price': float(items['price']), 'id': items['id'], 'name': items['name']}]
                responseBody.append(responseItems)
            body = responseBody
        elif event['routeKey'] == "PUT /items":
            requestJSON = json.loads(event['body'])
            table.put_item(
                Item={
                    'id': requestJSON['id'],
                    'price': Decimal(str(requestJSON['price'])),
                    'name': requestJSON['name']
                })
            body = 'Put item ' + requestJSON['id']
    except KeyError:
        statusCode = 400
        body = 'Unsupported route: ' + event['routeKey']
    body = json.dumps(body)
    res = {
        "statusCode": statusCode,
        "headers": {
            "Content-Type": "application/json"
        },
        "body": body
    }
    return res
```

------

## Paso 3: crear una API HTTP
<a name="http-api-dynamo-db-create-api"></a>

La API HTTP proporciona un punto de enlace HTTP para su función de Lambda. En este paso, se crea una API vacía. En los siguientes pasos, se configuran rutas e integraciones para conectar la API y la función Lambda.



**Para crear una API HTTP**

1. Inicie sesión en la consola de API Gateway en [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Seleccione **Crear API**y, a continuación, para **API HTTP**, seleccione **Crear**.

1. En **API name (Nombre de la API)**, escriba**http-crud-tutorial-api**.

1. En **Tipo de dirección IP**, seleccione **IPv4**.

1. Elija **Next (Siguiente)**.

1. En **Configurar rutas**, seleccione **Siguiente** para omitir la creación de rutas. Se crearán rutas más adelante.

1. Revise la etapa que API Gateway crea y, a continuación, seleccione **Siguiente**.

1. Seleccione **Create (Crear)**.

## Paso 4: crear rutas
<a name="http-api-dynamo-db-create-routes"></a>

Las rutas son una manera de enviar solicitudes entrantes de API a los recursos de backend. Las rutas constan de dos partes: un método HTTP y una ruta de recurso, por ejempl, `GET /items`. Para este ejemplo de API, creamos cuatro rutas:
+ `GET /items/{id}`
+ `GET /items`
+ `PUT /items`
+ `DELETE /items/{id}`

**Para crear rutas**

1. Inicie sesión en la consola de API Gateway en [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Elija la API.

1. Elija **Routes (Rutas)**.

1. Seleccione **Create (Crear)**.

1. En **Method (Método)**, seleccione **GET**.

1. En la ruta de acceso, introduzca **/items/\$1id\$1**. El `{id}` al final de la ruta es un parámetro de ruta que API Gateway recupera de la ruta de solicitud cuando un cliente realiza una solicitud.

1. Seleccione **Create (Crear)**.

1. Repita los pasos 4 a 7 para `GET /items`, `DELETE /items/{id}`, y `PUT /items`.

![\[La API tiene rutas para GET /items, GET /items/{id}, DELETE /items/{id} y PUT /items.\]](http://docs.aws.amazon.com/es_es/apigateway/latest/developerguide/images/ddb-create-routes.png)


## Paso 5: crear una integración
<a name="http-api-dynamo-db-create-integration"></a>

Se crea una integración para conectar una ruta a los recursos de backend. Para este ejemplo de API, se crea una integración Lambda que se utiliza para todas las rutas.

**Para crear una integración**

1. Inicie sesión en la consola de API Gateway en [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Elija la API.

1. Seleccione **Integraciones**.

1. Seleccione **Administrar integraciones** y, a continuación, seleccione **Crear**.

1. Omitir **Conectar esta integración a una ruta**. Esta etapa se completará más adelante.

1. En **Tipo de integración**, seleccione **Función Lambda**.

1. En **Función Lambda**, introduzca **http-crud-tutorial-function**.

1. Seleccione **Create (Crear)**.

## Paso 6: conectar la integración a las rutas
<a name="http-api-dynamo-db-attach-integrations"></a>

Para este ejemplo de API, se utiliza la misma integración Lambda para todas las rutas. Después de conectar la integración a todas las rutas de la API, la función Lambda se invoca cuando un cliente llama a cualquiera de sus rutas.



**Para conectar integraciones a rutas**

1. Inicie sesión en la consola de API Gateway en [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Elija la API.

1. Seleccione **Integraciones**.

1. Seleccione una ruta.

1. En **Elegir una integración existente**, seleccione **http-crud-tutorial-function**.

1. Seleccione **Conectar integración**.

1. Repita los pasos 4 a 6 para todas las rutas. 

Todas las rutas muestran que se adjuntó una integración de AWS Lambda.

![\[La consola muestra a AWS Lambda en todas las rutas para indicar que la integración se adjuntó.\]](http://docs.aws.amazon.com/es_es/apigateway/latest/developerguide/images/ddb-attach-integrations.png)


Ahora que se tiene una API HTTP con rutas e integraciones, se puede probar la API.

## Paso 7: probar la API
<a name="http-api-dynamo-db-invoke-api"></a>

Para asegurarse de que la API está funcionando, se utiliza [curl](https://curl.se).

**Para obtener la URL para invocar la API**

1. Inicie sesión en la consola de API Gateway en [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Elija la API.

1. Tenga en cuenta la URL de invocación de la API. Aparece en **Invocar URL** en la página **Detalles**.  
![\[Después de crear la API, la consola muestra la URL de invocación de la API.\]](http://docs.aws.amazon.com/es_es/apigateway/latest/developerguide/images/ddb-invoke-url.png)

1. Copie la URL de invocación de la API. 

   La totalidad de la URL se parece a `https://abcdef123.execute-api.us-west-2.amazonaws.com`. 

**Para crear o actualizar un elemento**
+ Utilice el siguiente comando para crear o actualizar un artículo. El comando incluye un cuerpo de solicitud con el ID, el precio y el nombre del artículo.

  ```
  curl -X "PUT" -H "Content-Type: application/json" -d "{\"id\": \"123\", \"price\": 12345, \"name\": \"myitem\"}" https://abcdef123.execute-api.us-west-2.amazonaws.com/items
  ```

**Para ver todos los artículos**
+ Utilice el siguiente comando para enumerar todos los artículos.

  ```
  curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items
  ```

**Para ver un artículo**
+ Utilice el siguiente comando para ver un artículo por su ID.

  ```
  curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items/123
  ```

**Para eliminar un elemento**

1. Utilice el siguiente comando para eliminar un artículo.

   ```
   curl -X "DELETE" https://abcdef123.execute-api.us-west-2.amazonaws.com/items/123
   ```

1. Ver todos los artículos para verificar que el artículo se eliminó.

   ```
   curl https://abcdef123.execute-api.us-west-2.amazonaws.com/items
   ```

## Paso 8: Eliminar
<a name="http-api-dynamo-db-cleanup"></a>

Para evitar costos innecesarios, elimine los recursos creados como parte de este ejercicio introductorio. Los siguientes pasos eliminan la API HTTP, la función de Lambda y los recursos asociados.

**Para eliminar una tabla de DynamoDB**

1. Abra la consola de DynamoDB en [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/).

1. Seleccionar la tabla.

1. Elija **Delete table (Eliminar tabla)**.

1. Confirme la elección y seleccione **Eliminar**.

**Para eliminar una API HTTP**

1. Inicie sesión en la consola de API Gateway en [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. En la página **API**, seleccione una API. Seleccione **Actions** y, luego, **Delete**.

1. Elija **Eliminar**.

**Para eliminar una función de Lambda**

1. Inicie sesión en la consola de Lambda en [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda).

1. En la página **Functions** (Funciones), seleccione una función. Seleccione **Actions** y, luego, **Delete**.

1. Elija **Eliminar**.

**Para eliminar el grupo de registro de una función de Lambda**

1. En la consola de Amazon CloudWatch, abra la [página de grupos de registro](https://console.aws.amazon.com/cloudwatch/home#logs:).

1. En la página **Grupos de registro**, seleccione el grupo de registro de la función (`/aws/lambda/http-crud-tutorial-function`). Elija **Actions (Acciones)** y, a continuación, elija **Delete log group (Eliminar grupo de registro)**.

1. Elija **Eliminar**.

**Para eliminar el rol de ejecución de una función de Lambda**

1. En la consola de AWS Identity and Access Management, abra la página [Roles](https://console.aws.amazon.com/iam/home?#/roles) (Roles).

1. Seleccione el rol de la función, por ejempl, `http-crud-tutorial-role`.

1. Elija **Delete role (Eliminar rol)**.

1. Elija **Sí, eliminar**.

## Pasos siguientes: automatización con AWS SAM o CloudFormation
<a name="http-api-dynamo-db-next-steps"></a>

Puede automatizar la creación y la limpieza de los recursos de AWS mediante el uso de CloudFormation o AWS SAM. Para obtener un ejemplo de plantilla de AWS SAM para este tutorial, consulte [samples/http-dynamo-tutorial.zip](samples/http-dynamo-tutorial.zip).

Para obtener plantillas de CloudFormation de ejemplo, consulte las [plantillas de CloudFormation de ejemplo](https://github.com/awsdocs/amazon-api-gateway-developer-guide/tree/main/cloudformation-templates).