

# API Gateway での WebSocket API の概要
<a name="apigateway-websocket-api-overview"></a>

API Gateway では、AWS のサービス (Lambda や DynamoDB など) または HTTP エンドポイントのステートフルフロントエンドとして WebSocket API を作成できます。WebSocket API は、クライアントアプリから受信するメッセージのコンテンツに基づいて、バックエンドを呼び出します。

WebSocket API は、リクエストを受け取って応答する REST API とは異なり、クライアントアプリとバックエンド間の双方向通信をサポートします。バックエンドは、接続されたクライアントにコールバックメッセージを送信できます。

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

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

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

## WebSocket API のルートを使用する
<a name="apigateway-websocket-api-overview-routes"></a>

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

`$connect` および `$disconnect` ルートの詳細については、「[接続されたユーザーとクライアントアプリを管理する: `$connect` ルートおよび `$disconnect` ルート](apigateway-websocket-api-route-keys-connect-disconnect.md)」を参照してください。

`$default` ルートおよびカスタムルートの詳細については、「[API Gateway の `$default` ルートおよびカスタムルートを使用してバックエンド統合を呼び出す](apigateway-websocket-api-routes-integrations.md)」を参照してください。

## 接続されたクライアントアプリケーションにデータを送信する
<a name="apigateway-websocket-api-overview-send-data"></a>

バックエンドサービスは、接続されたクライアントアプリにデータを送信できます。以下を実行することにより、データを送信できます。
+ 統合を使用してレスポンスを送信します。レスポンスは、定義したルートレスポンスでクライアントに返されます。
+ `@connections` API を使用して POST リクエストを送信することができます。詳細については、「[バックエンドサービスでの `@connections` コマンドの使用](apigateway-how-to-call-websocket-api-connections.md)」を参照してください。

## WebSocket API ステータスコード
<a name="apigateway-websocket-status-codes"></a>

API Gateway WebSocket API は、[WebSocket Close Code Number Registry](https://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number) に説明されているように、サーバーからクライアントへの通信に次のステータスコードを使用します。

1001  
API Gateway は、クライアントが 10 分間アイドル状態であるか、最大 2 時間の接続の存続時間に達したときに、このステータスコードを返します。

1003  
API Gateway は、エンドポイントがバイナリメディアタイプを受信すると、このステータスコードを返します。バイナリメディアタイプは WebSocket API ではサポートされていません。

1005  
API Gateway は、クライアントがクローズコードなしでクローズフレームを送信すると、このステータスコードを返します。

1006  
API Gateway は、WebSocket クローズフレームなしで TCP 接続が閉じられるなど、接続が予期せず閉じられた場合、このステータスコードを返します。

1008  
API Gateway は、エンドポイントが特定のクライアントから受信したリクエストが多すぎると、このステータスコードを返します。

1009  
API Gateway は、エンドポイントが処理するには大きすぎるメッセージを受信すると、このステータスコードを返します。

1011  
API Gateway は、内部サーバーエラーが発生したときに、このステータスコードを返します。

1012  
サービスが再起動すると、API Gateway はこのステータスコードを返します。

# 接続されたユーザーとクライアントアプリを管理する: `$connect` ルートおよび `$disconnect` ルート
<a name="apigateway-websocket-api-route-keys-connect-disconnect"></a>

次のセクションでは、WebSocket API の `$connect` ルートおよび `$disconnect` ルートを使用する方法について説明します。

**Topics**
+ [`$connect` ルート](#apigateway-websocket-api-routes-about-connect)
+ [`$connect` ルートからの接続情報の受け渡し](#apigateway-websocket-api-passing-connectionId-on-connect)
+ [`$disconnect` ルート](#apigateway-websocket-api-routes-about-disconnect)

## `$connect` ルート
<a name="apigateway-websocket-api-routes-about-connect"></a>

クライアントアプリは、WebSocket アップグレードリクエストを送信して WebSocket API に接続します。リクエストが成功すると、接続が確立されている間に `$connect` ルートが実行されます。

WebSocket 接続はステートフルな接続であるため、`$connect` ルートのみで認可を設定できます。`AuthN`/`AuthZ` は接続時にのみ実行されます。

`$connect` ルートに関連付けられている統合の実行が完了するまで、アップグレードリクエストは保留中になり、実際の接続は確立されません。`$connect` リクエストが失敗した場合 (`AuthN`/`AuthZ` の障害や統合の障害など)、接続は行われません。

**注記**  
`$connect` で承認が失敗した場合、接続は確立されず、クライアントは `401` または `403` レスポンスを受け取ります。

`$connect` の統合の設定はオプションです。次の場合は `$connect` 統合の設定を検討してください。
+ `Sec-WebSocket-Protocol` フィールドを使用して、クライアントがサブプロトコルを指定できるようにする。サンプルコードについては、「[WebSocket サブプロトコルを必要とする `$connect` ルートを設定する](websocket-connect-route-subprotocol.md)」を参照してください。
+ クライアントが接続したときに通知を受ける。
+ 接続をスロットリングする、または接続するユーザーを管理する。
+ バックエンドで、コールバック URL を使用してメッセージをクライアントに送信する。
+ 各接続 ID およびその他の情報をデータベース (例: Amazon DynamoDB) に保存する。

## `$connect` ルートからの接続情報の受け渡し
<a name="apigateway-websocket-api-passing-connectionId-on-connect"></a>

 プロキシ統合と非プロキシ統合の両方を使用して、`$connect` ルートからデータベースまたは他の AWS のサービス に情報を渡すことができます。

### プロキシ統合を使用して接続情報を渡すには
<a name="websocket-connect-proxy-integration"></a>

イベントでは、Lambda プロキシ統合から接続情報にアクセスできます。別の AWS のサービス または AWS Lambda 関数を使用して接続に投稿します。

次の Lambda 関数は、`requestContext` オブジェクトを使用して接続 ID、ドメイン名、ステージ名、およびクエリ文字列を記録する方法を示しています。

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

```
 export const handler = async(event, context) => {
    const connectId = event["requestContext"]["connectionId"]
    const domainName = event["requestContext"]["domainName"]
    const stageName = event["requestContext"]["stage"]
    const qs = event['queryStringParameters']
    console.log('Connection ID: ', connectId, 'Domain Name: ', domainName, 'Stage Name: ', stageName, 'Query Strings: ', qs )
    return {"statusCode" : 200}
};
```

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

```
import json
import logging
logger = logging.getLogger()
logger.setLevel("INFO")


def lambda_handler(event, context):
    connectId = event["requestContext"]["connectionId"]
    domainName = event["requestContext"]["domainName"]
    stageName = event["requestContext"]["stage"]
    qs = event['queryStringParameters']
    connectionInfo = {
        'Connection ID': connectId,
        'Domain Name': domainName,
        'Stage Name': stageName,
        'Query Strings': qs}
    logging.info(connectionInfo)
    return {"statusCode": 200}
```

------

### 非プロキシ統合を使用して接続情報を渡すには
<a name="websocket-connect-non-proxy-integration"></a>
+ 非プロキシ統合により接続情報にアクセスできます。統合リクエストを設定し、WebSocket API リクエストテンプレートを提供します。以下の、[Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) マッピングテンプレートは、統合リクエストを提供します。このリクエストは、以下の詳細を非プロキシ統合に送信します。
  + 接続 ID
  + ドメイン名
  + ステージ名
  + パス
  + ヘッダー
  + クエリ文字列

  このリクエストは、接続 ID、ドメイン名、ステージ名、パス、ヘッダー、クエリ文字列を非プロキシ統合に送信します。

  ```
  {
      "connectionId": "$context.connectionId",
      "domain": "$context.domainName",
      "stage": "$context.stage",
      "params": "$input.params()"
  }
  ```

  データ変換の設定の詳細については、「[API Gateway での WebSocket API のデータ変換](websocket-api-data-transformations.md)」を参照してください。

  統合リクエストを完了するには、統合レスポンスに `StatusCode: 200` を設定します。統合レスポンスの詳しい設定方法については、「[API Gateway コンソールを使用した統合レスポンスの設定](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-using-console)」を参照してください。

## `$disconnect` ルート
<a name="apigateway-websocket-api-routes-about-disconnect"></a>

`$disconnect` ルートは、接続を閉じた後に実行されます。

接続は、サーバーまたはクライアントによって閉じることができます。接続が実行されると、接続がすでに閉じられているため、`$disconnect` がベストエフォート型のイベントです。API Gateway は、統合に `$disconnect` イベントを配信するために最善を尽くしますが、配信を保証することはできません。

バックエンドは、`@connections` API を使用して切断を開始できます。詳細については、「[バックエンドサービスでの `@connections` コマンドの使用](apigateway-how-to-call-websocket-api-connections.md)」を参照してください。

# API Gateway の `$default` ルートおよびカスタムルートを使用してバックエンド統合を呼び出す
<a name="apigateway-websocket-api-routes-integrations"></a>

次のセクションでは、WebSocket API の `$default` ルートまたはカスタムルートを使用してバックエンド統合を呼び出す方法について説明します。

**Topics**
+ [ルートを使用したメッセージの処理](#apigateway-websocket-api-overview-routes)
+ [`$default` ルート](#apigateway-websocket-api-routes-about-default)
+ [カスタムルート](#apigateway-websocket-api-routes-about-custom)
+ [API Gateway WebSocket API 統合を使用したビジネスロジックへの接続](#apigateway-websocket-api-overview-integrations)
+ [WebSocket API と REST API の重要な相違点](#apigateway-websocket-api-overview-integrations-differences)

## ルートを使用したメッセージの処理
<a name="apigateway-websocket-api-overview-routes"></a>

API Gateway WebSocket API では、クライアントからバックエンドサービスに、またはその逆にメッセージを送信できます。HTTP のリクエスト/レスポンスモデルとは異なり、WebSocket ではクライアントがアクションを実行することなく、バックエンドがクライアントにメッセージを送信できます。

メッセージの形式は JSON または JSON 以外とすることができます。ただし、メッセージの内容によっては、JSON メッセージのみを特定の統合にルーティングできます。JSON 以外のメッセージは、`$default` ルートによってバックエンドにパススルーされます。

**注記**  
API Gateway は最大 128 KB までのメッセージペイロードをサポートし、最大フレームサイズは 32 KB です。メッセージが 32 KB を超えた場合は、それぞれが 32 KB 以下の複数のフレームに分割する必要があります。大きなメッセージ (またはフレーム) が受信された場合、接続は 1009 コードで閉じられます。  
現時点では、バイナリペイロードはサポートされていません。バイナリフレームが受信された場合、接続は 1003 コードで閉じられます。ただし、バイナリペイロードはテキストに変換できます。「[API Gateway での WebSocket API のバイナリメディアタイプ](websocket-api-develop-binary-media-types.md)」を参照してください。

API Gateway の WebSocket API では、メッセージの内容に基づいて JSON メッセージをルーティングし、特定のバックエンドサービスを実行できます。クライアントが WebSocket 接続経由でメッセージを送信すると、これが WebSocket API に対する*ルートリクエスト*になります。リクエストが、API Gateway の対応するルートキーを持つルートと照合されます。WebSocket API のルートリクエストは、API Gateway コンソールで、または AWS CLI もしくは AWS SDK を使用してセットアップできます。

**注記**  
AWS CLI および AWS SDK で、統合を作成する前または後にルートを作成できます。現在のところ、コンソールは統合の再利用をサポートしていないため、最初にルートを作成してから、そのルートの統合を作成する必要があります。

統合リクエストを進める前にルートリクエストの検証を実行するよう API Gateway を設定できます。検証に失敗すると、API Gateway はバックエンドを呼び出さずにリクエストを失敗させ、次のような `"Bad request body"` ゲートウェイレスポンスをクライアントに送信し、CloudWatch Logs で検証の失敗を発行します。

```
{"message" : "Bad request body", "connectionId": "{connectionId}", "messageId": "{messageId}"}
```

これによりバックエンドへの不要な呼び出しが減り、API のその他の要件に集中することができます。

また、API のルートに対するルートのレスポンスを定義し、双方向通信を有効にすることもできます。ルートレスポンスは、特定のルートの統合の完了時にどのようなデータがクライアントに送信されるかを示します。たとえば、クライアントがレスポンスを受信せずにバックエンドにレスポンスを送信するようにする場合 (単方向通信)、ルートのレスポンスを定義する必要はありません。ただし、ルートレスポンスのルートを提供しない場合、API Gateway は統合の結果に関する情報をクライアントに送信しません。

## `$default` ルート
<a name="apigateway-websocket-api-routes-about-default"></a>

すべての API Gateway WebSocket API は、`$default` ルートを持つことができます。これは、次の方法で使用できる特殊なルーティング値です。
+ これを定義されたルートキーと一緒に使用し、定義されたいずれのキーとも一致しない受信メッセージの「フォールバック」ルート (たとえば、特定のエラーメッセージを返す汎用モック統合) を指定できます。
+ 定義されたルートキーなしでこれを使用し、バックエンドコンポーネントにルーティングを委任するプロキシモデルを指定できます。
+ これを使用して、JSON 以外のペイロードのルートを指定できます。

## カスタムルート
<a name="apigateway-websocket-api-routes-about-custom"></a>

メッセージの内容に基づいて特定の統合を呼び出す場合、カスタムルートを作成してこれを行うことができます。

カスタムルートは、指定されたルートキーと統合を使用します。受信メッセージにプロパティ JSON プロパティが含まれていて、そのプロパティがルートキーの値に一致する値に評価される場合、API Gateway は統合を呼び出します。(詳しくは、[API Gateway での WebSocket API の概要](apigateway-websocket-api-overview.md) を参照してください)。

たとえば、チャットルームアプリケーションを作成するとします。ルート選択式が `$request.body.action` である WebSocket API を作成して開始できます。次に、`joinroom` および `sendmessage` の 2 つのルートを定義できます。クライアントアプリは、次のようなメッセージを送信して `joinroom` ルートを呼び出す場合があります。

```
{"action":"joinroom","roomname":"developers"}
```

また、次のようなメッセージを送信して `sendmessage` ルートを呼び出す場合があります。

```
{"action":"sendmessage","message":"Hello everyone"}
```

## API Gateway WebSocket API 統合を使用したビジネスロジックへの接続
<a name="apigateway-websocket-api-overview-integrations"></a>

API Gateway WebSocket API のルートを設定したら、使用する統合を指定する必要があります。ルートリクエストとルートレスポンスを持つことができるルートと同じように、統合は*統合リクエスト*と*統合レスポンス*を持つことができます。*統合リクエスト*には、クライアントから受け取ったリクエストを処理するためにバックエンドで予期される情報が含まれます。*統合レスポンス*には、バックエンドが API Gateway に返すデータが含まれます。このデータは、クライアントに送信するメッセージを作成するために使用される場合があります (ルートレスポンスが定義されている場合)。

統合の設定の詳細については、「[API Gateway での WebSocket API の統合](apigateway-websocket-api-integrations.md)」を参照してください。

## WebSocket API と REST API の重要な相違点
<a name="apigateway-websocket-api-overview-integrations-differences"></a>

WebSocket API の統合は REST API の統合に似ていますが、次のような違いがあります。
+ 現時点では、API Gateway コンソールで最初にルートを作成してから、そのルートのターゲットとして統合を作成する必要があります。ただし、API と CLI では、ルートと統合を任意の順序で個別に作成できます。
+ 複数のルートに単一の統合を使用できます。たとえば、相互に密接に関連した一連のアクションがある場合は、それらのすべてのルートを単一の Lambda 関数に移動したい場合があります。統合の詳細を複数回定義する代わりに、1 回指定して、関連する各ルートに割り当てることができます。
**注記**  
現在のところ、コンソールは統合の再利用をサポートしていないため、最初にルートを作成してから、そのルートの統合を作成する必要があります。  
AWS CLI、AWS SDK では、ルートのターゲットを `"integrations/{integration-id}"` の値に設定して統合を再利用できます。ここで `{integration-id}"` は、ルートに関連付ける統合の一意の ID です。
+ API Gateway は、ルートと統合で使用できる複数の[選択式](apigateway-websocket-api-selection-expressions.md)を提供します。入力テンプレートまたは出力マッピングを選択するために、コンテンツタイプに依存する必要はありません。ルート選択式の場合と同様に、API Gateway で評価される選択式を定義して、適切な項目を選択できます。それらのすべては、一致するテンプレートが見つからない場合に、`$default` テンプレートにフォールバックされます。
  + 統合リクエストで、テンプレート選択式は `$request.body.<json_path_expression>` および静的な値をサポートしています。
  + 統合レスポンスで、テンプレート選択式は `$request.body.<json_path_expression>`、`$integration.response.statuscode`、`$integration.response.header.<headerName>`、および静的な値をサポートします。

リクエストとレスポンスが同期的に送信される HTTP プロトコルでは、通信は基本的に一方向です。WebSocket プロトコルでは、通信は双方向です。レスポンスは非同期であり、必ずしもクライアントのメッセージの送信と同じ順序でクライアントによって受信される必要はありません。さらに、バックエンドはクライアントにメッセージを送信できます。

**注記**  
`AWS_PROXY` または `LAMBDA_PROXY` 統合を使用するように設定されたルートでは、通信は一方向で、API Gateway は自動的にルートレスポンスにバックエンドレスポンスをパススルーしません。たとえば、`LAMBDA_PROXY` 統合の場合は、 Lambda 関数が返す本文はクライアントに返されません。クライアントが統合レスポンスを受信するには、ルートレスポンスを定義して、双方向通信を可能にする必要があります。

# WebSocket 選択式
<a name="apigateway-websocket-api-selection-expressions"></a>

API Gateway はリクエストとレスポンスのコンテキストを評価し、キーを生成する方法として、選択式を使用します。次に、このキーを使用して、通常は API デベロッパーから提供される使用可能な値のセットから選択できます。サポートされている正確な変数のセットは、式によって異なります。各式については、以下で詳しく説明します。

すべての式では、言語は一連のルールに従います。
+ 変数には `"$"` が前に付けられます。
+ 中かっこを使用して、変数の境界を明示的に定義できます (例: `"${request.body.version}-beta"`)。
+ 複数の変数がサポートされていますが、評価は 1 回しか発生しません (繰り返しの評価は行われません)。
+ ドル記号 (`$`) を使って `"\"` をエスケープすることができます。これは、予約された `$default` キー (例: `"\$default"`) にマッピングされる式を定義するときに最も便利です。
+ 場合によっては、パターン形式が必要です。この場合、式は `"/"` のようにスラッシュ (`"/2\d\d/"`) で囲み、`2XX` のステータスコードに合わせる必要があります。

**Topics**
+ [ルートレスポンス選択式](#apigateway-websocket-api-route-response-selection-expressions)
+ [API キー選択式](#apigateway-websocket-api-apikey-selection-expressions)
+ [API マッピング選択式](#apigateway-websocket-api-mapping-selection-expressions)
+ [WebSocket 選択式の概要](#apigateway-websocket-api-selection-expression-table)

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

[ルートレスポンス](apigateway-websocket-api-route-response.md)は、バックエンドからクライアントにレスポンスをモデル化するために使用されます。WebSocket API の場合、ルートレスポンスはオプションです。定義された場合、WebSocket メッセージを受信したときにレスポンスをクライアントに返す必要があることを API Gateway に指定します。

*ルートレスポンス選択式*の評価により、ルートレスポンスキーが生成されます。最終的に、このキーを使用して、API に関連付けられたいずれかの [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid-routeresponses.html](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid-routeresponses.html) から選択されます。ただし、現在サポートされているのは `$default` キーのみです。

## API キー選択式
<a name="apigateway-websocket-api-apikey-selection-expressions"></a>

この式は、クライアントが有効な [API キー](api-gateway-basic-concept.md#apigateway-definition-api-key)を提供した場合のみ、特定のリクエストを続行する必要があるとサービスが決定したときに評価されます。

現在サポートされている値は、`$request.header.x-api-key` および `$context.authorizer.usageIdentifierKey` の 2 つのみです。

## API マッピング選択式
<a name="apigateway-websocket-api-mapping-selection-expressions"></a>

この式は、カスタムドメインを使用してリクエストが実行されたときに選択する API ステージを決定するために評価されます。

現在、サポートされている値は `$request.basepath` のみです。

## WebSocket 選択式の概要
<a name="apigateway-websocket-api-selection-expression-table"></a>

次の表は、WebSocket API の選択式のユースケースをまとめたものです。


| 選択式 | 評価結果のキー | コメント | ユースケースの例 | 
| --- | --- | --- | --- | 
| Api.RouteSelectionExpression | Route.RouteKey | \$1default はキャッチオールルートとしてサポートされています。 | クライアントリクエストのコンテキストに基づいて Route WebSocket メッセージをルーティングします。 | 
| Route.ModelSelectionExpression | Route.RequestModels のキー | オプション。 非プロキシ統合に対して指定されている場合、モデル検証が発生します。 `$default` はキャッチオールとしてサポートされています。  | 同じルート内で動的にリクエスト検証を実行します。 | 
| Integration.TemplateSelectionExpression | Integration.RequestTemplates のキー |  オプション。 受信ペイロードを操作するための非プロキシ統合に提供できます。 `${request.body.jsonPath}` および静的な値がサポートされています。 `$default` はキャッチオールとしてサポートされています。  | リクエストの動的プロパティに基づいて、呼び出し元のリクエストを操作します。 | 
| Integration.IntegrationResponseSelectionExpression | IntegrationResponse.IntegrationResponseKey |  オプション。非プロキシ統合に提供される場合があります。 エラーメッセージのパターン一致 (Lambda から) またはステータスコード (HTTP 統合から) として動作します。 `$default` は、成功したレスポンスのキャッチオールとして動作する非プロキシ統合で必要です。  |  バックエンドからのレスポンスを操作します。 バックエンドの動的なレスポンスに基づいて発生するアクションを選択します (特定のエラーを明確に処理)。  | 
| IntegrationResponse.TemplateSelectionExpression | IntegrationResponse.ResponseTemplates のキー | オプション。非プロキシ統合に提供される場合があります。\$1default はサポートされています。  |  場合によっては、レスポンスの動的プロパティは、同じルートおよび関連する統合内で別の変換を指示します。 `${request.body.jsonPath}`、`${integration.response.statuscode}`、`${integration.response.header.headerName}`、`${integration.response.multivalueheader.headerName}`、および静的な値がサポートされています。 `$default` はキャッチオールとしてサポートされています。  | 
| Route.RouteResponseSelectionExpression | RouteResponse.RouteResponseKey |  WebSocket ルートの双方向通信を開始するために提供する必要があります。 現在、この値は `$default` のみに制限されています。  |  | 
| RouteResponse.ModelSelectionExpression | RouteResponse.RequestModels のキー | 現在サポートされていません。 |  | 