

# API Gateway で WebSocket API のルートを作成する
<a name="websocket-api-develop-routes"></a>

WebSocket API では、受信する JSON メッセージは設定したルートに基づいてバックエンド統合に転送されます (JSON 以外のメッセージは、設定した `$default` ルートに転送されます)。

*ルート*には*ルートキー*が含まれます。これは、*ルート選択式*が評価されたときに予期される値です。属性 `routeSelectionExpression` は、API レベルで定義されます。メッセージペイロードに存在することが予期される JSON プロパティを指定します。ルート選択式の詳細については、「[ルート選択式](#apigateway-websocket-api-route-selection-expressions)」を参照してください。

たとえば、JSON メッセージに `action` プロパティが含まれていて、このプロパティに基づいてさまざまなアクションを実行する場合、ルート選択式は `${request.body.action}` のようになります。ルーティングテーブルでは、このテーブルで定義したカスタムルートキーの値に対して、`action` プロパティの値を一致させることによって、実行するアクションを指定します。

3 つの事前定義されたルート (`$connect`、`$disconnect`、および `$default`) を使用できます。さらに、カスタムルートを作成することができます。
+ API Gateway は、クライアントと WebSocket API 間の永続的な接続が開始されたときに、`$connect` ルートを呼び出します。
+ API Gateway は、クライアントまたはサーバーが API から切断したときに、`$disconnect` ルートを呼び出します。
+ API Gateway は、一致するルートが見つかった場合、メッセージに対してルート選択式が評価された後でカスタムルートを呼び出します。この一致により、呼び出される統合が決まります。
+ ルート選択式をメッセージに対して評価できない場合や、一致するルートが見つからない場合、API Gateway は `$default` ルートを呼び出します。

## ルート選択式
<a name="apigateway-websocket-api-route-selection-expressions"></a>

*ルート選択式*は、サービスが受信メッセージについてたどるルートを選択するときに評価されます。このサービスでは、`routeKey` が評価された値に完全に一致するときにルートが使用されます。何も一致せず、`$default` ルートキーを持つルートが存在する場合は、そのルートが選択されます。評価された値と一致するルートがなく、`$default` ルートもない場合、サービスからエラーが返されます。WebSocket ベースの API の場合、式の形式は `$request.body.{path_to_body_element}` である必要があります。

たとえば、次の JSON メッセージを送信するとします。

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

`action` プロパティに基づいて、API の動作を選択する必要があります。その場合は、次のルート選択式を定義できます。

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

この例で `request.body` は、メッセージの JSON ペイロードを参照し、`.action` が [JSONPath](https://goessner.net/articles/JsonPath/) 式になります。JSON パス式は `request.body` の後に使用できますが、結果は文字列化されることに注意してください。たとえば、JSONPath 式は 2 つの要素の配列を返し、文字列 `"[item1, item2]"` として表示されます。このため、式は配列やオブジェクトではなく値に対して評価することをお勧めします。

静的な値を使用するか、複数の変数を使用できます。以下の表に示しているのは、例と上記のペイロードに対して評価された結果です。


| 式 | 評価結果 | 説明 | 
| --- | --- | --- | 
| \$1request.body.action | join | 1 つのラップ解除された変数 | 
| \$1\$1request.body.action\$1 | join | 1 つのラップされた変数 | 
| \$1\$1request.body.service\$1/\$1\$1request.body.action\$1 | chat/join | 静的な値を持つ複数の変数 | 
| \$1\$1request.body.action\$1-\$1\$1request.body.invalidPath\$1  | join- | JSONPath が見つからない場合、変数は "" として解決されます。 | 
| action | action | 静的な値 | 
| \$1\$1default | \$1default | 静的な値 | 

評価された結果は、ルートを見つけるために使用されます。一致するルートキーがあるルートがある場合、そのルートがメッセージを処理するために選択されます。一致するルートが見つからなかった場合、API Gateway は `$default` ルートを見つけようとします (利用可能な場合)。`$default` ルートが定義されていない場合、API Gateway はエラーを返します。

## API Gateway で WebSocket API のルートを設定する
<a name="apigateway-websocket-api-routes"></a>

新しい WebSocket API を初めて作成するときは、3 つの事前定義されたルート (`$connect`、`$disconnect`、`$default`) があります。これらのルートは、コンソール、API、または AWS CLI を使って作成できます。必要に応じて、カスタムルートを作成することができます。詳細については、「[API Gateway での WebSocket API の概要](apigateway-websocket-api-overview.md)」を参照してください。

**注記**  
CLI では、統合を作成する前または後にルートを作成したり、複数のルートで同じ統合を再利用したりできます。

### API Gateway コンソールを使用したルートの作成
<a name="apigateway-websocket-api-route-using-console"></a>

**API Gateway コンソールを使用してルートを作成するには**

1. API Gateway コンソールにサインインし、[API]、[**Routes (ルート)**] の順に選択します。

1. **[ルートの作成]** を選択します。

1. **[ルートキー]** に、ルートキー名を入力します。定義済みのルート (`$connect`、`$disconnect`、および`$default`) またはカスタムルートを作成できます。
**注記**  
カスタムルートを作成する場合、ルートキー名に `$` プレフィックスは使用しないでください。このプレフィックスは事前定義されたルートのために予約されています。

1. ルートの統合タイプを選択して設定します。詳細については、「[API Gateway コンソールを使用して WebSocket API 統合リクエストを設定する](apigateway-websocket-api-integration-requests.md#apigateway-websocket-api-integration-request-using-console)」を参照してください。

### AWS CLI を使用したルートの作成
<a name="apigateway-websocket-api-route-using-awscli"></a>

次の [create-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route.html) コマンドは、ルートを作成します。

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

出力は次のようになります。

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

### `$connect` のルートリクエスト設定の指定
<a name="apigateway-websocket-api-route-request-connect"></a>

API の `$connect` ルートを設定するときは、以下のオプション設定を使用して、API の認可を有効にできます。詳細については、「[`$connect` ルート](apigateway-websocket-api-route-keys-connect-disconnect.md#apigateway-websocket-api-routes-about-connect)」を参照してください。
+ **認可**: 認可が必要ない場合は、`NONE`を指定できます。それ以外の場合は、以下を指定できます。
  + API へのアクセスを制御するために標準の AWS IAM ポリシーを使用するには、`AWS_IAM` を指定します。
  + 以前に作成した Lambda オーソライザー関数を指定して API の認可を実装するには、`CUSTOM` を指定します。オーソライザーは、独自の AWS アカウントまたは別の AWS アカウントに設定できます。Lambda オーソライザーの詳細については、「[API Gateway Lambda オーソライザーを使用する](apigateway-use-lambda-authorizer.md)」を参照してください。
**注記**  
API Gateway コンソールで、`CUSTOM` 設定は「[Lambda オーソライザーを設定する (コンソール)](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-with-console)」で説明したオーソライザー関数を設定した後でのみ表示されます。
**重要**  
**[認可]** 設定は、`$connect` ルートだけではなく、API 全体に適用されます。`$connect` ルートは、すべての接続で呼び出されるため、他のルートを保護します。
+ **API キーの必要性**: 必要に応じて、API の `$connect` ルートで API キーを必須にすることができます。API キーを使用量プランと一緒に使用して、API へのアクセスを制御、追跡できます。詳細については、「[API Gateway での REST API の使用量プランと API キー](api-gateway-api-usage-plans.md)」を参照してください。

### API Gateway コンソールを使用して `$connect` ルートリクエストをセットアップする
<a name="apigateway-websocket-api-connect-route-request-using-console"></a>

API Gateway コンソールを使用して WebSocket API の `$connect` ルートリクエストを設定するには

1. API Gateway コンソールにサインインし、[API]、[**Routes (ルート)**] の順に選択します。

1. **[ルート]** で、`$connect` を選択するか、[API Gateway コンソールを使用したルートの作成](#apigateway-websocket-api-route-using-console) に従って `$connect` ルートを作成します。

1. **[ルートリクエスト設定]** セクションで、**[編集]** を選択します。

1. **[認可]** では、認可タイプを選択します。

1. `$connect` ルートで API キーを必須にするには、**[API キーを必須化]** を選択します。

1. **[Save changes]** (変更の保存) をクリックします。

# API Gateway で WebSocket API のルートレスポンスを設定する
<a name="apigateway-websocket-api-route-response"></a>

WebSocket ルートは、双方向または単方向通信に対して設定できます。ユーザーがルートレスポンスを設定しない限り、API Gateway はルートレスポンスにバックエンドレスポンスを渡しません。

**注記**  
WebSocket API の `$default` ルートレスポンスのみを定義できます。統合レスポンスを使用して、バックエンドサービスからのレスポンスを操作できます。詳細については、「[統合レスポンスの概要](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-overview)」を参照してください。

API Gateway コンソール、AWS CLI、または AWS SDK を使用して、ルートレスポンスとレスポンス選択式を設定できます。

ルートレスポンス選択式の設定の詳細については、「[ルートレスポンス選択式](apigateway-websocket-api-selection-expressions.md#apigateway-websocket-api-route-response-selection-expressions)」を参照してください。

**Topics**
+ [API Gateway コンソールを使用したルートレスポンスの設定](#apigateway-websocket-api-route-response-using-console)
+ [AWS CLI を使用してルートレスポンスを設定する](#apigateway-websocket-api-route-response-using-awscli)

## API Gateway コンソールを使用したルートレスポンスの設定
<a name="apigateway-websocket-api-route-response-using-console"></a>

WebSocket API を作成し、プロキシ Lambda 関数をデフォルトルートにアタッチしたら、API Gateway コンソールを使用してルートレスポンスを設定できます。

1. API Gateway コンソールにサインインし、`$default` ルートの Lambda 関数の統合で WebSocket API を選択します。

1. **[Routes]** (ルート) で、`$default` ルートを選択します。

1. **[双方向通信を有効にする]** を選択します。

1. [**API のデプロイ**] を選択します。

1. API をステージにデプロイします。

 以下の [wscat](https://www.npmjs.com/package/wscat) コマンドを使用して、API に接続します。`wscat` の詳細については、「[`wscat` を使用した WebSocket API への接続とメッセージの送信](apigateway-how-to-call-websocket-api-wscat.md)」を参照してください。

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

 Enter ボタンを押して、デフォルトルートを呼び出します。Lambda 関数の本体が戻るはずです。

## AWS CLI を使用してルートレスポンスを設定する
<a name="apigateway-websocket-api-route-response-using-awscli"></a>

次の [create-route-response](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route-response.html) コマンドは、`$default` ルートのルートレスポンスを作成します。API ID とルート ID は、[get-apis](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-apis.html) コマンドと [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'
```

出力は次のようになります。

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

# WebSocket サブプロトコルを必要とする `$connect` ルートを設定する
<a name="websocket-connect-route-subprotocol"></a>

クライアントは、WebSocket API への接続中に、`Sec-WebSocket-Protocol` フィールドを使用して [WebSocket サブプロトコル](https://datatracker.ietf.org/doc/html/rfc6455#page-12)をリクエストできます。API がサポートするサブプロトコルをクライアントがリクエストした場合にのみ接続を許可するように、`$connect` ルートの統合を設定できます。

次の Lambda 関数の例は、`Sec-WebSocket-Protocol` ヘッダーをクライアントに返します。この関数は、クライアントが `myprotocol` サブプロトコルを指定した場合のみ API への接続を確立します。

このサンプル API と Lambda プロキシ統合を作成する CloudFormation テンプレートについては、[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;
}
```

[https://www.npmjs.com/package/wscat](https://www.npmjs.com/package/wscat) を使用して、API がサポートするサブプロトコルをクライアントがリクエストした場合にのみ API が接続を許可することをテストできます。次のコマンドは、`-s` フラグを使用して、接続中にサブプロトコルを指定します。

次のコマンドは、サポートされていないサブプロトコルとの接続を試行します。クライアントが `chat1` サブプロトコルを指定したため、Lambda 統合は 400 エラーを返し、接続は失敗します。

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

次のコマンドは、サポートされているサブプロトコルを接続リクエストに含めます。Lambda 統合により、接続が可能になります。

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

WebSocket API の呼び出しの詳細については、「[WebSocket API を呼び出す](apigateway-how-to-call-websocket-api.md)」を参照してください。