這是一個演示和示例應用程序,旨在成為一個簡單的基於網絡的多用戶聊天系統。
它提供持久的群組聊天、用戶之間的私人聊天、用戶列表、空閒(遠離鍵盤)檢測和其他一些功能。
它基於多種 Azure 技術構建,包括: Web PubSub、靜態 Web 應用程式和表格存儲
??筆記。這是一個個人項目,旨在幫助學習,同時建立一些有趣的東西。該代碼附帶了您可能期望從此類項目中獲得的所有警告。
目標:
用例和主要特性:
這是最終用戶透過瀏覽器使用的主要 Web 前端。
其原始碼位於client/中,由靜態獨立的純 ES6 JS 應用程式組成,不需要捆綁或 Node.js。它是使用 Vue.js 作為支撐框架、Bulma 作為 CSS 框架編寫的。
一些注意事項:
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 表格式儲存體以保存群組聊天和使用者資料(選擇表格儲存是因為它簡單且便宜)。它不是託管在獨立的 Azure Function App 中,而是部署到靜態 Web 應用程式中,作為其無伺服器 API 支援的一部分
有四個 HTTP 函數,全部由預設的/api/
路徑提供
eventHandler
- 從 Azure Web PubSub 服務發送的「上游」事件的 Webhook 接收器,包含大部分應用程式邏輯。不由客戶端直接調用,僅由 Azure WebPub Sub 呼叫。getToken
- 由用戶端呼叫以取得存取權杖和 URL,以透過 WebSocket 連線至 Azure Web PubSub 服務。必須在 URL 查詢中使用 userId 進行調用,例如 GET /api/getToken?userId={user}
getUsers
- 傳回登入使用者的列表,請注意此函數的路徑是/api/users
getChats
- 傳回活動群聊的列表,請注意此函數的路徑是/api/chats
狀態由state.js
處理,state.js 是一個 ES6 模組,匯出支援使用者和聊天狀態 CRUD 的函數。此模組執行與Azure Tables的所有交互,並提供相對透明的接口,因此可以換入不同的儲存後端。
透過 Azure Web PubSub 和事件處理程序,客戶端和伺服器之間有兩種方式的訊息流
使用 json.webpubsub.azure.v1 子協定而不是基本的 WebSocket,這提供了許多功能:可以將使用者新增至群組中,客戶端可以傳送自訂事件(使用type: event
),也可以直接向其他客戶端發送訊息無需透過伺服器(使用type: sendToGroup
)
筆記:
事件和聊天使用json.webpubsub.azure.v1子協定發送
從客戶端發送的聊天訊息使用sendToGroup
和自訂 JSON 有效負載,其中包含三個欄位message
、 fromUserId
和fromUserName
,這些訊息由 Azure Web PubSub 在客戶端之間中繼,伺服器永遠不會收到通知:
{
type : 's endToGroup ',
group : < chatId > ,
dataType : 'j son ',
data : {
message : < message text > ,
fromUserId : < userId > ,
fromUserName : < userName > ,
},
}
發送到後端伺服器的事件會作為 WebSocket 訊息從客戶端透過與event
類型相同的子協定和應用程式特定的子類型發送,例如
{
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
綁定。為了將訊息傳回 Web PubSub,伺服器 SDK 可以簡單地在函數程式碼中使用,而不是使用webPubSub
輸出綁定。Azure 表中的狀態由兩個名為chats
和users
表(集合)組成
由於每個聊天都在 Members 欄位內包含嵌套對象,因此每個聊天都以 JSON 字串儲存在名為data
的欄位中。 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
應該使用部署/資料夾中找到的 Bicep 範本一步為您部署所有內容
有關詳細資訊和說明,請參閱部署資料夾中的自述文件
這是可能的,但需要一些努力,因為 Azure Web PubSub 服務需要能夠呼叫本機電腦上的 HTTP 終端點,因此使用了隧道。
在本地運行時,使用靜態 Web 應用 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