

# Creación de rutas para las API de WebSocket en API Gateway
<a name="websocket-api-develop-routes"></a>

En la API de WebSocket, los mensajes JSON entrantes se dirigen a las integraciones de backend en función de las rutas que se hayan configurado. (Los mensajes que no son de JSON se dirigen a la ruta `$default` que se configure).

Una *ruta* incluye una *clave de ruta*, que es el valor que se espera una vez que se evalúa una *expresión de selección de ruta*. `routeSelectionExpression` es un atributo definido en el nivel de API. Especifica una propiedad JSON cuya presencia se espera en la carga del mensaje. Para obtener más información sobre las expresiones de selección de ruta, consulte [Expresiones de selección de ruta](#apigateway-websocket-api-route-selection-expressions).

Por ejemplo, si los mensajes JSON contienen una propiedad `action` y desea realizar diferentes acciones en función de esta propiedad, la expresión de selección de ruta podría ser `${request.body.action}`. La tabla de enrutamiento especificaría la acción que se debe realizar comparando el valor de la propiedad `action` con los valores de clave de ruta personalizados que se han definido en la tabla.

Existen tres rutas predefinidas que se pueden utilizar: `$connect`, `$disconnect` y `$default`. Además, es posible crear rutas personalizadas.
+ API Gateway llama a la ruta `$connect` al iniciarse una conexión persistente entre el cliente y una API de WebSocket.
+ API Gateway llama a la ruta `$disconnect` cuando el cliente o el servidor se desconecta de la API.
+ API Gateway llama a una ruta personalizada después de evaluar la expresión de selección de ruta con respecto al mensaje si se encuentra una ruta coincidente; esta coincidencia determina qué integración se invoca.
+ API Gateway llama a la ruta `$default` si la expresión de selección de ruta no puede evaluarse con respecto al mensaje o no se encuentra ninguna ruta coincidente.

## Expresiones de selección de ruta
<a name="apigateway-websocket-api-route-selection-expressions"></a>

Una *expresión de selección de ruta* se evalúa cuando el servicio está seleccionando la ruta que debe seguir un mensaje entrante. El servicio utiliza la ruta cuya `routeKey` coincida exactamente con el valor evaluado. Si no hay ninguna coincidencia y existe una ruta con la clave de ruta `$default`, se selecciona esta. Si no hay rutas que coincidan con el valor evaluado y no existe ninguna ruta `$default`, el servicio devuelve un error. En las API basadas en WebSocket, la expresión debe tener el formato `$request.body.{path_to_body_element}`.

Por ejemplo, supongamos que está enviando el siguiente mensaje JSON:

```
{
    "service" : "chat",
    "action" : "join",
    "data" : {
        "room" : "room1234"
   }
}
```

Es posible que desee seleccionar el comportamiento de la API en función de la propiedad `action`. En ese caso, podría definir la siguiente expresión de selección de ruta:

```
$request.body.action
```

En este ejemplo, `request.body` hace referencia a la carga JSON del mensaje y `.action` es una expresión [JSONPath](https://goessner.net/articles/JsonPath/). Puede utilizar cualquier expresión de ruta JSON después de `request.body`, pero tenga en cuenta que el resultado se representará en forma de cadena. Por ejemplo, si la expresión JSONPath devuelve una matriz de dos elementos, esta se presentará como la cadena `"[item1, item2]"`. Por este motivo, es conveniente que la expresión dé como resultado un valor y no una matriz ni un objeto.

Puede utilizar simplemente un valor estático o puede utilizar varias variables. En la tabla siguiente, se muestran ejemplos y sus resultados evaluados frente a la carga anterior.


| Expresión | Resultado evaluado | Descripción | 
| --- | --- | --- | 
| \$1request.body.action | join | Una variable desencapsulada | 
| \$1\$1request.body.action\$1 | join | Una variable encapsulada | 
| \$1\$1request.body.service\$1/\$1\$1request.body.action\$1 | chat/join | Varias variables con valores estáticos | 
| \$1\$1request.body.action\$1-\$1\$1request.body.invalidPath\$1  | join- | Si no se encuentra JSONPath, la variable se resueve como "". | 
| action | action | Valor estático | 
| \$1\$1default | \$1default | Valor estático | 

El resultado evaluado se utiliza para encontrar una ruta. Si hay una ruta con una clave de ruta coincidente, se selecciona la ruta para procesar el mensaje. Si no se encuentra ninguna ruta coincidente, API Gateway intenta encontrar la ruta `$default` si está disponible. Si no se ha definido la ruta `$default`, API Gateway devuelve un error.

## Configuración de rutas para una API de WebSocket en API Gateway
<a name="apigateway-websocket-api-routes"></a>

La primera vez que se crea una API de WebSocket, existen tres rutas predefinidas: `$connect`, `$disconnect` y `$default`. Puede crearlas mediante la consola, la API o la AWS CLI. Si lo desea, puede crear rutas personalizadas. Para obtener más información, consulte [Descripción general de las API de WebSocket en API Gateway](apigateway-websocket-api-overview.md).

**nota**  
En la CLI, puede crear las rutas antes o después de crear las integraciones y puede volver a utilizar la misma integración para varias rutas.

### Creación de una ruta mediante la consola de API Gateway
<a name="apigateway-websocket-api-route-using-console"></a>

**Para crear una ruta mediante la consola de API Gateway**

1. Inicie sesión en la consola de API Gateway, elija la API y, a continuación, elija **Routes (Rutas)**.

1. Elija **Crear ruta**.

1. En **Clave de la ruta**, ingrese el nombre de la clave de la ruta. Puede crear las rutas predefinidas (`$connect`, `$disconnect` y `$default`) o una ruta personalizada.
**nota**  
Cuando cree una ruta personalizada, no utilice el prefijo `$` en el nombre de la clave de ruta. Este prefijo está reservado para las rutas predefinidas.

1. Seleccione y configure el tipo de integración de la ruta. Para obtener más información, consulte [Configuración de una solicitud de integración de la API de WebSocket mediante la consola de API Gateway](apigateway-websocket-api-integration-requests.md#apigateway-websocket-api-integration-request-using-console).

### Creación de una ruta utilizando la AWS CLI
<a name="apigateway-websocket-api-route-using-awscli"></a>

El siguiente comando [create-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route.html) permite crear una ruta:

```
aws apigatewayv2 --region us-east-1 create-route --api-id aabbccddee --route-key $default
```

El resultado será similar al siguiente:

```
{
    "ApiKeyRequired": false,
    "AuthorizationType": "NONE",
    "RouteKey": "$default",
    "RouteId": "1122334"
}
```

### Especificación de los ajustes de la solicitud de ruta para `$connect`
<a name="apigateway-websocket-api-route-request-connect"></a>

Cuando se configura la ruta `$connect` para la API, están disponibles los siguientes ajustes opcionales para permitir la autorización para la API. Para obtener más información, consulte [La ruta `$connect`](apigateway-websocket-api-route-keys-connect-disconnect.md#apigateway-websocket-api-routes-about-connect).
+ **Authorization (Autorización)**: si no se necesita autorización, puede especificar `NONE`. De lo contrario, puede especificar: 
  + `AWS_IAM` para utilizar políticas estándar de AWS IAM con el fin de controlar el acceso a la API. 
  + `CUSTOM` para implementar la autorización para una API mediante la especificación de una función de autorizador de Lambda que se ha creado previamente. El autorizador puede encontrarse en su propia cuenta de AWS o en otra cuenta de AWS. Para obtener más información sobre los autorizadores de Lambda, consulte [Uso de autorizadores Lambda de API Gateway](apigateway-use-lambda-authorizer.md).
**nota**  
En la consola de API Gateway, la configuración de `CUSTOM` solo es visible después de que se haya configurado una función de autorizador como se describe en [Configuración de un autorizador de Lambda (consola)](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-with-console).
**importante**  
El valor de **Authorization (Autorización)** se aplica a toda la API, no solo a la ruta `$connect`. La ruta `$connect` protege a las demás rutas, porque se la llama en cada conexión.
+ **Clave de API obligatoria**: si lo desea, puede exigir el uso de una clave de API para la ruta `$connect` de una API. Puede utilizar las claves de API junto con los planes de uso para controlar y realizar un seguimiento del acceso a sus API. Para obtener más información, consulte [Planes de uso y clave de API para las API de REST en API Gateway](api-gateway-api-usage-plans.md).

### Configuración de la solicitud de ruta `$connect` con la consola API Gateway
<a name="apigateway-websocket-api-connect-route-request-using-console"></a>

Para configurar la solicitud de la ruta `$connect` para una API de WebSocket mediante la consola de API Gateway:

1. Inicie sesión en la consola de API Gateway, elija la API y, a continuación, elija **Routes (Rutas)**.

1. En **Rutas**, elija `$connect` o cree una ruta `$connect` según [Creación de una ruta mediante la consola de API Gateway](#apigateway-websocket-api-route-using-console).

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

1. En **Autorización**, seleccione un tipo de autorización.

1. Para solicitar una API para la ruta `$connect`, seleccione **Solicitar clave de API**.

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

# Configuración de respuestas de ruta para las API de WebSocket en API Gateway
<a name="apigateway-websocket-api-route-response"></a>

Las rutas de WebSocket se pueden configurar para la comunicación unidireccional o bidireccional. API Gateway no pasará la respuesta del backend a través de la respuesta de la ruta, a menos configure una respuesta de ruta. 

**nota**  
Solo puede definir la respuesta de la ruta `$default` para las API de WebSocket. Puede utilizar una respuesta de integración para manipular la respuesta de un servicio de backend. Para obtener más información, consulte [Información general sobre las respuestas de integración](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-overview). 

Puede configurar respuestas de ruta y expresiones de selección de respuestas mediante la consola de API Gateway o la AWS CLI o un AWS SDK. 

Para obtener más información sobre las expresiones de selección de respuesta de ruta, consulte [Expresiones de selección de respuesta de ruta](apigateway-websocket-api-selection-expressions.md#apigateway-websocket-api-route-response-selection-expressions).

**Topics**
+ [Configurar una respuesta de ruta mediante la consola de API Gateway](#apigateway-websocket-api-route-response-using-console)
+ [Configuración de una respuesta de ruta con la AWS CLI](#apigateway-websocket-api-route-response-using-awscli)

## Configurar una respuesta de ruta mediante la consola de API Gateway
<a name="apigateway-websocket-api-route-response-using-console"></a>

Tras crear una API de WebSocket y asociar una función de Lambda proxy a la ruta predeterminada, puede configurar la respuesta de la ruta mediante la consola de API Gateway:

1. Inicie sesión en la consola de API Gateway y elija una API de WebSocket con una integración de función de Lambda de proxy en la ruta `$default`.

1. En **Routes** (Rutas), elija la ruta `$default`.

1. Elija **Habilitar la comunicación bidireccional**. 

1. Elija **Implementar API**.

1. Implemente su API en una etapa.

 Use el siguiente comando [wscat](https://www.npmjs.com/package/wscat) para conectarse a la API. Para obtener más información acerca de `wscat`, consulte [Utilice `wscat` para conectarse y enviar mensajes a una API de WebSocket](apigateway-how-to-call-websocket-api-wscat.md). 

```
wscat -c wss://api-id.execute-api.us-east-2.amazonaws.com/test
```

 Pulse el botón Enter para llamar a la ruta predeterminada. El cuerpo de la función de Lambda debería regresar.

## Configuración de una respuesta de ruta con la AWS CLI
<a name="apigateway-websocket-api-route-response-using-awscli"></a>

El siguiente comando [create-route-response](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route-response.html) permite crear una respuesta de ruta para la ruta `$default`. Puede identificar el ID de la API y el ID de ruta con los comandos [get-apis](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-apis.html) y [get-routes](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-routes.html).

```
aws apigatewayv2 create-route-response \
    --api-id aabbccddee \
    --route-id 1122334  \
    --route-response-key '$default'
```

El resultado será similar al siguiente:

```
{
    "RouteResponseId": "abcdef",
    "RouteResponseKey": "$default"
}
```

# Configuración de una ruta `$connect` que requiere un subprotocolo WebSocket
<a name="websocket-connect-route-subprotocol"></a>

Los clientes pueden usar el campo `Sec-WebSocket-Protocol` para solicitar un [subprotocolo WebSocket](https://datatracker.ietf.org/doc/html/rfc6455#page-12) durante la conexión a su API de WebSocket. Puede configurar una integración de la ruta `$connect` para permitir conexiones solo si un cliente solicita un subprotocolo compatible con su API.

La siguiente función de Lambda de ejemplo devuelve el encabezado `Sec-WebSocket-Protocol` a los clientes. La función establece una conexión a su API solo si el cliente especifica el subprotocolo `myprotocol`.

Para obtener una plantilla de CloudFormation que cree este ejemplo de integración de API y proxy de Lambda, consulte [samples/ws-subprotocol.zip](samples/ws-subprotocol.zip).

```
export const handler = async (event) => {
    if (event.headers != undefined) {
        const headers = toLowerCaseProperties(event.headers);
        
        if (headers['sec-websocket-protocol'] != undefined) {
            const subprotocolHeader = headers['sec-websocket-protocol'];
            const subprotocols = subprotocolHeader.split(',');
            
            if (subprotocols.indexOf('myprotocol') >= 0) {
                const response = {
                    statusCode: 200,
                    headers: {
                        "Sec-WebSocket-Protocol" : "myprotocol"
                    }
                };
                return response;
            }
        }
    }
    
    const response = {
        statusCode: 400
    };
        
    return response;
};

function toLowerCaseProperties(obj) {
    var wrapper = {};
    for (var key in obj) {
        wrapper[key.toLowerCase()] = obj[key];
    }
    return wrapper;
}
```

Puede usar [https://www.npmjs.com/package/wscat](https://www.npmjs.com/package/wscat) para probar si su API permite conexiones solo si un cliente solicita un subprotocolo compatible con su API. Los siguientes comandos utilizan el indicador `-s` para especificar subprotocolos durante la conexión.

El siguiente comando intenta una conexión con un subprotocolo no compatible. Dado que el cliente especificó el subprotocolo `chat1`, la integración de Lambda devuelve un error 400 y la conexión no es correcta.

```
wscat -c wss://api-id.execute-api.region.amazonaws.com/beta -s chat1
error: Unexpected server response: 400
```

El siguiente comando incluye un subprotocolo admitido en la solicitud de conexión. La integración de Lambda permite la conexión.

```
wscat -c wss://api-id.execute-api.region.amazonaws.com/beta -s chat1,myprotocol
connected (press CTRL+C to quit)
```

Para obtener más información acerca de cómo invocar la API de WebSocket, consulte [Invocación de las API de WebSocket](apigateway-how-to-call-websocket-api.md).