リアルタイム WebSocket クライアントの構築 - AWS AppSync

リアルタイム WebSocket クライアントの構築

GraphQLサブスクリプションの AWS AppSync リアルタイム WebSocket クライアント実装ガイド

次のシーケンス図と手順は、WebSocket クライアント、HTTP クライアント、および AWS AppSync サービス間のリアルタイムサブスクリプションワークフローを示しています。

  1. クライアントは、AWS AppSync リアルタイムエンドポイントと WebSocket 接続を確立します。ネットワークエラーが発生した場合、クライアントはジッターされたエクスポネンシャルバックオフを行う必要があります。詳細については、AWS アーキテクチャブログの「エクスポネンシャルバックオフとジッター」を参照してください。

  2. WebSocket 接続が正常に確立されると、クライアントは connection_init メッセージを送信します。

  3. クライアントは AWS AppSync からの connection_ack メッセージを待機します。このメッセージには、"ka"、キープアライブ、メッセージの最大待機時間 (ミリ秒) である connectiontTimeoutMs パラメータが含まれています。

  4. AWS AppSync は、キープアライブメッセージ、"ka"、を定期的に送信します。クライアントは、各 "ka" メッセージを受信した時間を追跡します。connectionTimeoutMs ミリ秒以内に "ka" メッセージが受信されない場合、クライアントは接続を終了する必要があります。

  5. クライアントは、start サブスクリプションメッセージを送信してサブスクリプションを登録します。単一の WebSocket 接続では、異なる認証モードであっても、複数のサブスクリプションがサポートされます。

  6. クライアントは、AWS AppSync が start_ack メッセージを送信するのを待機して、サブスクリプションが正常に完了したことを確認します。エラーがある場合、AWS AppSync は "type": "error" メッセージを返します。

  7. クライアントはサブスクリプションイベントをリッスンします。これらは、対応するミューテーションが呼び出された後に送信されます。クエリとミューテーションは通常、https:// 経由で AWS AppSync GraphQLエンドポイントに送信されます。サブスクリプションは、セキュアな WebSocket (wss://) を使用して AWS AppSync リアルタイムエンドポイントを通過します。

  8. クライアントは、stop サブスクリプションメッセージを送信してサブスクリプションを登録解除します。

  9. すべてのサブスクリプションを登録解除した後、WebSocket を介して転送されるメッセージがないことを確認した後、クライアントは WebSocket 接続から切断できます。

WebSocket 接続を確立するためのハンドシェイクの詳細

AWS AppSync に接続し、成功したハンドシェイクを開始するには、WebSocket クライアントに以下が必要です。

  • AppSync リアルタイムエンドポイント

  • 以下のパラメータを含むクエリ文字列: header および payload:

    • header: AWS AppSync エンドポイントと認証に関連する情報が含まれます。これは、文字列化された JSON オブジェクトからエンコードされた base64 文字列です。JSON オブジェクトのコンテンツは、認証モードによって異なります。

    • payload: payload の Base64 でエンコードされた文字列。

これらの必要な詳細情報を使用して、WebSocket クライアントは、WebSocket プロトコルとして graphql-ws を使用して、クエリ文字列がある API リアルタイムエンドポイントを含む URL に接続できます。

AWS AppSync GraphQL エンドポイントからの AWS AppSync リアルタイムエンドポイントの検出

AWS AppSync GraphQL エンドポイントと AWS AppSync リアルタイムエンドポイントは、プロトコルとドメインが多少異なります。AWS CLI コマンド aws appsync get-graphql-api を使用して AWS AppSync GraphQL エンドポイントを取得できます。

AWS AppSync GraphQL エンドポイント:

https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql

AWS AppSync リアルタイムエンドポイント:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql

アプリケーションは、クエリとミューテーションに任意の HTTP クライアントを使用して、AWS AppSync GraphQL エンドポイント (https://) に接続することができます。アプリケーションは、サブスクリプション用の任意の WebSocket クライアントを使用して、AWS AppSync リアルタイムエンドポイント (wss://) に接続できます。

AWS AppSync API 認証モードに基づくヘッダーパラメータフォーマット

接続クエリ文字列で使用される header オブジェクトの形式は、AWS AppSync API 認証モードによって異なります。オブジェクト内の host フィールドは、wss:// 呼び出しがリアルタイムエンドポイントに対して行われた場合でも、接続の検証に使用される AWS AppSync GraphQL エンドポイントを参照します。ハンドシェイクを開始し、許可された接続を確立するには、payload が空の JSON オブジェクトである必要があります。

API キー

ヘッダーの内容:

  • "host": <string>: これは AWS AppSync GraphQL エンドポイントのホストです。

  • "x-api-key": <string>: API 用に設定された AWS AppSync API キー。

例:

{ "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com", "x-api-key":"da2-12345678901234567890123456" }

ペイロードの内容:

{}

リクエストの URL:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJob3N0IjoiZXhhbXBsZTEyMzQ1Njc4OTAwMDAuYXBwc3luYy1hcGkudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20iLCJ4LWFtei1kYXRlIjoiMjAyMDA0MDFUMDAxMDEwWiIsIngtYXBpLWtleSI6ImRhMi16NHc0NHZoczV6Z2MzZHRqNXNranJsbGxqaSJ9&payload=e30=

Amazon Cognito ユーザープールと OpenID 接続 (OIDC)

ヘッダーの内容:

  • "Authorization": <string>: JWT アクセストークン。

  • "host": <string>: これは AWS AppSync GraphQL エンドポイントのホストです。

例:

{ "Authorization":"eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJHWEFLSXBieU5WNHhsQjEXAMPLEnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyEXAMPLEiJhNmNmMjcwNy0xNjgxLTQ1NDItOWYxOC1lNjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImVkMzM5MmNkLWNjYTMtNGM2OC1hNDYyLTJlZGI3ZTNmY2FjZiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk0NTc3MTgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl83OHY0SVZibVAiLCJleHAiOjE1Njk0NjEzMjAsImlhdCI6MTU2OTQ1NzcyMCwianRpIjoiNTgzZjhmYmMtMzk2MS00YzA4LWJhZTAtYzQyY2IxMTM5NDY5IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1N3RoZWw0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3EXAMPLEn0.B4EXAMPLEFNpJ6ikVp7e6DRee95V6Qi-zEE2DJH7sHOl2zxYi7f-SmEGoh2AD8emxQRYajByz-rE4Jh0QOymN2Ys-ZIkMpVBTPgu-TMWDyOHhDUmUj2OP82yeZ3wlZAtr_gM4LzjXUXmI_K2yGjuXfXTaa1mvQEBG0mQfVd7SfwXB-jcv4RYVi6j25qgow9Ew52ufurPqaK-3WAKG32KpV8J4-Wejq8t0c-yA7sb8EnB551b7TU93uKRiVVK3E55Nk5ADPoam_WYE45i3s5qVAP_-InW75NUoOCGTsS8YWMfb6ecHYJ-1j-bzA27zaT9VjctXn9byNFZmEXAMPLExw", "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com" }

ペイロードの内容:

{}

リクエストの URL:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=

IAM

ヘッダーの内容には以下のものがあります。

  • "accept": "application/json, text/javascript": 定数 <string> パラメータ。

  • "content-encoding": "amz-1.0": 定数 <string> パラメータ。

  • "content-type": "application/json; charset=UTF-8": 定数 <string> パラメータ。

  • "host": <string>: これは AWS AppSync GraphQL エンドポイントのホストです。- "x-amz-date": <string>: タイムスタンプは UTC で、YYYYMMDD’T’HHMMSS’Z’ の ISO 8601 形式である必要があります。たとえば、20150830T123600Z は有効なタイムスタンプです。タイムスタンプにミリ秒を含めないでください。詳細については、AWS 全般のリファレンスの「署名バージョン 4 の日付の処理」を参照してください。

    • "X-Amz-Security-Token": <string>: 一時的なセキュリティ認証情報を使用する場合に必要になる、AWS セッショントークン。詳細については、次を参照してください。 |IAMlong| ユーザーガイド. - "Authorization": <string>: SigV4 signing information for the AWS AppSync endpoint。署名プロセスの詳細については、AWS 全般のリファレンスの「タスク 4: HTTP リクエストに署名を追加する」を参照してください。

SigV4 署名の HTTP リクエストには、正規の URL が含まれています。これは AWS AppSync GraphQL エンドポイントに /connect が追加されたものです。サービスエンドポイント AWS リージョンは、AWS AppSync API を使用しているリージョンと同じで、サービス名は「appsync」です。署名する HTTP リクエストは次のとおりです。

{ url: "https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql/connect", data: "{}", method: "POST", headers: { "accept": "application/json, text/javascript", "content-encoding": "amz-1.0", "content-type": "application/json; charset=UTF-8", } }

例:

{ "accept": "application/json, text/javascript", "content-encoding": "amz-1.0", "content-type": "application/json; charset=UTF-8", "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com", "x-amz-date": "20200401T001010Z", "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==", "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=83EXAMPLEbcc1fe3ee69f75cd5ebbf4cb4f150e4f99cec869f149c5EXAMPLEdc" }

ペイロードの内容:

{}

リクエストの URL:

wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyEXAMPLEHQiOiJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFEXAMPLEQiLCJjb250ZW50LWVuY29kaW5nIjoEXAMPLEEuMCIsImNvbnRlbnQtdHlwZSI6ImFwcGxpY2F0aW9EXAMPLE47IGNoYXJzZXQ9VVRGLTgiLCJob3N0IjoiZXhhbXBsZEXAMPLENjc4OTAwMDAuYXBwc3luYy1hcGkudXMtZWFzdC0xLmFtYEXAMPLEcy5jb20iLCJ4LWFtei1kYXRlIjoiMjAyMDA0MDFUMDAxMDEwWiIsIlgtEXAMPLElY3VyaXR5LVRva2VuIjoiQWdvSmIzSnBaMmx1WDJWakVBb2FEbUZ3TFhOdmRYUm9aV0Z6ZEMweUlrY3dSUUlnQWg5N0NsanE3d09QTDhLc3hQM1l0RHV5Yy85aEFqOFBoSjdGdmYzOFNnb0NJUURoSllKYkpsbmpQc3Bpb096dGorK3BFYWdXQ3ZlWlVqS0VuMHp5VWhCbXhpck5CUWpqLy8vLy8vLy8vLzhCRUFBYUREY3hPRGsyTkRneU56ZzFOU0lNbzFtV25wRVNXVW9ZdzRCa0txRUZTcm0zRFh1TDh3K1piVmM0SktqRFA0dlVDS05SNkxlOUM5cFpwOVBzVzBOb0Z5M3ZMQlVkQVh3dDZQSld1T1ZHOGZlWGZpRUVBKzFraGdGSy93RXR3Uis5ekY3TmFNTU1zZTA3d04yZ0cydEgwZUtNVFhuOEF3QVFYK3NNYnl0UW84aWVwUDlQWk96bFpzU0ZiL2RQNVE4aGs2WWpHVGFMMWVZY0tac1RrREFxMnVLRlE4bVlVVkE5RXRRbk5SaUZMRVk4M2FLdkcvdHFMV05uR2xTTlZ4N1NNY2ZvdmtGRHFRYW1tKzg4eTFPd3dBRVlLN3Fjb2NlWDZaN0dHY2FZdUlmR3BhWDJNQ0NFTGVRdlorOFd4RWdPbklmejdHWXZzWU5qTFpTYVJuVjRHK0lMWTFGMFFOVzY0UzlOdmorQndEZzNodDJDck52cHdqVllsajlVM25teEUwVUc1bmU4M0xMNWhocU1wbTI1a21MN2VuVmd3MmtRem1VMmlkNElLdTBDL1dhb0RSdU8yRjV6RTYzdkpieE44QVlzNzMzOCs0QjRIQmI2Qlo2T1VnZzk2UTE1UkE0MS9nSXF4YVZQeHlUcERmVFU1R2ZTTHhvY2RZZW5pcXFwRk10WkcybjlkMHU3R3NRTmNGa05jRzNxRFptNHREbzh0WmJ1eW0wYTJWY0YyRTVoRkVnWEJhK1hMSkNmWGkvNzdPcUFFalAweDdRZGszQjQzcDhLRy9CYWlvUDVSc1Y4ekJHdkgxekFneVBoYTJyTjcwL3RUMTN5cm1QZDVRWUVmd3pleGpLclY0bVdJdVJnOE5USFlTWkpVYWV5Q3dUb204MFZGVUpYRytHWVRVeXY1VzIyYUJjbm9SR2lDaUtFWVRMT2tnWGVjZEtGVEhtY0lBZWpROVdlbHIwYTE5NktxODd3NUtOTUNrY0NHRm53Qk5GTG1mbmJwTnFUNnJVQnh4czNYNW50WDlkOEhWdFNZSU5Uc0dYWE1aQ0o3Zm5iV2FqaGcvYW94MEZ0SFgyMWVGNnFJR1Q4ajF6K2wyb3BVK2dnd1Vna2hVVWdDSDJUZnFCaitNTE1WVnZwZ3FKc1BLdDU4MmNhRktBcklGSXZPKzlRdXB4TG5FSDJoejA0VE1UZm5VNmJRQzZ6MWJ1VmU3aCt0T0xuaDFZUEZzTFE4OGFuaWIvN1RUQzhrOURzQlRxMEFTZThSMkdiU0VzbU85cWJiTXdnRWFZVWhPS3RHZXlRc1NKZGhTazZYeFhUaHJXTDlFbndCQ1hEa0lDTXFkbnRBeHl5TTluV3NaNGJMOUpIcUV4Z1dVbWZXQ2h6UEZBcW4zRjR5ODk2VXFIVFp4bHEzV0d5cG41SEhjZW0ySHFmM0lWeEtIMWluaHFkVnRrcnlFaVRXckk3WmRqYnFucVJibCtXZ3RQdEtPT3dlRGxDYVJzM1IycVhjYk5nVmhsZU1rNElXbkY4RDE2OTVBZW5VMUx3SGpPSkxrQ2p4Z05GaVdBRkVQSDlhTklhcXMvWnhBPT0iLCJBdXRob3JpemF0aW9uIjoiQVdTNC1ITUFDLVNIQTI1NiBDcmVkZW50aWFsPVhYWFhYWFhYWFhYWFhYWFhYWFgvMjAxOTEwMDIvdXMtZWFzdC0xEXAMPLE5bmMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWFjY2VwdDtjb250ZWEXAMPLE29kaW5nO2NvbnRlbnQtdHlwZTtob3EXAMPLEW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT04MzE4EXAMPLEiY2MxZmUzZWU2OWY3NWNkEXAMPLE0Y2I0ZjE1MGU0Zjk5Y2VjODY5ZjE0OWM1ZDAzNDEXAMPLEn0=&payload=e30=

: 1 つの WebSocket 接続には、(異なる認証モードであっても) 複数のサブスクリプションを設定できます。これを実装する 1 つの方法は、最初のサブスクリプション用の WebSocket 接続を作成し、最後のサブスクリプションが登録解除されたときにそれを閉じることです。これは、最後のサブスクリプションが登録解除された直後にアプリケーションがサブスクライブされた場合に備えて、WebSocket 接続を閉じる前に数秒待つことで最適化できます。モバイルアプリの例では、ある画面から別の画面に変更するとき、アンマウントイベントでは、サブスクリプションを停止し、マウントイベントでは、別のサブスクリプションを開始します。

リアルタイム WebSocket オペレーション

AWS AppSync で成功した WebSocket ハンドシェイクを開始した後、クライアントは、異なるオペレーションのための AWS AppSync への接続ステップを完了するために、後続のメッセージを送信する必要があります。これらのメッセージには、次のデータが必要です。

  • type: 操作のタイプ。

  • id: サブスクリプションの一意の識別子。この目的のために UUID を使用することをお勧めします。

  • payload: オペレーションタイプに応じて、関連付けられたペイロード。

type フィールドのみが必須フィールドで、idpayload はオプションです。

イベントのシーケンス

サブスクリプションリクエストを正常に開始、確立、登録、および処理するには、クライアントは次のシーケンスを実行する必要があります。

  1. 接続の初期化 (connection_init)

  2. 接続確認応答 (connection_ack)

  3. サブスクリプション登録 (start)

  4. サブスクリプション確認応答 (start_ack)

  5. サブスクリプションの処理 (data)

  6. サブスクリプションの登録解除 (stop)

接続初期化メッセージ

ハンドシェイクが成功した後、クライアントは connection_init メッセージを送信して、AWS AppSync リアルタイムエンドポイントとの通信を開始する必要があります。この手順を行わないと、他のすべてのメッセージは無視されます。メッセージは、以下の JSON オブジェクトを次のように文字列化することによって得られる文字列です。

{ "type": "connection_init" }

接続確認メッセージ

connection_init メッセージを送信した後、クライアントは connection_ack メッセージを待つ必要があります。connection_ack 受信前に送信されたメッセージはすべて無視されます。メッセージは次のように表示されるはずです。

{ "type": "connection_ack", "payload": { // Time in milliseconds waiting for ka message before the client should terminate the WebSocket connection "connectionTimeout": 300000 } }

キープアライブメッセージ

接続確認メッセージに加えて、クライアントは定期的にキープアライブメッセージを受信します。接続タイムアウト期間内にキープアライブメッセージが受信されない場合、クライアントは接続を終了する必要があります。AWS AppSync は、接続を自動的にシャットダウンするまで (24 時間後)、これらのメッセージを送信し、登録済みサブスクリプションを処理し続けます。キープアライブメッセージはハートビートであり、クライアントによる確認は不要です。

{ "type": "ka" }

サブスクリプション登録メッセージ

クライアントが connection_ack メッセージを受信した後、サブスクリプション登録メッセージを AWS AppSync に送信できます。このメッセージは、以下のフィールドを含む文字列化された JSON オブジェクトです。

  • "id": <string>: サブスクリプションの ID。この id はサブスクリプションごとに一意である必要があります。そうしないと、サーバーはサブスクリプション id が重複していることを示すエラーを返します。

  • "type": "start": 定数 <string> パラメータ。

  • "payload": <Object>: サブスクリプションに関連する情報が含まれています。

    • "data": <string>: GraphQL クエリと変数を含む文字列化された JSON オブジェクト。

      • "query": <string>: GraphQL オペレーション。

      • "variables": <Object>: クエリの変数を格納します。

    • "extensions": <Object>: 認証オブジェクトが含まれています。

  • "authorization": <Object>: 認証に必要なフィールドが含まれます。

サブスクリプション登録の認証オブジェクト

また、 セクションにある同じルールが認証オブジェクトに適用されます。唯一の例外は IAM で、SigV4 署名情報がわずかに異なります。詳細については、IAM の例を参照してください。

Amazon Cognito ユーザープールの使用例:

{ "id": "ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69", "payload": { "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}", "extensions": { "authorization": { "Authorization": "eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJEXAMPLEBieU5WNHhsQjhPVW9YMnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyJzdWIiOiJhNmNmMjcwNy0xNjgxLTQ1NDItEXAMPLENjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImU3YWVmMzEyLWUEXAMPLEY0Zi04YjlhLTRjMWY5M2Q5ZTQ2OCIsInRva2VuX3VzZSI6ImFjY2VzcyIsIEXAMPLEIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk2MTgzMzgsImlzcyI6Imh0dEXAMPLEXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zbEXAMPLEc3QtMl83OHY0SVZibVAiLCJleHAiOjE1NzAyNTQ3NTUsImlhdCI6MTU3MDI1MTE1NSwianRpIjoiMmIEXAMPLEktZTVkMi00ZDhkLWJiYjItNjA0YWI4MDEwOTg3IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1EXAMPLE0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3J6YWZlIn0.CT-qTCtrYeboUJ4luRSTPXaNewNeEXAMPLE14C6sfg05tO0fOMpiUwj9k19gtNCCMqoSsjtQoUweFnH4JYa5EXAMPLEVxOyQEQ4G7jQrt5Ks6STn53vuseR3zRW9snWgwz7t3ZmQU-RWvW7yQU3sNQRLEXAMPLEcd0yufBiCYs3dfQxTTdvR1B6Wz6CD78lfNeKqfzzUn2beMoup2h6EXAMPLE4ow8cUPUPvG0DzRtHNMbWskjPanu7OuoZ8iFO_Eot9kTtAlVKYoNbWkZhkD8dxutyoU4RSH5JoLAnrGF5c8iKgv0B2dfEXAMPLEIihxaZVJ9w9w48S4EXAMPLEcA", "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com" } } }, "type": "start" }

IAM の使用例:

{ "id": "eEXAMPLE-cf23-1234-5678-152EXAMPLE69", "payload": { "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}", "extensions": { "authorization": { "accept": "application/json, text/javascript", "content-type": "application/json; charset=UTF-8", "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==", "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=b90131a61a7c4318e1c35ead5dbfdeb46339a7585bbdbeceeaff51f4022eb1fd", "content-encoding": "amz-1.0", "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com", "x-amz-date": "20200401T001010Z" } } }, "type": "start" }

SigV4 署名は、URL に /connect を追加する必要がなく、data は JSON 文字列化された GraphQL オペレーションに置き換えられます。次に、SigV4 署名リクエストの例を示します。

{ url: "https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql", data: "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}", method: "POST", headers: { "accept": "application/json, text/javascript", "content-encoding": "amz-1.0", "content-type": "application/json; charset=UTF-8", } }

サブスクリプション確認メッセージ

サブスクリプション開始メッセージを送信した後、クライアントは AWS AppSync が start_ack メッセージを送信するのを待機する必要があります。start_ack は、サブスクリプションが正常に完了したことを示します。メッセージは次の文字列です。

サブスクリプションの成功例:

{ "type": "start_ack", "id": "eEXAMPLE-cf23-1234-5678-152EXAMPLE69" }

エラーメッセージ

接続の初期化またはサブスクリプションの登録が失敗した場合、またはサブスクリプションがサーバーから終了された場合、サーバーは次のエラーメッセージをクライアントに送信します。

  • "type": "error": 定数 <string> パラメータ。

  • "id": <string>: 対応する登録済みサブスクリプションの id (該当する場合)。

  • "payload" <Object>: このオブジェクトには、対応するエラー情報が含まれています。

例:

{ "type": "error", "payload": { "errors": [ { "errorType": "LimitExceededError", "message": "Rate limit exceeded" } ] } }

データメッセージの処理

クライアントがミューテーションを送信すると、AWS AppSync は、それに関心を持つすべてのサブスクライバーを識別し、"start" サブスクリプションオペレーションで使用される対応するサブスクリプション id を使用して、各サブスクライバーに "type":"data" メッセージを送信します。クライアントは、データメッセージを受信したときに、対応するサブスクリプションと照合できるように、送信するサブスクリプション id を追跡する必要があります。

  • "type": "data": 定数 <string> パラメータ。

  • "id": <string>: 対応する登録済みサブスクリプションの id

  • "payload" <Object>: このオブジェクトには、サブスクリプション情報を持つデータオブジェクトが含まれています。

例:

{ "type": "data", "id": "ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69", "payload": { "data": { "onCreateMessage": { "__typename": "Message", "message": "test" } } } }

サブスクリプションの登録解除メッセージ

アプリがサブスクリプションイベントのリッスンを停止する場合、クライアントは次の文字列化された JSON オブジェクトを含むメッセージを送信する必要があります。

  • "type": "stop": 定数 <string> パラメータ。

  • "id": <string>: 登録解除されるサブスクリプションの id

例:

{ "type":"stop", "id":"ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69" }

AWS AppSync は、次の文字列化された JSON オブジェクトを含む確認メッセージを送り返します。

  • "type": "complete": 定数 <string> パラメータ。

  • "id": <string>: 未登録のサブスクリプションの ID。

メッセージの受信後、この特定のサブスクリプションに対するメッセージは送信されません。

例:

{ "type":"complete", "id":"eEXAMPLE-cf23-1234-5678-152EXAMPLE69" }

WebSocket の切断

切断する前に、クライアントは、データ損失を避けるために、WebSocket 接続を介して現在オペレーションが行われていないことを確認するために必要なロジックを持っている必要があります。WebSocket から切断する前に、すべてのサブスクリプションを登録解除する必要があります。