これは、シンプルなマルチユーザー Web ベースのチャット システムとして設計されたデモおよびサンプル アプリケーションです。
永続的なグループ チャット、ユーザー間のプライベート チャット、ユーザー リスト、アイドル状態 (キーボードから離れた状態) の検出、およびその他のいくつかの機能を提供します。
Web PubSub、静的 Web アプリ、テーブル ストレージなど、いくつかの Azure テクノロジーに基づいて構築されています。
??注記。これは個人的なプロジェクトとして作成され、興味深いものを構築しながら学習を支援するために作成されました。このコードには、このようなプロジェクトで予想されるすべての注意事項が含まれています。
目標:
ユースケースと主な機能:
これは、エンド ユーザーがブラウザ経由で使用するメインの Web フロントエンドです。
このソースはclient/にあり、静的なスタンドアロンの純粋な ES6 JS アプリケーションで構成されており、バンドルや Node.js は必要ありません。これは、サポート フレームワークとして Vue.js を使用し、CSS フレームワークとして Bulma を使用して書かれています。
いくつかのメモ:
client/js/app.js
このアプローチを使用して子コンポーネントを含む Vue.js アプリを作成する方法を示しています。クライアント ロジックの大部分はここにあります。client/js/components/chat.js
は、アプリケーション内の各チャット タブをホストするために使用される Vue.js コンポーネントです。.auth/
エンドポイントは、ユーザーをサインインし、userId などのユーザーの詳細を取得するために使用されます。これはバックエンドであり、Azure Web PubSub との間で WebSocket イベントを処理し、一部の操作に REST API を提供します。
このソースはapi/にあり、Node.js Azure Function App で構成されています。 Azure Table Storage に接続して、グループ チャットとユーザー データを保持します (Table Storage は、シンプルで安価であるため選択されました)。これはスタンドアロンの Azure Function App でホストされず、サーバーレス API サポートの一部として静的 Web アプリにデプロイされます。
HTTP 関数は 4 つあり、すべてデフォルトの/api/
パスから提供されます。
eventHandler
- Azure Web PubSub サービスから送信される「アップストリーム」イベントの Webhook レシーバーには、アプリケーション ロジックの大部分が含まれています。クライアントによって直接呼び出されるのではなく、Azure WebPub Sub のみが呼び出されます。getToken
- WebSocket 経由で Azure Web PubSub サービスに接続するためのアクセス トークンと URL を取得するためにクライアントによって呼び出されます。 URL クエリで userId を使用して呼び出す必要があります。例: GET /api/getToken?userId={user}
getUsers
- サインインしているユーザーのリストを返します。この関数のルートは/api/users
であることに注意してください。getChats
- アクティブなグループ チャットのリストを返します。この関数のルートは/api/chats
であることに注意してください。状態は、ユーザーとチャットの状態 CRUD をサポートする関数をエクスポートする ES6 モジュールであるstate.js
で処理されます。このモジュールは、Azure Tables とのすべての対話を実行し、比較的透過的なインターフェイスを提供するため、別のストレージ バックエンドを交換できます。
クライアントとサーバーの間には、Azure Web PubSub およびイベント ハンドラーを介した双方向のメッセージ フローがあります。
基本的な WebSocket ではなく json.webpubsub.azure.v1 サブプロトコルが使用され、これにより多くの機能が提供されます。ユーザーをグループに追加でき、クライアントはカスタム イベントを送信でき ( type: event
を使用)、他のクライアントにメッセージを直接送信することもできます。サーバーを経由せずに ( type: sendToGroup
使用)
注:
イベントとチャットはjson.webpubsub.azure.v1サブプロトコルを使用して送信されます
クライアントから送信されるチャット メッセージは、 sendToGroup
と、 message
、 fromUserId
、 fromUserName
の 3 つのフィールドを持つカスタム JSON ペイロードを使用します。これらのメッセージは、Azure Web PubSub によってクライアント間で中継され、サーバーには通知されません。
{
type : 's endToGroup ',
group : < chatId > ,
dataType : 'j son ',
data : {
message : < message text > ,
fromUserId : < userId > ,
fromUserName : < userName > ,
},
}
バックエンド サーバー宛てのイベントは、 event
タイプとアプリケーション固有のサブタイプを持つ同じサブプロトコルを介してクライアントから WebSocket メッセージとして送信されます。
{
type : 'e vent ',
event : 'j oinChat ',
dataType : 't ext ',
data : < chatId > ,
}
イベントの種類は次のとおりです。
バックエンド API のeventHandler
関数には、これらの各ユーザー イベントのケースと、接続および切断のシステム イベントのハンドラーが含まれています。
サーバーから送信されるメッセージには、次のようなカスタム Chatr アプリ固有のペイロードが含まれます。
{
chatEvent : < eventType > ,
data : < JSON object type dependant >
}
ここで、 eventType
次のいずれかです。
client/js/app.js
のクライアント コードは、クライアントが受信したこれらのメッセージを処理し、それに応じて反応します。
このプロジェクトの計画は、 Azure Web PubSubとAzure Static Web Apps を使用し、静的 Web Apps API サポート (実際には内部ではAzure Functions ) のサーバーレス関数のセットとしてサーバー側コンポーネントをホストすることでした。 Azure Static Web Appsが選択された理由は、コードレスおよび構成不要のユーザー サインインと認証に対する優れたサポートがあり、これを活用したいと考えていたためです。
このアプローチに関するコメントは次のとおりです。
webPubSubConnection
バインディングを使用する代わりに、Webhook イベント ハンドラーとして機能する標準 HTTP 関数を作成できます。 Web PubSub にメッセージを送り返すには、 webPubSub
出力バインディングを使用するのではなく、関数コード内でサーバー SDK を単純に使用できます。Azure Tables の状態は、 chats
とusers
という名前の 2 つのテーブル (コレクション) で構成されます
各チャットには members フィールド内にネストされたオブジェクトが含まれているため、各チャットはdata
と呼ばれるフィールドに JSON 文字列として保存されます。 PartitionKey は使用されず、文字列「chatr」にハードコーディングされます。データ オブジェクト内の RowKey と id フィールドは同じです。
チャットデータエンティティの例
{
"id" : " eab4b030-1a3d-499a-bd89-191578395910 " ,
"name" : " This is a group chat " ,
"members" : {
"0987654321" : {
"userId" : " 0987654321 " ,
"userName" : " Another Guy "
},
"1234567890" : {
"userId" : " 1234567890 " ,
"userName" : " Ben "
}
},
"owner" : " 1234567890 "
}
ユーザーは、以下で説明するフィールド (列) を持つエンティティとして保存されます。ネストされたフィールドがないため、JSON 文字列としてエンコードする必要はありません。ここでも PartitionKey は使用されず、文字列「chatr」にハードコードされています。
userId
フィールドtwitter
、 aad
、またはgithub
でサインインしたときに提供された認証メイクファイルを参照
$ make
help This help message
lint ? Lint & format, will not fix but sets exit code on error
lint-fix Lint & format, will try to fix errors and modify code
run ? Run server locally using Static Web Apps CLI
clean ? Clean up project
deploy Deploy everything to Azure using Bicep
tunnel ? Start loophole tunnel to expose localhost
コンポーネントの数とコンポーネント間の構成により、展開は少し複雑になります。 Makefile ターゲットのdeploy
deploy/フォルダーにある Bicep テンプレートを使用して、1 つのステップですべてをデプロイする必要があります。
詳細と手順については、展開フォルダーの Readme を参照してください。
これは可能ですが、Azure Web PubSub サービスがロケーション マシン上の HTTP エンドポイントを呼び出すことができる必要があるため、トンネルが使用されているため、少し手間がかかります。
ローカルで実行する場合は、静的 Web Apps CLI が使用され、これにより偽のユーザー認証エンドポイントが提供されます。
手順の概要は次のとおりです。
api/local.settings.sample.json
をapi/local.settings.json
にコピーし、必要な設定値を編集します。loophole http 7071 --hostname chatr
https://{{hostname-of-tunnel-service}}/api/eventHandler
入力しますmake run
http://localhost:4280/index.html
を開きます