AWS AppSync Eventsに接続する
このガイドでは、Amplifyライブラリを使用してAWS AppSync Eventsに接続する方法について説明します。
AWS AppSync Eventsを使用すると、接続やリソーススケーリングを管理することなく、数百万のサブスクライバーにリアルタイムイベントデータをブロードキャストできるセキュアで高性能なサーバーレスWebSocket APIを作成できます。この機能を使用すると、共同ドキュメントエディタ、チャットアプリ、ライブポーリングシステムなどの複数ユーザー機能を構築できます。
AWS AppSync Eventsの詳細については、デベロッパーガイドをご覧ください。
既存のAmplifyバックエンドなしでEvent APIに接続する
開始する前に、以下が必要です:
- AWSコンソールで作成されたEvent API
- メモを取ってください: HTTPエンドポイント、リージョン、APIキー
import type { EventsChannel } from 'aws-amplify/data';import { useState, useEffect, useRef } from 'react';import { Amplify } from 'aws-amplify';import { events } from 'aws-amplify/data';
Amplify.configure({ API: { Events: { endpoint: 'https://abcdefghijklmnopqrstuvwxyz.appsync-api.us-east-1.amazonaws.com/event', region: 'us-east-1', defaultAuthMode: 'apiKey', apiKey: 'da2-abcdefghijklmnopqrstuvwxyz', }, },});
export default function App() { const [myEvents, setMyEvents] = useState<unknown[]>([]);
const sub = useRef<ReturnType<EventsChannel['subscribe']>>(null);
useEffect(() => { let channel: EventsChannel;
const connectAndSubscribe = async () => { channel = await events.connect('default/channel');
if (!sub.current) { sub.current = channel.subscribe({ next: (data) => { console.log('received', data); setMyEvents((prev) => [data, ...prev]); }, error: (err) => console.error('error', err), }); } };
connectAndSubscribe();
return () => { sub.current?.unsubscribe(); sub.current = null; return channel?.close(); }; }, []);
async function publishEvent() { // HTTP POSTでパブリッシュします await events.post('default/channel', { some: 'data' });
// または、WebSocketチャネル経由でイベントをパブリッシュします const channel = await events.connect('default/channel'); await channel.publish({ some: 'data' }); }
return ( <> <button onClick={publishEvent}>Publish Event</button> <ul> {myEvents.map((data, idx) => ( <li key={idx}>{JSON.stringify(data.event, null, 2)}</li> ))} </ul> </> );}既存のAmplifyバックエンドにEvent APIを追加する
このガイドでは、既存のAmplifyバックエンドにEvent APIを追加する方法について説明します。フロントエンドアプリケーションからEvent APIで認証するためにCognito User Poolsを使用します。サインインしているユーザーはEvent APIをサブスクライブしてイベントをパブリッシュできます。
開始する前に、以下が必要です:
- 既存のAmplifyバックエンド(クイックスタートを参照)
@aws-amplify/backendと@aws-amplify/backend-cliの最新バージョン(npm add @aws-amplify/backend@latest @aws-amplify/backend-cli@latest)
バックエンド定義の更新
まず、バックエンド定義に新しいEvent APIを追加します。
import { defineBackend } from '@aws-amplify/backend';import { auth } from './auth/resource';// CDKリソースをインポートします:import { CfnApi, CfnChannelNamespace, AuthorizationType,} from 'aws-cdk-lib/aws-appsync';import { Policy, PolicyStatement } from 'aws-cdk-lib/aws-iam';
const backend = defineBackend({ auth,});
// Event APIリソースの新しいスタックを作成します:const customResources = backend.createStack('custom-resources');
// スタックに新しいEvent APIを追加します:const cfnEventAPI = new CfnApi(customResources, 'CfnEventAPI', { name: 'my-event-api', eventConfig: { authProviders: [ { authType: AuthorizationType.USER_POOL, cognitoConfig: { awsRegion: customResources.region, // Event APIをAmplifyによってプロビジョンされたCognito User Poolを使用するように設定します: userPoolId: backend.auth.resources.userPool.userPoolId, }, }, ], // Connect、Publish、および Subscribe操作の認可プロバイダーとしてUser Poolを設定します: connectionAuthModes: [{ authType: AuthorizationType.USER_POOL }], defaultPublishAuthModes: [{ authType: AuthorizationType.USER_POOL }], defaultSubscribeAuthModes: [{ authType: AuthorizationType.USER_POOL }], },});
// Event APIのデフォルトネームスペースを作成します:const namespace = new CfnChannelNamespace( customResources, 'CfnEventAPINamespace', { apiId: cfnEventAPI.attrApiId, name: 'default', });
// User Pool内の認証されたユーザーロールにポリシーをアタッチしてEvent APIへのアクセスを許可します:backend.auth.resources.authenticatedUserIamRole.attachInlinePolicy( new Policy(customResources, 'AppSyncEventPolicy', { statements: [ new PolicyStatement({ actions: [ 'appsync:EventConnect', 'appsync:EventSubscribe', 'appsync:EventPublish', ], resources: [`${cfnEventAPI.attrApiArn}/*`, `${cfnEventAPI.attrApiArn}`], }), ], }));
// 最後に、Event API設定をamplify_outputsに追加します:backend.addOutput({ custom: { events: { url: `https://${cfnEventAPI.getAtt('Dns.Http').toString()}/event`, aws_region: customResources.region, default_authorization_type: AuthorizationType.USER_POOL, }, },});バックエンドのデプロイ
変更をテストするには、Amplify Sandboxをデプロイします。
npx ampx sandboxフロントエンドアプリケーションの接続
サンドボックスがデプロイされた後、フロントエンドアプリケーションをEvent APIに接続します。Amplify認証器コンポーネントを使用してCognito User Poolにサインインします。
認証器をまだインストールしていない場合は、npm add @aws-amplify/ui-reactを実行してインストールできます。
import { useEffect, useState } from 'react';import { Amplify } from 'aws-amplify';import { events, type EventsChannel } from 'aws-amplify/data';import { Authenticator } from '@aws-amplify/ui-react';import '@aws-amplify/ui-react/styles.css';import outputs from '../amplify_outputs.json';
Amplify.configure(outputs);
export default function App() { const [myEvents, setMyEvents] = useState<Record<string, any>[]>([]);
useEffect(() => { let channel: EventsChannel;
const connectAndSubscribe = async () => { channel = await events.connect('default/channel');
channel.subscribe({ next: (data) => { console.log('received', data); setMyEvents((prev) => [data, ...prev]); }, error: (err) => console.error('error', err), }); };
connectAndSubscribe();
return () => channel && channel.close(); }, []);
async function publishEvent() { // HTTP POSTでパブリッシュします await events.post('default/channel', { some: 'data' });
// または、WebSocketチャネル経由でイベントをパブリッシュします const channel = await events.connect('default/channel'); await channel.publish({ some: 'data' }); }
return ( <Authenticator> {({ signOut, user }) => ( <> <div> <h1>ようこそ、{user.username}さん</h1> <button onClick={signOut}>Sign Out</button> </div> <div> <button onClick={publishEvent}>Publish Event</button> <ul> {myEvents.map((data) => ( <li key={data.id}>{JSON.stringify(data.event)}</li> ))} </ul> </div> </> )} </Authenticator> );}