

# Tutorial: Creación de una API de WebSocket con una integración de AWS
<a name="websocket-api-step-functions-tutorial"></a>

En este tutorial, se crea una aplicación de transmisión sin servidor con una API de WebSocket. Los clientes pueden recibir mensajes sin tener que sondear para comprobar si hay actualizaciones.

 Este tutorial muestra cómo transmitir mensajes a los clientes conectados e incluye un ejemplo de un autorizador de Lambda, una integración simulada y una integración que no sea de proxy en Step Functions.

![Descripción general de la arquitectura de la API creada en este tutorial.](https://docs.aws.amazon.com/es_es/apigateway/latest/developerguide/images/ws-sfn-app.png)


Una vez haya creado los recursos con una plantilla de CloudFormation, utilizará la consola de API Gateway para crear una API de WebSocket que se integre con los recursos de AWS. Adjuntará un autorizador de Lambda a la API y creará una integración de servicios de AWS con Step Functions para iniciar la ejecución de una máquina de estado. La máquina de estado de Step Functions invocará una función de Lambda que envía un mensaje a todos los clientes conectados.

Después de crear la API, probará la conexión a la API y verificará que se envían y reciben mensajes. Para completar este tutorial se necesita aproximadamente 45 minutos.

**Topics**
+ [Requisitos previos](#websocket-api-step-functions-prerequisites)
+ [Paso 1: Crear recursos](#websocket-api-step-functions-create-dependencies)
+ [Paso 2: Crear una API de WebSocket](#websocket-api-step-functions-create-api)
+ [Paso 3: Creación de un autorizador de Lambda](#websocket-api-step-functions-create-authorizer)
+ [Paso 4: Creación de una integración bidireccional simulada](#websocket-api-step-functions-create-mock-integration)
+ [Paso 5: Creación de una integración que no sea de proxy con Step Functions](#websocket-api-step-functions-create-step-function-integration)
+ [Paso 6: probar la API](#websocket-api-step-functions-test-api)
+ [Paso 7: limpiar](#websocket-api-step-functions-cleanup)
+ [Siguientes pasos](#websocket-api-step-functions-next-steps)

## Requisitos previos
<a name="websocket-api-step-functions-prerequisites"></a>

Necesita los siguientes requisitos previos:
+ 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).
+ `wscat` para conectarse a la API. Para obtener más información, consulte [Utilice `wscat` para conectarse y enviar mensajes a una API de WebSocket](apigateway-how-to-call-websocket-api-wscat.md).

Le recomendamos que complete el tutorial de la aplicación de chat de WebSocket antes de iniciar este tutorial. Para completar el tutorial de la aplicación de chat de WebSocket, consulte [Tutorial: Creación de una aplicación de chat de WebSocket con una API de WebSocket, Lambda y DynamoDB](websocket-api-chat-app.md).

## Paso 1: Crear recursos
<a name="websocket-api-step-functions-create-dependencies"></a>

Descargue y descomprima [la plantilla de creación de aplicaciones para CloudFormation](samples/ws-sfn-starter.zip). Usará esta plantilla para crear lo siguiente:
+ Funciones de Lambda que gestionan las solicitudes de la API y autorizan el acceso a la API.
+ Una tabla de DynamoDB para almacenar los ID de cliente y la identificación de usuario de entidad principal devuelta por el autorizador de Lambda.
+ Una máquina de estado de Step Functions para enviar mensajes a los clientes conectados.

**Para crear una pila de CloudFormation**

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

1. Seleccione **Create stack (Crear pila)** y, a continuación, seleccione **With new resources (standard) (Con nuevos recursos [estándar])**.

1. En **Specify template (Especificar plantilla)**, elija **Upload a template file (Cargar un archivo de plantilla)**.

1. Seleccione la plantilla que ha descargado.

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

1. En **Stack name (Nombre de pila)**, escriba **websocket-step-functions-tutorial** y, a continuación, elija **Next (Siguiente)**.

1. En **Configure stack options (Configurar opciones de pila)**, elija **Next (Siguiente)**.

1. Para **Capabilities** (Capacidades), sepa que CloudFormation puede crear recursos de IAM en su cuenta.

1. Elija **Siguiente** y, a continuación, elija **Enviar**.

CloudFormation aprovisiona los recursos especificados en la plantilla. Puede tardar varios minutos en finalizar el aprovisionamiento de los recursos. Elija la pestaña **Salidas** para ver los recursos creados y los ARN. Cuando el estado de la pila de CloudFormation sea **CREATE\_COMPLETE**, estará listo para continuar con el paso siguiente.

## Paso 2: Crear una API de WebSocket
<a name="websocket-api-step-functions-create-api"></a>

Creará una API de WebSocket para gestionar las conexiones de clientes y enrutar solicitudes a los recursos que creó en el paso 1.

**Para crear una API de WebSocket**

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**. En **WebSocket API** (API de WebSocket), elija **Build** (Crear).

1. En **API name (Nombre de la API)**, escriba**websocket-step-functions-tutorial**.

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

1. Para **Route selection expression** (Expresión de selección de ruta), ingrese **request.body.action**.

   La expresión de selección de ruta determina la ruta que API Gateway invoca cuando un cliente envía un mensaje.

1. Elija **Siguiente**.

1. Para **Rutas predefinidas**, elija **Agregar $connect**, **Agregar $disconnect** y **Agregar $default**.

   Las rutas **$connect** y **$disconnect** son rutas especiales que API Gateway invoca automáticamente cuando un cliente se conecta o se desconecta de una API. API Gateway invoca la ruta **$default** cuando ninguna otra ruta coincide con una solicitud. Creará una ruta personalizada para conectarse a Step Functions después de crear la API.

1. Elija **Siguiente**.

1. Para **Integración para $connect**, haga lo siguiente:

   1. Para **Tipo de integración**, elija **Lambda**.

   1. Para **Función de Lambda**, elija la función de Lambda **$connect** correspondiente que creó con CloudFormation en el paso 1. El nombre de la función de Lambda debe comenzar con **websocket-step**.

1. Para **Integración para $disconnect**, haga lo siguiente:

   1. Para **Tipo de integración**, elija **Lambda**.

   1. Para **Función de Lambda**, elija la función de Lambda **$disconnect** correspondiente que creó con CloudFormation en el paso 1. El nombre de la función de Lambda debe comenzar con **websocket-step**.

1. Para **Integración para $default**, elija **simulación**.

   En una integración simulada, API Gateway administra la respuesta de la ruta sin un backend de integración.

1. Elija **Siguiente**.

1. Revise la etapa que API Gateway le crea. De forma predeterminada, API Gateway crea una etapa denominada **producción** e implementa automáticamente la API en esa etapa. Elija **Siguiente**.

1. Elija **Create and deploy** (Crear e implementar).

## Paso 3: Creación de un autorizador de Lambda
<a name="websocket-api-step-functions-create-authorizer"></a>

Para controlar el acceso a la API de WebSocket, debe crear un autorizador de Lambda. La plantilla de CloudFormation creó la función del autorizador de Lambda para usted. Puede ver la función de Lambda en la consola de Lambda. El nombre no debe comenzar por **websocket-step-functions-tutorial-AuthorizerHandler**. Esta función de Lambda deniega todas las llamadas a la API de WebSocket a menos que el encabezado de `Authorization` sea `Allow`. La función de Lambda también transfiere la variable `$context.authorizer.principalId` a la API, que luego se utiliza en la tabla de DynamoDB para identificar a los intermediarios de la API.

En este paso, debe configurar la ruta **$connect** para usar el autorizador de Lambda.

**Creación de un autorizador de Lambda**

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 el panel de navegación principal, elija **Autorizadores**.

1. Elija **Creación de un autorizador**.

1. Para **Nombre del autorizador**, ingrese **LambdaAuthorizer**.

1. Para **ARN de autorizador**, ingrese el nombre del autorizador creado por la plantilla de CloudFormation. El nombre no debe comenzar por **websocket-step-functions-tutorial-AuthorizerHandler**.
**nota**  
Le recomendamos que no utilice este autorizador de ejemplo para las API de producción.

1. Para **Tipo de origen de identidad**, elija **Encabezado**. En **Clave**, escriba **Authorization**.

1. Elija **Crear autorizador**.

Después de crear el autorizador, debe adjuntarlo a la ruta **$connect** de la API.

**Asociación de un autorizador a la ruta de $connect**

1. En el panel de navegación principal, elija **Rutas**.

1. Elija la ruta **$connect**.

1. En la sección **Configuración de la solicitud de ruta**, elija **Editar**.

1. Para **Autorización**, elija el menú desplegable y, a continuación, seleccione el autorizador de solicitudes.

1. Seleccione **Save changes (Guardar cambios)**.

## Paso 4: Creación de una integración bidireccional simulada
<a name="websocket-api-step-functions-create-mock-integration"></a>

A continuación, debe crear la integración simulada bidireccional para la ruta **$default**. Una integración simulada le permite enviar una respuesta al cliente sin usar un backend. Cuando crea una integración para la ruta **$default**, puede mostrar a los clientes cómo interactuar con la API.

Debe configurar la ruta **$default** para indicar a los clientes que usen la ruta **sendmessage**.

**Creación de una integración simulada**

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 ruta **$default** y, a continuación, elija la pestaña **Solicitud de integración**.

1. Para las **Plantillas de solicitud**, elija **Editar**.

1. Para **Expresión de selección de plantilla**, ingrese **200** y, a continuación, elija **Editar**.

1. En la pestaña **Solicitud de integración**, para **Plantillas de solicitud**, elija **Crear plantilla**.

1. Para **Clave de plantilla**, ingrese **200**.

1. Para **Generar plantilla**, ingrese la siguiente plantilla de asignación:

   ```
   {"statusCode": 200}
   ```

   Seleccione **Crear plantilla**.

   El resultado debe ser similar a lo siguiente:  
![Configuración de la solicitud de integración para una integración simulada para la ruta $default.](https://docs.aws.amazon.com/es_es/apigateway/latest/developerguide/images/ws-sfn-mock-integration-request.png)

1. Para el panel de la **ruta $default**, elija **Habilitar la comunicación bidireccional**.

1. Elija la pestaña **Respuesta de integración** y, a continuación, elija **Creación de respuesta de integración**.

1. Para **Clave de respuesta**, escriba **$default**.

1. Para **Expresión de selección de plantillas**, ingrese **200**.

1. Elija **Crear respuesta**.

1. En **Plantillas de respuesta**, elija **Crear plantilla**.

1. Para **Clave de plantilla**, ingrese **200**.

1. Para **Plantilla de respuesta**, ingrese la siguiente plantilla de asignación:

   ```
   {"Use the sendmessage route to send a message. Connection ID: $context.connectionId"}
   ```

1. Seleccione **Crear plantilla**.

   El resultado debe ser similar a lo siguiente:  
![Configuración de respuesta de integración para una integración simulada para la ruta $default.](https://docs.aws.amazon.com/es_es/apigateway/latest/developerguide/images/ws-sfn-mock-integration-response.png)

## Paso 5: Creación de una integración que no sea de proxy con Step Functions
<a name="websocket-api-step-functions-create-step-function-integration"></a>

A continuación, debe crear una ruta **sendmessage**. Los clientes pueden invocar la ruta **sendmessage** para transmitir un mensaje a todos los clientes conectados. La ruta **sendmessage** tiene una integración de servicio de AWS que no es de proxy con AWS Step Functions. La integración invoca el comando [StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) para la máquina de estado de Step Functions que la plantilla de CloudFormation creó para usted.

**Creación de una integración que no sea de proxy**

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 **Create route (Crear ruta)**.

1. Para **Route key** (Clave de ruta), ingrese **sendmessage**.

1. En **Tipo de integración**, seleccione **Servicio de AWS**.

1. Para **Región de AWS**, ingrese la región en la que implementó la plantilla de CloudFormation.

1. Para **Servicio de AWS**, elija **Step Functions**.

1. En **Método HTTP**, elija **POST**.

1. En **Nombre de la función**, introduzca **StartExecution**.

1. Para **Rol de ejecución**, ingrese el rol de ejecución creado por la plantilla de CloudFormation. El nombre debe ser **WebsocketTutorialApiRole**.

1. Elija **Create route (Crear ruta)**.

A continuación, debe crear una plantilla de asignación para enviar los parámetros de la solicitud a la máquina de estado de Step Functions.

**Para crear una plantilla de mapeo**

1. Elija la ruta **sendmessage** y, a continuación, elija la pestaña **Solicitud de integración**.

1. En la sección **Plantillas de solicitud**, elija **Editar**.

1. Para **Expresión de selección de plantillas**, ingrese **\\$default**.

1. Elija **Edit (Edición de)**.

1. En la sección **Plantillas de solicitud**, elija **Crear plantilla**.

1. Para **Clave de plantilla**, ingrese **\\$default**.

1. Para **Generar plantilla**, ingrese la siguiente plantilla de asignación:

   ```
   #set($domain = "$context.domainName")
   #set($stage = "$context.stage")
   #set($body = $input.json('$'))
   #set($getMessage = $util.parseJson($body))
   #set($mymessage = $getMessage.message)
   {
   "input": "{\"domain\": \"$domain\", \"stage\": \"$stage\", \"message\": \"$mymessage\"}",
   "stateMachineArn": "arn:aws:states:{{us-east-2}}:{{123456789012}}:stateMachine:WebSocket-Tutorial-StateMachine"
   }
   ```

   Sustituya {{stateMachineArn}} por el ARN de la máquina de estado creada por CloudFormation.

   La plantilla de asignación hace lo siguiente:
   + Crea la variable `$domain` mediante la variable de contexto `domainName`.
   + Crea la variable `$stage` mediante la variable de contexto `stage`.

     Las variables `$domain` y `$stage` son necesarias para crear una URL de devolución de llamada.
   + Toma el mensaje JSON `sendmessage` entrante y extrae la propiedad de `message`.
   + Crea la entrada de la máquina de estado. La entrada es el dominio y la etapa de la API de WebSocket y el mensaje de la ruta `sendmessage`.

1. Seleccione **Crear plantilla**.  
![configuración de ruta sendmessage.](https://docs.aws.amazon.com/es_es/apigateway/latest/developerguide/images/ws-sfn-integration-request.png)

Puede crear una integración que no sea de proxy en las rutas **$connect** o **$disconnect**, para agregar o eliminar directamente un ID de conexión de la tabla de DynamoDB, sin invocar una función de Lambda.

## Paso 6: probar la API
<a name="websocket-api-step-functions-test-api"></a>

A continuación, implementará y probará la API para asegurarse de que funciona correctamente. Utilizará el comando `wscat` para conectarse a la API y, a continuación, utilizará un comando de barra inclinada para enviar un marco de ping para comprobar la conexión a la API de WebSocket.

**Para implementar su 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. En el panel de navegación principal, elija **Rutas**.

1. Elija **Implementar API**.

1. Para **Etapa**, elija **producción**.

1. (Opcional) Para **Descripción de implementación**, ingrese una descripción.

1. Elija **Implementar**.

Después de implementar la API, puede invocarla. Use la URL de invocación para llamar a la API.

**Obtención de la URL de invocación para la API**

1. Elija la API.

1. Elija **Stages** (Etapas) y, a continuación, elija **production** (producción).

1. Tenga en cuenta la **WebSocket URL** (URL de WebSocket) de la API. La dirección URL debe tener un aspecto similar al siguiente: `wss://{{abcdef123}}.execute-api.{{us-east-2}}.amazonaws.com/production`.

Ahora que tiene la URL de invocación, puede probar la conexión a la API de WebSocket.

**Prueba de la conexión a la API**

1. Para conectarse a la API, utilice el siguiente comando. En primer lugar, se prueba la conexión invocando la ruta de `/ping`.

   ```
   wscat -c wss://{{abcdef123}}.execute-api.{{us-east-2}}.amazonaws.com/production -H "Authorization: Allow" --slash -P
   ```

   ```
   Connected (press CTRL+C to quit)
   ```

1. Ingrese el siguiente comando para hacer ping al marco de control. Puede utilizar un marco de control para keepalive los fines del cliente.

   ```
   /ping
   ```

   El resultado debe ser similar a lo siguiente:

   ```
   < Received pong (data: "")
   ```

Ahora que ha probado la conexión, se puede probar que la API funciona correctamente. En este paso, se abre una nueva ventana de terminal para que la API de WebSocket pueda enviar un mensaje a todos los clientes conectados.

**Para probar la API**

1. Abra un nuevo terminal y ejecute el comando `wscat` de nuevo con los siguientes parámetros.

   ```
   wscat -c wss://{{abcdef123}}.execute-api.{{us-east-2}}.amazonaws.com/production -H "Authorization: Allow"
   ```

   ```
   Connected (press CTRL+C to quit)
   ```

1. API Gateway determina qué ruta invocar en función de la expresión de selección de solicitud de rutas de la API. La expresión de selección de rutas de la API es `$request.body.action`. Como resultado, API Gateway invoca la ruta `sendmessage` cuando envía el siguiente mensaje:

   ```
   {"action": "sendmessage", "message": "hello, from Step Functions!"}
   ```

   La máquina de estados de Step Functions asociada a la ruta invoca una función de Lambda con el mensaje y la URL de devolución de llamada. La función de Lambda llama a la API de administración de API Gateway y envía el mensaje a todos los clientes conectados. Todos los clientes reciben el siguiente mensaje:

   ```
   < hello, from Step Functions!
   ```

Ahora que ha probado la API de WebSocket, puede desconectarse de la API.

**Para desconectarse de la API**
+ Pulse `CTRL+C` para desconectarse de la API.

  Cuando un cliente se desconecta de la API, API Gateway invoca la ruta **$disconnect** de la API. La integración de Lambda para la ruta **$disconnect** de la API elimina el ID de conexión de DynamoDB.

## Paso 7: limpiar
<a name="websocket-api-step-functions-cleanup"></a>

Para evitar costos innecesarios, elimine los recursos creados como parte de este tutorial Los siguientes pasos eliminan la pila y API de WebSocket de CloudFormation.

**Para eliminar una API de WebSocket**

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 de las **API**, seleccione la **websocket-api**.

1. Elija **Action (Acciones)**, elija **Delete (Eliminar)**y, a continuación, confirme su elección.

**Para eliminar una pila de CloudFormation**

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

1. Seleccione su pila de CloudFormation.

1. Elija **Delete (Eliminar)** y, a continuación, confirme su elección.

## Siguientes pasos
<a name="websocket-api-step-functions-next-steps"></a>

Puede automatizar la creación y la limpieza de todos los recursos de AWS involucrados en este tutorial. Para ver un ejemplo de una plantilla de CloudFormation que automatiza estas acciones para este tutorial, consulte [ws-sfn.zip](samples/ws-sfn-complete.zip).